Clean Architecture : Part 2 - The Clean Architecture

아키텍처 관점에서 마지막이자 가장 중요한 레이어는 엔티티 또는 도메인 레이어에요. 엔티티는 핵심 비니지스 규칙을 캡슐화해요. 핵심 비지니스 규칙은 비지니스의 존재에 필수지만, SW 시스템에 필수는 아니에요. 외부 변경은 이 레이어의 동작에 그 어떤 영향을 주면 안되요. SW 시스템 또는 어플리케이션이 없어도 타당한 비지니스 규칙을 구현하는 엔티티를 만들 수 있어요. 기술적인 관점에서 엔티티는 단지 데이터 만이 아니라 메소드와 로직을 포함하는 객체에요. 엔티티는 DTO (Data Transfer Object) 와 DAO (Data Access Object) 가 아니에요.

  1. Controller 에서 버튼 클릭 이벤트를 처리해요. Controller 는 UseCase Input Port 인터페이스를 구현하는 객체의 메소드를 하나 호출하죠.
  2. 우린 막 두 레이어 (Presentation 레이어와 Use Case 레이어) 경계를 넘었고 지금은 Use Case 레이어에 있어요.
  3. Use Case 구현 (Use Case Interactor) 는 엔티티 또는 다른 도메인의 핵심 객체를 조정해서 전달된 요청을 처리해요.
  4. Use Case 구현 (Use Case Interactor) 는 처리 결과를 받은 후 UseCase Output Port 인터페이스를 구현하는 객체의 메소드를 하나 호출하죠.
  5. Presenter 는 Use Case 구현으로 부터 결과를 받고 (Presenter 가 구현하는 UseCase Output Port 인터페이스를 통해 전달이 되겠죠?), 그리고, Presenter 는 받은 결과를 적당한 형태로 변형해서 View 레이어로 전달해요



These arrows represent code level dependencies which means the code where an arrow starts knows about the code the arrow is pointing to. All these arrows fulfill the Dependency Rule as all arrows crossing the boundaries are always going from left to right - from the framework circle to the interface adapters circle to the use case circle.

Implementing Clean Architecture - Of controllers and presenters


Thoughts on Clean Architecture

interface SomeRepository {
    fun doSomething()
}
class SomeViewModel1(private val someRepository: SomeRepository) {
    //...
    fun doSomething() {
        //...
        someRepository.doSomething()
        //...
    }
    //...
}
class SomeViewModel2(private val someRepository: SomeRepository) {
    //...
    fun doSomething() {
        //...
        someRepository.doSomething()
        //...
    }
    //...
}
class SomeViewModel3(private val someRepository: SomeRepository) {
    //...
    fun doSomething() {
        //...
        someRepository.doSomething()
        //...
    }
    //...
}

If the requirements for the repository change, let’s say the doSomething method now needs a model coming from a SomeOtherRepository, how much code do you need to change? How many ViewModels are affected?


The "Real" Repository Pattern in Android

[DAO] DAO, DTO, Entity Class의 차이 - Heee's Development Blog

// Network DTO
data class NetworkProduct(
    @SerializedName("id")
    val id: String?,
    @SerializedName("name")
    val name: String?,
    @SerializedName("nowPrice")
    val nowPrice: Double?,
    @SerializedName("wasPrice")
    val wasPrice: Double?
)
// Entity
data class Product( 
    val id: String,
    val name: String,
    val price: Price
) {
// Value object
  data class Price( 
      val nowPrice: Double,
      val wasPrice: Double
  ) {
      companion object {
          val EMPTY = Price(0.0, 0.0)
      }
  }
}
// Database DTO
@Entity(tableName = "Product")
data class DBProduct(
    @PrimaryKey                
    @ColumnInfo(name = "id")                
    val id: String,                
    @ColumnInfo(name = "name")                
    val name: String,
    @ColumnInfo(name = "nowPrice")
    val nowPrice: Double,
    @ColumnInfo(name = "wasPrice")
    val wasPrice: Double
)

클린 아키텍처 by 엉클 밥

개발자인 나에게 중요한 것은 Use Case 가 정확하게 동작하는 것임. Use Case 동작 결과를 확인하는데 UI 가 필요함? 아님!! 테스트 프레임워크로 Use Case 실행 결과를 확인 할 수 있음.