Clean Architecture by Example
One question people often ask when learning about Clean Architecture is on code example. The original article and even the book itself does not contain much of it. It is quite understandable though since it deals with high level abstraction that any code example that is too concrete might risk being taken too literal or prescriptive. Still when adopting it, especially on the team setting some concrete code could go a long way to help ground the discussion and moving on to implementation side.
That being said, I made the example project, a tasklist management app, below :
It is developed from ground up using Clean Architecture utilizing as much as layers and component from it. It’s an iOS App project in ObjC as that’s the setting of some of the project we have here. That being said, apart from syntax, the approach itself should be language-independent/trasferable as it mainly relies on the base language and the built-in platform support.
It is always tricky to come up with proper scope on project example for certain architectural pattern. You need to have enough “meat” on the required logic to justify the usage of all the layers and abstraction. Too little, some abstraction will appear silly and unnecessary, too much it will take too big of scope for an example and might distract from the focus. So, you might find some part intentionally “scaled” in scope to make it just enough to show the usefulness of certain layer.
It is mainly for teaching and discussion purposes with the accompanying slide below that I in the sharing and discussion session.
Following are some highlighted notes on some ideas and intention on the project.
Separating Logic from Infrastructure
One of the importance of architecture is to have a clean boundary between the logic of your project and your external dependencies. With blurred boundary you cannot test and refactor those logic well e.g: do unit testing on them easily, but with a clean one you can.
Below are the components on the project and dependency direction between them on the project.
All the logic of the projects are on the upper parts (the light yellow boxes) with the rest of the code on the below parts only contains generic/boilerplate to interface with external dependencies (I/O, Platform SDK, third party library). In terms of pattern, the code on the below parts follow Humble Object pattern, an important pattern on testing.
You will find the classes below on the project contain only what is necessary to interface with dependency that we need but in a way that does not interfere nor pollute any of our “important” logic.
Some Domain Driven Design (DDD) Influence
There are a lot of complementary patterns that you can use from DDD on implementing Clean Architecture. Specifically for Entity there are items on DDD Tactical Patterns that fit really well to be used here.
A DDD Practicioner might notice some of the pattern on Entity layer
There is Domain Repository and Domain Service pattern from DDD used to model the domain above.
Well, to be fair, actually Clean Architecture is more of a “plugin” to DDD in a way that it’s one of the preferable architecture choice for doing DDD. In any case, it is a good complementary material to look into to have richer context for applying Clean Architecture although not mandatory.
One important value on our development here is on Testing and it follows naturally that we need to structure the code in a way that is supportive to that. It’s one of the reason we are pretty picky with our structural choices for our code.
Having well-separated logic for low level technical concerns you might find all the tests on the logic parts (Entity, Interactor and ViewModel) are pretty straightforward and easy to follow. Compared that with cases when the classes cluttered with external API call and you need an army of mocks and stubs and setup/teardown gymnastics to test simple logic.
So, do checkout the code and hopefully it can give some hint on how certain concept might morph into code, at the very least in this specific situation.