Making decisions is hard. Sometimes it helps to take a look at what you actually want to achieve. Some principles I try to follow:
- Keep it simple: Least complex solution is preferred.
- Choose vanilla: Stay close to the system, prevent pattern/architecture/framework.
- Locality, Separation, Independence: Prevent dependencies between modules / features / sections.
- Maintainability: Prevent future work.
- Don't let it dry out: While DRY (don't repeat yourself) is great, it's often misunderstood as don't repeat code. It should be don't repeat logic instead.
- Explicit over implicit. Don't hide the details.
Trying to prevent using external dependencies. This is a guideline, not a rule. The closer to the core, the more significant it becomes.
- Try a simpler solution that works out of the box.
- If worth it, try to reimplement. Book the effort as learning.
- If using something external, try to wrap it for easy replacement.
I like rules, but not to enforce them. So I am not using any formatter or linter. Just some conventions I got used to.
// TODO:
indicates where something has to be done next.
- Use on a branch to indicate ongoing development.
- Never merge to main.
// TODO <xyz>:
indicates an optional improvement for the future. Common tags:
FB#
: A workaround because something does not work as expected, reference related FB number. Fix when FB is resolved.finetuning
: A non critical improvement is possible.idea
: A new feature might evolve here.
On file level, Code is structured to easily find stuff using the minimap. Useing // MARK: - XYZ
.
On block level, Code is structured like a text. Related lines of code are together and separated to other blocks by an empty line.
Use empty lines to structure the file visually.
Use Xcode default formatting with control + m
.
Scene - A structural independent section of the app. Usually the entry into a set of screens that can be displayed in a NavigationStack. (E.g. ListLoopScene that will present ListScreen.)
Screen -
An independent arrangement of Views that is displayed in a Scene
.
(E.g. ListScreen that is presented in a ListLoopScene.)
View, Row, Section, ... - Building blocks to layout into a Screen.
Container - A generic View to place another View into.
State - A struct that represents a snapshot of changable state for a Scene or Screen.
Data - A struct that represents some content to be displayed by a Screen or View. (I prefer Data over Model or ViewModel.)
While most of them are basically the same, sometimes nuances make sense to better communicate expections.
Service - Provides a simple adhoc functionality to be accessed when needed.
Manager - Takes care of a more complex topic, usually needs to be setup and kept alive.
DataSource - Source of information to read and write.
Provider - Read only source of information to be consumed.