Post

[Book - Clean Code] 11. 시스템

의존성 주입

사용과 제작을 분리하는 강력한 메커니즘 중 하나가 DI(Dependency Injection)이다.
DI는 IoC(Inversion of Control) 기법을 의존성 관리에 적용한 메커니즘이다.

IoC(제어 역전)에서는 한 객체가 맡은 보조 책임을 새로운 객체에게 전적으로 떠넘긴다.
새로운 객체는 넘겨받은 책임만 맡으므로 SRP(Single Responsibility Principle)를 지키게 된다.

의존성 관리 맥락에서 객체는 의존성 자체를 인스턴스로 만드는 책임은 지지 않는다.
대신에 이런 책임을 다른 전담 메커니즘에 넘겨야만 한다.
그렇게 함으로써 제어를 역전한다.

초기 설정은 시스템 전체에서 필요하므로 대개 책임질 메커니즘으로 main 루틴이나 특수 컨테이너를 사용한다.

DI 컨테이너는 필요한 객체의 인스턴스를 만든 후 생성자 인수나 설정자 메서드를 사용해 의존성을 설정한다.
실제로 생성되는 객체 유형은 설정 파일에서 지정하거나 특수 생성 모듈에서 코드로 명시한다.

Spring Framework는 Java DI 컨테이너를 제공하며, 객체 사이 의존성은 XML 파일에 정의하고, Java 코드에서는 이름으로 특정한 객체를 요청한다.

대다수 DI 컨테이너는 필요할 때까지는 객체를 생성하지 않고, 대부분은 계산 지연이나 비슷한 최적화에 쓸 수 있도록 팩토리를 호출하거나 프록시를 생성하는 방법을 제공한다.
즉, 계산 지역 기법이나 이와 유사한 최적화 기법에서 이런 메커니즘을 사용할 수 있다.

확장

처음부터 best practice 시스템을 만들 수 있다는 믿음은 미신이다.

오늘 주어진 사용자 스토리에 맞춰 시스템을 구현해야 한다.
내일은 새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다.
즉, 이것이 반복적이고 점진적인 애자일 방식의 핵심이다.

TDD, 리팩터링, 클린 코드는 코드 수준에서 시스템을 조정하고 확장하기 쉽게 만든다.

자바 프록시

자바 프록시는 단순한 상황에 적합하다.

개별 객체나 클래스에서 메서드 호출을 감싸는 경우가 좋은 예다.

하지만 JDK에서 제공하는 동적 프록시는 인터페이스만 지원한다.
클래스 프록시를 사용하려면 CGLIB, ASM, Javassist 등과 같은 바이트 코드 처리 라이브러리가 필요하다.

자바 프록시의 단점은 코드 양과 크기이다.
다시 말해서, 프록시를 사용하면 깨끗한 코드를 작서하기 어렵다!
또한 프록시는 (진정한 AOP 해법에 필요한) 시스템 단위로 실행 지점을 명시하는 메커니즘도 제공하지 않는다.

순수 자바 AOP 프레임워크

대부분의 프록시 코드는 판박이라 도구로 자동화할 수 있다.

Spring은 비즈니스 논리를 POJO로 구현한다.
POJO는 순수하게 도메인에 초점을 맞추며, 엔터프라이즈 프레임워크에 (그리고 다른 도메인에도) 의존하지 않는다.
따라서 테스트가 개념적으로 더 쉽고 간단하다.

즉 상대적으로 단순하기 때문에 사용자 스토리를 올바로 구현하기 쉬우며 미래 스토리에 맞춰 코드를 보수하고 개선하기 편하다.

AspectJ 관점

관심사를 관점으로 분리하는 가장 강력한 도구는 AspectJ 언어로,
언어 차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장이다.

테스트 주도 시스템 아키텍처 구축

관점으로 관심사를 분리하는 방식은 그 위력이 막강하다.

애플리케이션 도메인 논리를 POJO로 작성할 수 있다면, 즉 코드 수준에서 아키텍처 관심사를 분리할 수 있다면, 진정한 테스트 주도 아키텍처 구축이 가능해진다.

의사 결정을 최적화하라

관심사를 모듈로 분리한 POJO 시스템은 기민함을 제공한다.
이런 기민함 덕택에 최신 정보에 기반해 최선의 시점에 최적의 결정을 내리기가 쉬워진다.
또한 결정의 복잡성도 줄어든다.

This post is licensed under CC BY 4.0 by the author.

© Yn3. Some rights reserved.