Circumventing design pattern hell with customized Xcode templates
Application development is a continuous process wherein each developer analyse, design and write their style of code. If we don't iterate upon the design patterns and allow the developers to choose, we would quickly end up with the design pattern hell.
The design pattern hell has three characteristics:
- Multiple Design Patterns: Too many different design patterns for similar problems. This easily becomes a bottleneck as the team grows, and if we do not find a common design pattern.
- Deviation from the Design Pattern: It takes years of practice to code in a particular design pattern, and there are known cases where the developers deviate from the original design pattern.
- No design pattern: There are certain cases where the developers might end up writing the code without following any design pattern, or as a result of (2) it would be not easy to see any particular design pattern being followed.
There are useful built-in templates which are already bundled with the Xcode. However, these templates don't suffice for the enterprise. The team often end up adding the custom templates which are tailored to their needs. Xcode templates can be used to address the above problems we face with the design pattern, which in turn speeds up the development process.
Before we begin, let's iterate on the different layers which we identified to create the Xcode templates.
- View Layer: Collection of classes derived from UIKit/SwiftUI framework along with related view logic
- Domain Layer: Collection of entity objects and related business logic which represents your enterprise business model.
- Data Layer: Collection of entity objects, mapping logic along with providing access to filesystem and/or database.
- Infrastructure Layer: Enables interaction with external systems by receiving, storing and providing data when requested.
At Halodoc, we use MVVM as mobile architecture. In MVVM architecture, we don't talk about how the model is being populated. This gives an open-ended problem on how to populate the model. To address this, we researched many different design patterns which would help us to define the boundaries based on these layers. Repository Pattern stood out being able to clearly define the boundaries which we have defined earlier.
Using the above layers, we identified that we need 3 types of Xcode templates:
- Feature Template - Contains the whole MVVM component package which contains all the components. Useful for introducing new code.
- Repository Template - Contains the domain, data and infrastructure components. Useful for refactoring the existing code.
- ViewController Template - Contains the View Components. Useful for refactoring or creating static views with no domain component.
Xcode Template format:
You can check the default template formats which exists in the path
Each templates has 2 elements in common:
Xcode uses this to display in the Choose a template for your new file section. The dimension of the icons should be 48*48 for 1x and 96*96 for 2x.
Xcode uses this
.plist to determine the User Interface and what files are added to the project upon selecting a particular template.
Feature Template's TemplateInfo.plist as shown above is used to create an entire feature. Among the top level entities, the Options provide the User Interface for the template. Each item in the Options defines certain Interface in the template.
Each item contains the following:
- Identifier: Uniquely identifies our option, we can use a custom value. If the value is
productNamethen the Xcode will use it to name the files.
- Required: Whether this item is optional or mandatory, Xcode uses this to enable/disable the Next button.
- Name: Name to be displayed for the item in the Template.
- Description: Description of the item in the Template, not visible.
- Type: Type of the UI element for the item.
- NotPersisted: Whether the previous value should be persisted or not.
In our case, we use three items.
- Item 1: Name prefix to be used when the Xcode generates the files.
- Item 2: Type of the View, whether to use a XIB, Storyboard or No UI Element.
- Item 3: To create a list of objects based on the API response.
We have defined the User Interface for template with the
TemplateInfo.plist. However we haven't looked at how the source files are defined and how it gets added to the project.
Now you know the basics of Template UI, let's see how to create the templates.
Creating the templates:
- For the View Layer
- ___FILEBASENAME___: Xcode uses the this macro to replace it with the value you entered.
- ___FILEBASENAMEASIDENTIFIER___: If you want to name your class with the file name.
- ___FILEHEADER___: Xcode uses this to populate the default headers like FileName, Author and other information.
- ___VARIABLE_productName___: Will use the value entered in the Feature Name identified with the productName identifier from the
Our ViewModel uses the RepositoryProtocol to define the dependency on the domain.
We extensively use promises in our iOS App. We have many infrastructure APIs which are paginated and returns a list of objects. Hence we have considered list of objects during the template design.
2. For the Domain Layer:
Our infrastructure layer is a generic layer which defines the Request, Response Models using Codable.
3. For the Data Layer:
Local storage will be added using the LocalDataSource as the need arises.
We have also provided many different User Interfaces ranging from Storyboard, XIB to manual view as well just by grouping the templates in multiple folders, i.e. None, NoneList, Storyboard, StoryboardList, XIB and XIBList based on the requirement.
Upon choosing the ViewType and the option to Create List Object, the specific folder will be picked to generate the code.
We have also provided added templates Repository.xctemplate with Domain and Data folder for refactoring and ViewController.xctemplate with only View Folder for ease of use.
This article talks about identifying your architecture and commonly used design patterns and how to create a custom template for it, how it helped the team with many aspects like easy setting up of Xcode for new team member, easy debugging, consistent design pattern. This helped developers to work with different business verticals pretty efficiently. Software companies/freelancers can use Xcode Templates as a defacto for the entire suite of projects.
Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for data engineers/architects and if solving hard problems with challenging requirements is your forte, please reach out to us with your resumé at email@example.com.
Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke.
We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 2500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allows patients to book a doctor appointment inside our application.
We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates foundation, Singtel, UOB Ventures, Allianz, Gojek and many more. We recently closed our Series B round and In total have raised USD$100million for our mission.
Our team work tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.