✍️ Note
Some codes and contents are sourced from The Clean Code Blog official documentation, The iOS Interview Guide Book, Head First Design Patterns 2nd, theswiftdev.com, and Wiki Pedia. This post is for personal notes where I summarize the original contents to grasp the key concepts
Clean Architecture

The Dependency Rule always applies. Source code dependencies always point inwards. As you move inwards the level of abstraction increases. The outermost circle is low level concrete detail. As you move inwards the software grows more abstract, and encapsulates higher level policies. The inner most circle is the most general by cleancoder.com
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
- 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 having to cram your system into their limited constraints.
- Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
- Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
- Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
- Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world
Dependency rule
The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle.
Entities
Entities encapsulate Enterprise wide business rules. An entity can be an object with methods, or it can be a set of data structures and functions. It doesn’t matter so long as the entities could be used by many different applications in the enterprise
If you don’t have an enterprise, and are just writing a single application, then these entities are the business objects of the application. They encapsulate the most general and high-level rules. They are the least likely to change when something external changes. For example, you would not expect these objects to be affected by a change to page navigation, or security. No operational change to any particular application should affect the entity layer.
My comments
- ViewModel can be a Entities
Use Cases
The software in this layer contains application specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.
We do not expect changes in this layer to affect the entities. We also do not expect this layer to be affected by changes to externalities such as the database, the UI, or any of the common frameworks. This layer is isolated from such concerns.
Interface Adapters
The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web. It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here. The models are likely just data structures that are passed from the controllers to the use cases, and then back from the use cases to the presenters and views.
Frameworks and Drivers
The outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework, etc. Generally you don’t write much code in this layer other than glue code that communicates to the next circle inwards.
Crossing boundaries.

At the lower right of the diagram is an example of how we cross the circle boundaries. It shows the Controllers and Presenters communicating with the Use Cases in the next layer. Note the flow of control. It begins in the controller, moves through the use case, and then winds up executing in the presenter. Note also the source code dependencies. Each one of them points inwards towards the use cases.
For example, consider that the use case needs to call the presenter. However, this call must not be direct because that would violate The Dependency Rule: No name in an outer circle can be mentioned by an inner circle. So we have the use case call an interface (Shown here as Use Case Output Port) in the inner circle, and have the presenter in the outer circle implement it.
I redraw the Clean Architecture
As my understanding, Clean Architecture is guidance that app can be separated by layers. There are boundaries between layers
App can have multiple layers like below (by The iOS Interview Guide)
- Service Layer
- UI Layer
- Storage Layer
- Business Logic Layer
This Image I added layers and informations which can be related to from the original clean architecture diagram.

