"복잡성은 죽음이다. 개발자에게서 생기를 앗아가며, 제품을 계획하고 제작하고 테스트하기 어렵게 만든다."
시스템 수준에서 깨끗함을 유지하는 방법
시스템 제작과 시스템 사용을 분리하라
- 제작과 사용은 아주 다르다는 사실을 명심한다.
- 소프트웨어 시스템은 (애플리케이션 객체를 제작하고 의존성을 서로 '연결'하는) 준비 과정과 (준비 과정 이후에 이어지는) 런타임 로직을 분리해야 한다.
- 관심사 분리
- 모듈성을 깨서는 절대로 안된다. 설정 논리는 일반 실행 논리와 분리해야 모듈성이 높아진다.
Main 분리
- 생성과 관련한 코드는 모두 main이나 main이 호출하는 모듈로 옮기고, 나머지 시스템은 모든 객체가 생성되었고 모든 의존성이 연결되었다고 가정한다.
팩토리
의존성 주입 (Dependency Injection, DI)
- 의존성 주입은 제어 역전 (Inversion of Control, IoC) 기법을 의존성 관리에 적용한 메커니즘이다.
IoC
- 한 객체가 맡은 보조 책임을 새로운 객체에게 전적으로 떠넘긴다.
- 새로운 객체는 넘겨받은 책임만 맡으므로 단일 책임 원칙(SRP)을 지키게 된다.
- 의존성 관리 맥락에서 객체는 의존성 자체를 인스턴스로 만드는 책임을 지지 않는다.
- 대신에 이런 책임을 다른 전담 메커니즘에 넘김으로써 제어를 역전한다.
- 초기 설정은 시스템 전체에서 필요하므로 대게 책임질 메커니즘으로 main 루틴이나 특수 컨테이너를 사용한다.
- 의존성 주입은 클래스가 의존성을 해결하려 하지 않는다.
의존성을 주입하는 방법으로 설정자(setter) 메서드나 생성자 인수를 제공한다.
- DI 컨테이너는 대개 요청이 들어올 떄마다 필요한 객체의 인스턴스를 만든 후 생성자 인수나 설정자 메서드를 사용해 의존성을 설정한다.
확장
- 처음부터 올바르게 시스템을 만들 수 있다는 믿음은 미신이다.
- 우리는 오늘 주어진 사용자 스토리에 맞춰 시스템을 구현해야 한다.
- 내일은 새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다.
- 이것이 반복적이고 점진적인 애자일 방식의 핵심이다.
- 코드 수준에서는 TDD와 리팩터링으로 얻어지는 깨끗한 코드가 시스템을 조정하고 확장하기 쉽게 만든다.
- 시스템 아키텍처는 관심사를 적절히 분리해 관리한다면 점진적으로 발전할 수 있다.
횡단 관심사
- 관점 지향 프로그래밍 AOP는 횡단 관심사에 대처해 모듈성을 확보하는 일반적인 방법론이다.
- AOP에서 관점 이라는 모듈 구성 개념은 "특정 관심사를 지원하려면 시스템에서 특정 지점들이 동작하는 방식을 일관성 있게 바꿔야 한다"라고 명시한다.
자바 프록시
- 단순한 상황에 적합하다.
개별 객체나 클래스에서 메서드 호출을 감싸는 경우가 좋은 예
- 코드의 양과 크기는 프록시의 두 가지 단점이다.
프록시를 사용하면 깨끗한 코드를 작성하기 어렵다.
또한 시스템 단위로 실행 지점을 명시하는 메커니즘도 제공하지 않는다.
순수 자바 AOP 프레임워크
- 대부분의 프록시 코드는 판박이라 도구로 자동화할 수 있다. 순수 자바 관점을 구현하는 스프링 AOP, JBoss AOP 등 여러 자바 프레임워크는 내부적으로 프록시를 사용한다.
- 스프링은 비즈니스 논리를 POJO로 구현한다.
- POJO는 순수하게 도메인에 초점을 맞춘다.
테스트가 개념적으로 더 쉽고 단순하다.
AspectJ 관점
- 관심사를 분리하는 가장 강력한 도구
- 언어 차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장이다.
테스트 주도 시스템 아키텍처 구축
- 애플리케이션 도메인 논리를 POJO로 작성할 수 있다면, 즉 코드 수준에서 아키텍처 관심사를 분리할 수 있다면, 진정한 테스트 주도 아키텍처 구축이 가능해지다.
- 좋은 API는 걸리적거리지 않아야 한다. 그래야 팀이 창의적인 노력을 사용자 스토리에 집중한다.
그리하지 않으면 아키텍처에 발이 묶여 고객에게 최적의 가치를 효율적으로 제공하지 못한다.
의사 결정을 최적화하라
- 모듈을 나누고 관심사를 분리하면 지엽적인 관리와 결정이 가능해진다.
- 가장 적합한 사람에게 책임을 맡기면 가장 좋다.
- 성급한 결정은 불충분한 지식으로 내린 결정이다. 가능한 마지막 순간까지 결정을 미루는 방법이 최선이다.
명백한 가치가 있을 때 표준을 현명하게 사용하라
시스템은 도메인 특화 언어가 필요하다
- DSL은 간단한 스크립트 언어나 표준 언어로 구현한 API를 가리킨다.
- 좋은 DSL은 도메인 개념과 그 개념을 구현한 코드 사이에 존재하는 '의사소통 간극'을 줄여준다.
- 효과적으로 사용한다면 DSL은 추상화 수준을 코드 관용구나 디자인 패턴 이상으로 끌어올린다.
시스템을 설계하든 개별 모듈을 설계하든, 실제로 돌아가느느 가장 단순한 수단을 사용해야 한다는 사실을 명심하자.
참조
https://refactoring.guru/ko/design-patterns/abstract-factory