"복잡성은 죽음이다. 개발자에게서 생기를 앗아가며, 제품을 계획하고 제작하고 테스트하기 어렵게 만든다."
-레이 오지, 마이크로소프트 CTO
How Would You Build a City?
적절한 추상화와 모듈화
Separate Constructing a System from Using It
제작(Construction)과 사용(Use)은 아주 다르다는 사실을 명심하라.
public Service getService() {
if (service == null)
service = new MyServiceImpl(...); // 모든 상황에 적합한 기본값일까?
return service;
}
Separation of Main
시스템 생성과 시스템 사용을 분리하는 방법으로, 생성과 관련한 코드는 모두 main이나 main이 호출하는 모듈로 옮기고, 애플리케이션은 모든 객체가 생성되었고 모든 의존성이 연결되었다고 가정한다.
Factories
때때로 객체가 생성되는 시점을 애플리케이션이 결정할 필요도 있는데, 이때는 추상 팩토리 패턴을 사용한다.
Dependency Injection
사용과 제작을 분리하는 강력한 메커니즘 중 하나로, 제어 역전(Inversion of Control, IoC)기법을 의존성 관리에 적용한 메커니즘이다.
의존성을 주입하는 setter 메서드나 생성자 인수를 제공한다.
DI 컨테이너는 필요한 객체의 인스턴스를 만든 후 생성자 인수나 설정자 메서드를 사용해 의존성을 설정한다.
스프링 프레임워크는 가장 널리 알려진 자바 DI 컨테이너를 제공한다.
Scaling Up
소프트웨어 시스템은 물리적인 시스템과 다르다.
관심사를 적절히 분리해 관리한다면 소프트웨어 아키텍처는 점진적으로 발전할 수 있다.
Cross-Cutting Concerns
트랜잭션, 보안, 일부 영속적인 동작은 소스 코드가 아니라 배치 기술자에서 정의한다.
다음은 횡단 관심사 해결을 위한 3가지 방법이다.
Java Proxies
개별 객체나 클래스에서 메서드 호출을 감싸는 경우처럼 단순한 상황에 적합하다.
Pure Java AOP Frameworks
순수 자바 관점을 구현하는 스프링 AOP, JBoss AOP 등과 같은 여러 자바 프레임워크는 내부적으로 프록시를 사용한다.
AspectJ Aspects
AspectJ는 언어 차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장이다.
Test Drive the System Architecture
최선의 시스템 구조는 각기 POJO 객체로 구현되는 모듈화된 관심사 영역으로 구성된다. 이렇게 서로 다른 영역은 해당 영역 코드에 최소한의 영향을 미치는 관점이나 유사한 도구를 사용해 통합한다. 이런 구조 역시 코드와 마찬가지로 테스트 주도 기법을 적용할 수 있다.
Optimize Decision Making
관심사를 모듈로 분리한 POJO 시스템은 기민함을 제공한다. 이런 기민함 덕택에 최신 정보에 기반해 최선의 시점에 최적의 결정을 내리기가 쉬워진다. 또한 결정의 복잡성도 줄어든다.
Use Standard Wisely, When They Add Demostrable Value
표준을 사용하면 아이디어와 컴포넌트를 재사용하기 쉽고, 적절한 경험을 가진 사람을 구하기 쉬우며, 좋은 아이디어를 캡슐화하기 쉽고, 컴포넌트를 엮기 쉽다. 하지만 때로는 표준을 만드는 시간이 너무 오래 걸려 업계가 기다리지 못한다. 어떤 표준은 원래 표준을 제정한 목적을 잊어버리기도 한다.
Systems Need Domain-Specific Languages
도메인 특화 언어(Domain-Specific Language, DSL)를 사용하면 고차원 정책에서 저차원 세부사항에 이르기까지 모든 추상화 수준과 모든 도메인을 POJO로 표현할 수 있다.
시스템은 역시 깨끗해야 한다.
POJO를 작성하고 각 구현 관심사를 분리하여 모든 추상화 단계에서 의도는 명확히 표현해야 한다.
시스템을 설계하든 개별 모듈을 설계하든, 실제로 돌아가는 가장 단순한 수단을 사용해야 한다는 사실을 명심하자.
📖 느낀점
이번 장은 모두 다 이해하고 읽었다고 할 수 없다.
조금 더 지식의 폭이 넓어지고 다시 펼쳐봐야겠다.