VIPER Architecture, It’s iOS version of Clean Architecture
https://www.objc.io/issues/13-architecture/viper
https://theswiftdev.com/viper-best-practices-for-ios-developers
The main parts of VIPER are:
https://www.objc.io/issues/13-architecture/viper/
- View: displays what it is told to by the Presenter and relays user input back to the Presenter.
- Interactor: contains the business logic as specified by a use case.
- Presenter: contains view logic for preparing content for display (as received from the Interactor) and for reacting to user inputs (by requesting new data from the Interactor).
- Entity: contains basic model objects used by the Interactor.
- Routing: contains navigation logic for describing which screens are shown in which order.
SOLID Principles
I summarized this principle by reading Head First Design Patterns, 2nd edition and The iOS Interview Guide blog.
S, Single Responsibility Principle
Class / Module should have only one responsibility and reason to change. Avoid changing a class if possible. This principle is related to cohesion. If you follow this principle, You can easily maintain a class than a class which has multiple responsibility.
If class have multiple responsibility, There is multiple reason to change it. It makes hard to maintaining.
O, Open-Closed Principle
Class opens for extension but closed for modification. It sounds complicated when I read this principle.
Opens for extension. It means without modification, class can be extended. There is many way to extension. The purpose is adding a new functionalities without changing the existing codes / logics. (by Head First Design Patterns 2nd)
For example, Observer pattern, you can add a new observer without changing a existing code. You can also follow this principle by adopting decoration pattern. Abstraction is also good for following this principle. Important thing is choosing which parts will be changed and separate it. (by Head First Design Pattens 2nd)
Also you can extend objects through inheritance, polymorphism, and composition by implementing them using interfaces, abstractions, and dependency injection. (by The iOS Interview Guide book)
L, Liskov Substitution Principle
An object (such as a class) may be replaced by a sub-object (such as a class that extends the first class) without breaking the program
Let say you have a class T. And you have a class S that inheritance from T. Your program could allow to replace T with S without breaking it.
Or you can think usecase protocol. You have a protocol and struct or class which conforms to usecase protocol. And You can inject that protocol type in ViewModel. In this case your program can allow to replace the injecting objects with the others that conforms to usecase protocol without breaking it.
Sub-Type: Subclass or Conforms to Protocol
Super-Type: Super class or high level protocol
I, Interface Segregation Principle
No code should be forced to depend on methods it does not use.[1] ISP splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called role interfaces. (by Wikipedia)
If you familiar with protocol oriented programming, You can easily understand what is meaning.
This principle is introduced at chapter 1, Head First Design Patterns 2nd
Example is making a Duck class. There are protocols that has multiple methods. Like a FlyBehavior and QuackBehavior. Separating the interfaces prevents the problem like RubberDuck class doesn’t need to implement FlyBehavior because It can’t fly. That interface doesn’t need.
In a Head First Design Patterns book, author suggested creating a FlyNoWay class that conforms to FlyBehavior protocol.
Example
protocol FlyBehavior {
func fly()
}
protocol QuackBehavior {
func quack()
}
class FlyWithWings: FlyBehavior {
func fly() {
print("I'm flying")
}
}
class FlyNoWay: FlyBehavior {
func fly() {
print("I can't fly")
}
}
class Quack: QuackBehavior {
func quack() {
print("Quack!!")
}
}
class MuteQuack: QuackBehavior {
func quack() {
print("....")
}
}
class Duck {
let flyBehavior: FlyBehavior
let quackBehavior: QuackBehavior
init(flyBehavior: FlyBehavior, quackBehavior: QuackBehavior) {
self.flyBehavior = flyBehavior
self.quackBehavior = quackBehavior
}
func performFly() {
flyBehavior.fly()
}
func performQuack() {
quackBehavior.quack()
}
}
class RubberDuck: Duck {}
let rubberDuck = RubberDuck(
flyBehavior: FlyNoWay(),
quackBehavior: Quack()
)
rubberDuck.performFly()
rubberDuck.performQuack()
//Prints
I can't fly
Quack!!
D, Dependency Inversion Principle
Depend on abstractions, not concretions
Tips for following this principle (by Head First Design Patterns 2nd)
- Don’t save concrete class’s reference using variable
- Create a class that conforms to protocol (Don’t create a class by inheritance from concrete class)
- Don’t override function that already implemented at base class. (Base class’s function should be defined that can be sharable for all the subclasses)
It is useful for writing unit testing.

With the addition of an abstract layer, both high- and lower-level layers reduce the traditional dependencies from top to bottom. Nevertheless, the “inversion” concept does not mean that lower-level layers depend on higher-level layers directly. Both layers should depend on abstractions (interfaces) that expose the behavior needed by higher-level layers.
In a direct application of dependency inversion, the abstracts are owned by the upper/policy layers. This architecture groups the higher/policy components and the abstractions that define lower services together in the same package. The lower-level layers are created by inheritance/implementation of these abstract classes or interfaces.[1]
The inversion of the dependencies and ownership encourages the re-usability of the higher/policy layers. Upper layers could use other implementations of the lower services. When the lower-level layer components are closed or when the application requires the reuse of existing services, it is common that an Adapter mediates between the services and the abstractions.
https://en.wikipedia.org/wiki/Dependency_inversion_principle

Leave a comment