Dicoding Developer Coaching #31: Android | Menerapkan Clean Architecture di Android
- 2. What is Design and
Architecture?
The word “architecture” is often used in the
context of something at a high level that is
divorced from the lower-level details, whereas
“design” more often seems to imply structures
and decisions at a lower level.
Architecture : Shape of the home, the
elevations, layout spaces and rooms.
Design : light switch is placed, furnace is placed,
size and placement of water heater
- 3. ARCHITECTURE
The second value of software has to do with
the word “software”—a compound word
composed of “soft” and “ware.” The word
“ware” means “product”; the word “soft”…
Well, that’s where the second value lies.
Software was invented to be “soft.” To fulfill its
purpose, software must be soft—that is, it must
be easy to change.
https://i.pinimg.com/originals/3d/0d/21/3d0d21ef129676422f3695538fb48522.gif
- 4. Function or Architecture?
Which of these two provides the greater value?
Is it more important for the software system to work?
OR
Is it more important for the software system to be easy to change?”
● If you give me a program that works perfectly but is impossible to change, then it won’t work
when the requirements change, and I won’t be able to make it work. Therefore the program will
become useless.
● If you give me a program that does not work but is easy to change, then I can make it work, and
keep it working as requirements change. Therefore the program will remain continually useful.
- 6. History
Over the last several years we’ve seen a whole range of ideas
regarding the architecture of systems. These include:
● Hexagonal Architecture (a.k.a. Ports and Adapters) by
Alistair Cockburn and adopted by Steve Freeman, and
Nat Pryce in their wonderful book Growing Object
Oriented Software
● Onion Architecture by Jeffrey Palermo
● Screaming Architecture from a blog of mine last year
● DCI from James Coplien, and Trygve Reenskaug.
● BCE by Ivar Jacobson from his book Object Oriented
Software Engineering: A Use-Case Driven Approach
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
- 7. Characteristics
1. 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.
2. Testable.
The business rules can be tested without the UI, Database, Web Server, or any other external element.
3. 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.
4. 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.
5. Independent of any external agency.
In fact your business rules simply don’t know anything at all about the outside world.
- 8. Clean Architecture Layers
https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg
● Entities
Entities encapsulate Enterprise wide
business rules.
● Use Cases
The software in this layer contains
application specific business rules. It
encapsulates and implements all of
the use cases of the system.
● Interface Adapters
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.
● Frameworks and Drivers.
The outermost layer is generally
composed of frameworks and tools
such as the Database, the Web
Framework, etc.
- 10. Dependency Rule
● Source code dependencies can only point inwards.
● Nothing in an inner circle can know anything at all
about something in an outer circle.
● In particular, the name of something declared in an
outer circle must not be mentioned by the code in the
an inner circle. That includes, functions, classes.
variables, or any other named software entity.
● By the same token, data formats used in an outer circle
should not be used by an inner circle, especially if
those formats are generated by a framework in an
outer circle. We don’t want anything in an outer circle
to impact the inner circles.
● It’s very important using dependency injection to
manage dependency.
- 11. No, the circles are schematic. You may find that you need more than just
these four. There’s no rule that says you must always have just these four.
However, 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.
Only Four Circles?
- 13. Repository Interface & Implementation
interface IMessageRepository {
fun getWelcomeMessage(name: String): String
}
● Repository Interface
class MessageRepository(private val source:DataSource): IMessageRepository
{
override fun getWelcomeMessage(name: String) = "Hello $name"
}
● Repository Implementation
- 14. DIP Example
class MessageInteractor(private val messageRepository:IMessageRepository){
override fun getMessage(name: String): String {
return messageRepository.getWelcomeMessage(name)
}
}
● Correct Code (Call interface)
class MessageInteractor(private val messageRepository:MessageRepository){
override fun getMessage(name: String): String{
return messageRepository.getWelcomeMessage(name)
}
}
● Incorrect Code (Call implementation directly)
- 17. Model Comparison
data class Tourism(
val tourismId: String,
val name: String,
val description: String,
)
//contain room annotation
@Entity(tableName = "tourism")
data class TourismEntity(
@PrimaryKey
@NonNull
@ColumnInfo(name = "tourismId")
val tourismId: String,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "description")
val description: String,
)
Tourism in Domain Layer TourismEntity in Data Layer
- 18. Model Example
class TourismInteractor(private val repository: ITourismRepository){
override fun getAllTourism():List<Tourism>> {
return repository.getAllTourism()
}
}
● Correct Code (Use domain/plain model)
class TourismInteractor(private val repository: ITourismRepository){
override fun getAllTourism():List<TourismEntity>> {
return repository.getAllTourism()
}
}
● Incorrect Code (Use model that contain Room library in domain layer)
- 20. Conclusion
● Conforming to these simple rules is not hard, and will save you a lot of
headaches going forward.
● By separating the software into layers, and conforming to The Dependency
Rule, you will create a system that is intrinsically testable, with all the benefits
that implies.
● When any of the external parts of the system become obsolete, like the
database, or the web framework, you can replace those obsolete elements
with a minimum of fuss.
- 21. Reference
Robert C. Martin. “Clean Architecture:
A Craftsman's Guide to Software
Structure and Design (Robert C.
Martin Series).” iBooks.
https://blog.cleancoder.com/uncle-bob/2012/
08/13/the-clean-architecture.html