The core of CC6 architecture was put together with the SOLID principles at the front mind. The history of SOLID goes back to the 1980s and has evolved over the years, it was finalized in the early 2000s by Uncle Bob. SOLID provides guidelines on how to arrange our functions and data structures into classes, and how those classes should be interconnected.
- SRP: The single responsibility principle
- An active corollary to Conway's law: The best structure for a software system is heavily influenced by the social structure of the organization that uses it so that each software module has one, and only one, reason to change.
- OCP: The open-close principle
- Bertrand Meyer made this principle famous in the 1980s. The gist is that for software systems to be easy to change, they must be designed to allow the behavior of those system to be changed by adding new code, rather than changing existing code.
- LSP: The liskov substitution principle
- Barbara Liskov's famous definition of subtypes, from 1988. In short, this principle says that to build software systems from interchangeable parts, those parts must adhere to contract that allows those parts to be substituted one from another.
- IPS: The interface segregation principle
- This principle advises software designers to avoid depending on things that they don't use.
- DIP: The dependency inversion principle
- The code that implements high-level policy should not depend on the code that implements low-level details. Rather details should depend on policies.
This cross platform architecture framework was designed with the following principles in mind:
- Reusability: This could be the most important principle to always keep in mind. We want to avoid having to do things twice, 90% of the time we are building the same application with just a different skin on it, the business logic is rarely different. So with this being said all SDK code within reason should be generic and allow for overrides. We should make use of interfaces and abstract classes even when it comes to the presentation layer.
- Cross platform collaboration: The complex business problems of our applications are pretty similar between iOS and Android. With CC6 developers across both platforms can share a single architecture and design patterns, meaning the same problem does not have to be solved twice. We want developers to be able to look at both code bases and understand the code without having intimate domain knowledge for the relevant platform, i.e a iOS dev can look at the CC6 kotlin code and have a very good idea of what it is doing.
- Testability and Isolation: Classes should be easy to test with minimal mocking required. Along with this classes should have distinct responsibility (i.e routing, presentation logic, business logic and mapping). This makes classes easy to test and change with out affecting larger scopes of an application.
The Dependency Rule
This is the key to how CC6 architecture works. The rule is simple.
"Source code dependencies must point only inward, toward higher-level policies" Robert C. Martin - Clean Architecture
Nothing in an inner circle should know anything at all about something in an outer circle. Something declared in an outer circle must not be mentioned by the code in an inner circle. This includes functions, classes, variables, or any other named software entity.
Clean Architecture Rules
To build reusable applications that are easily testable, maintainable and scalable we have to separate concerns this goes back to the SRP principle. With this in mind we want CC6 to follow these rules:
- Independent of frameworks. The architecture does not depend on the existence of some library of feature-laden software. This allows you to use such frameworks as tools, rather than forcing you to cram your system into their limited constraints.
- Testable. The business rules can be tested without the UI, database, network, or any other external element.
- Independent of the UI. The UI can change easily, without changing the rest of the system. This is very important to CC6 every app we build for a client is going to have different UI requirements. For example the Rinami CAM application may look very different to a clients CAM app but logically when I issue a part to work order the business logic very rarely changes.
- Independent of the database. You can swap out Coredata or Objectbox for RealmDB or something else. Your business rules are not bound to the database.
- Independent of the networking layer. You can swap out URLSession with Alamofire
- Independent of any external agency. In fact, your business rules don't know anything at all about the interfaces to the outside world.