소개
만들면서 배우는 클린 아키텍처 책을 읽고 정리하며 소감을 적는 포스트입니다.
의식적으로 지름길 사용하기
절대 갚을 길 없는 기술 부채를 쌓아가면서 항상 지름길의 유혹을 느낀다는 사실을 저주한다.
지름길을 방지하기 위해서는 먼저 지름길 자체를 파악해야 한다.
왜 지름길은 깨진 창문 같을까?
1969년 심리학자 필립 짐바르도(Philip Zimbardo)는 나중에 깨진 창문 이론
이라고 알려진 실험을 했다.
어떤 것이 멈춘 것처럼 보이고, 망가져 보이고, [부정적인 형용사를 넣어보자], 혹은 관리되지 않는다고 여겨지면 인간의 뇌는 이를 더 멈추고, 망가뜨리고, [부정적인 형용사를 넣어보자] 해도 된다고 생각하게 된다.
이 이론은 삶의 많은 부분에 적용할 수 있다.
- 기물 파손이 흔한 동네에서는 방치된 차를 도둑질하거나 망가뜨리는 일이 더 쉽게 일어난다.
좋은
동네라도 차의 창문이 깨져있다면 차를 망가뜨리는 일이 쉽게 일어난다.- 침실이 정돈돼 있지 않으면 옷을 옷장에 넣는 대신 바닥에 아무렇게나 던져 놓기 싶다.
- 괴롭힘이 흔한 집단에서는 괴롭힘이 더 쉽게 일어난다.
코드 작업에 적용될 때의 의미는 다음과 같다.
- 품질이 떨어진 코드에서 작업할 때 더 낮은 품질의 코드를 추가하기가 쉽다.
- 코딩 규칙을 많이 어긴 코드에서 작업할 때 또 다른 규칙을 어기기도 쉽다.
- 지금길을 많이 사용한 코드에서 작업할 때 또 다른 지름길을 추가하기도 쉽다.
깨끗한 상태로 시작할 책임
소프트웨어 프로젝트는 대개 큰 비용이 들고 장기적인 노력을 필요로 하기 때문에 깨진 창문을 막는 것이 소프트웨어 개발자들의 아주 막대한 책임이다.
그리 중요하지 않거나, 프로토타이핑 작업 중이거나, 경제적인 이유로 지름길이 더 실용적일 때도 있다. 하지만 이럴 때는 세심하게 잘 기록해야 한다.
마이클 나이가드(Michael Nygard)가 제안한 아키텍처 결정 기록(Architecture Decision Recordes, ADRs)의 형태도 괜찮다.
유스케이스 간 모델 공유하기
유스케이스 간에 입출력 모델을 공유하게 되면 유스케이스들 사이에 결합이 생긴다.
공유로 인한 영향 SendMoneyUseCase와 RevokeActivityUseCase가 결합된다는 것이다. 공유하고 있는 SendMoneyCommand 클래스가 변경되면 두 유스케이스 모두 영향을 받는다.
단일 책임 원칙에서 이야기하는 변경할 이유
를 공유하는 것이다.
유스케이스 간 입출력 모델을 공유하는 것은 유스케이스들이 기능적으로 묶여 있을 때 유효하다. 특정 세부사항을 변경 할 경우 실제로 두 유스케이스 모두에 영향을 주고 싶은 것이다.
도메인 엔티티를 입출력 모델로 사용하기
도메인 엔티티를 유스케이스의 입출력 모델로 사용하면 도메인 엔티티가 유스케이스에 결합된다.
Account 엔티티에 존재하지 않은 정보를 유스케이스가 필요하다면 엔티티에 새로운 필드를 추가하고 싶은 유혹이 생긴다.
간단한 생성이나 업데이트 유스케이스에서는 유스케이스 인터페이스에 도메인 엔티티가 있는 것은 괜찮을지도 모른다. 데이터베이스에 저장해야 하는 바로 그 상태 정보가 엔티티에 있기 때문이다.
더 복잡한 도메인 로직을 구현해야 한다면(도메인 로직의 일부를 풍부한 도메인 엔티티로 위임할 수도 있으니), 유스케이스 인터페이스에 대한 전용 입출력 모델을 만들어야 한다.
이 지름길이 위험한 이유는 시간이 지나면서 복잡한 도메인 로직 괴물이 되어 가기 때문이다. 그러므로 처음에는 도메인 엔티티를 입력 모델로 사용했더라도 도메인 모델로부터 독립적인 전용 입력 모델로 교체해야 하는 시점을 잘 파악해야 한다.
인커밍 포트 건너뛰기
아웃고잉 포트에 비해 인커밍 포트는 의존성 역전에 필수적인 요소는 아니다.
인커밍 포트가 없으면 도메인 로직의 진입점이 불분명해진다.
전용 인커밍 포트가 있으면 진입점을 한눈에 식별이 가능하다. 또한 아키텍처를 쉽게 강제할 수 있따.
애플리케이션의 규모가 작거나 인커밍 어댑터가 하나밖에 없어서 모든 제어 흐름을 인커밍 포트의 도움 없이 단숨에 파악할 수 있다면 인커밍 포트가 없는 것이 편하다.
애플리케이션 서비스 건너뛰기
애플리케이션 서비스가 없으면 도메인 로직을 둘 곳이 없다.
간단한 CRUD 유스케이스에서는 보통 애플리케이션 서비스가 도메인 로직 없이 생성, 업데이터, 삭제 요청을 그대로 영속성 어댑터에 전달하기 때문에 그대로 전달하는 대신 영속성 어댑터가 직접 유스케이스를 구현하게 할 수 있다.
하지만 이 방법은 인커밍 어댑터와 아웃고잉 어댑터 사이에 모델을 공유해야 한다. 나아가 애플리케이션 코어에 유스케이스라고 할만할 것이 없어진다. 만약 시간이 지남에 따라 CRUD 유스케이스 점점 복잡해지면 도메인 로직을 그대로 아웃고잉 어댑터에 추가하고 싶은 생각이 들 것이다.