Often a task’s complexity is daunting. Often aspects of a task can be used to guide design decisions in a direction which leads to elegance, robustness, and flexibility. This can lead to more readable code and easier maintenance.
This primer is meant to inspire better design, not to guide it. Please explore patterns of interest to consider implementation. Any feedback or suggestions are welcomed.
Some Architectural Patterns
Singleton and Registry
If an object needs only one instance, it’s a Singleton. Restrict to one instance if you need to coordinate actions or keep track of other classes. For Registry, use a singleton base class to keep a reference to all items.
Loose Coupling and Chain of Responsibility
Keep the steps of the process loosely coupled to keep the codebase modular. Call the next function until the process is done.
Much like proxies in other cases, use an object to interface to another. This can be used to simplify usage of remote resources, to simplify a resource intensive object or process, or to control access to something.
Observer and Publish-subscribe
To pass information, either have a subject notify dependents upon state change directly, or use another service, like a Message Service.
If you have a data-heavy problem, like object or sound identification, focus on the data. When designing, consider all memory as a blackboard which reads a control component, which uses knowledge sources to operate on the blackboard memory.
Consider the application as a relation of states, and think about how every action can be made to be a change of state. Essentially, implement a finite state machine.
Other Design Considerations
If a method does not need to be done in order, try to separate the steps so that the kernel can perform the task, along with others, without keeping similarly-parallel tasks waiting.