- 높은 추상화 수준, 즉 시스템 수준에서도 깨끗함을 유지하는 방법을 살펴본다.
시스템 제작과 시스템 사용을 분리하라.
-
제작 ( Construction ) 과 사용 ( Use ) 는 아주 다르다.
-
소프트웨어 시스템은 ( 애플리케이션 객체를 제작하고 의존성을 서로 연결하는 ) 준비 과정과 ( 준비과정 이후에 이어지는) 런티암 로직을 분리해야한다.
-
시작 단계는 모든 애플리케이션이 풀어야할 관심사다.
-
관심사 분리는 가장 오래되고 가장 중요한 설계 기법 중 하나
-
초기화 지연 ( 레이지 이니셜라이제이션 ) 혹은 계산 지연 ( 레이지 에볼루션 ) 기법
- 객체 null 체크후 null 일 경우만 객체 생성함.
- 장점은 있다 null 을 반환하지 않는다. 객체 생성시간이 늦어져서 어플리케이션을 시작하는 시간이 빨라진다.
- 단점
- 메서드가 생성자와 , 생성자 인수에 의존하게 된다.
- 테스트도 문제
- 객체가 무거운 객체라면 단위 테스트에서 메서드를 호출하기전에 적절한 테스트 전용 객체 ( Mock Object) 를 할당해야 한다.
- 또한 일반 런타임 로직에다 객체 생성 로직을 섞어놓은 탓에 모든 실행경로도 테스트해야 한다. ( 객체가 null인 경로와 null이 아닌 경로 )
- 책임이 둘 ( null 일 경우 , null이 아닐 경우) 일 경우는 단일책임원칙에 위배된다.
- 저런 기법으로 모듈성을 깨지 말자.
- 설정 논리는 일반 실행 논리와 분리해야 모듈성이 높아진다.
메인 분리
- 생성과 사용을 분리하는 방법중 하나
- 생성 코드는 main이나 main이 호출하는 모듈로 옮기고 사용은 다른쪽에서한다.
- 이러면 다른쪽은 main을 보지 않는다. ( 생성 과정을 모른다 )
팩토리
- 객체가 생성되는 시점을 애플리케이션이 결정
- Abstract factory 패턴을 사용
- 구체적인 객체 생성 방법은 몰라도 생성되는 시점을 완벽하게 통제.
- 생성자 인수역시 넘길수 있음.
의존성 주입
- 사용과 제작을 분리하는 강력한 메커니즘 중 하나
- 스프링의 IOC 그것이다.
- 스프링은 특수 컨테이너를 사용한다.
확장
-
점차 기능이 늘어남.
-
처음부터 올바르게 시스템을 만들 수 있다는 말은 미신이다.
-
새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다.
-
이것이 반복적이고 점진적인 애자일 방식의 핵심
-
TDD와 리팩토링으로 인해 얻어지는 깨끗한 코드는 코드 수준에서 시스템을 조정하고 확장하기 쉽게 만든다.
-
시스템과 소프트웨어는 다르다. 소프트웨어는 관심사를 적절히 분리해 관리 한다면 점진적으로 발전할수 있다.
-
컨테이너와 비지니스 로직이 강하게 결합되어 있다면 독자적인 단위테스트가 어렵고
-
클래스를 생성할때는 컨테이너에서 파생해야 되며 컨테이너가 요구하는 다양한 생명주기 메서드도 제공해야 한다.
-
DTO는 구조체며 메소드가 없다.
횡단 관심사
-
영속성과 같은 관심사는 애플리케이션의 자연스러운 객체 경계를 넘나드는 경향이 있다.
-
모듈화한 영속성 프레임워크와 모듈화한 도메인논리가 세밀한 단위로 겹친다.
-
AOP에서 관점이라는 모듈구성개념 은 특정관심사를 지원하려면 시스템에서 특징 지점들이 동작하는 방식을 일관성 있게 바꿔야 한다.
-
AOP의 진정한 가치는 시스템 동작을 간결하고 모듈화된 방식으로 명시하는 능력
자바 프록시
- 개별 객체나 클래스에서 메서드 호출을 감싸는 경우가 좋은 예.
- jdk에서는 동적프록시는 api만 제공
- 클래스 프록시를 사용하려면 cglib , asm ,javassis등과 같은 바이트코드 처리 라이브러리가 필요
- 단순한 예제에도 코드가 많아지며 제법 복잡해진다.
- 프록시를 사용하면 깨끗한 코드를 작성하기 어렵다
- 프록시는 AOP처럼 시스템 단위로 실행지점을 명시할수도 없다.
- ( 프록시 패턴 )
순수 자바 AOP 프레임워크
- 의존성이 적으면 테스트가 쉬워진다.
- 순수자바 AOP 프레임워크는 스프링관련된 코드가 없어서 스프링과 사실상 독립적이다.
- 아까 위에 나왔던 컨테이너와 비지니스로직의 결합이 없어진다.
- ( 이게 자바 프록시보다 낫다는 말 )
AspecJ
- 관심사를 관점으로 분리하는 가장 강력한 도구
- 언어차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장
- 관점을 분리하는 강력하고 풍부한 도구 집합을 제공하지만 새 도구를 사용하고
- 새문법과 사용법을 익혀야하는 단점이 존재.
테스트 주도 시스템 아키텍처 구축
-
관점 ( 혹은 유사한 개념으로 ) 관심사를 분리하는 방식은 그 위력이 막강하다.
-
어플리케이션 도메인 논리를 POJO로 작성할 수 있다면.
-
즉 코드 수준에서 아키텍처 관심사를 분리할 수 있다면 진정한 테스트 주도 아키텍처 구축이 가능해진다.
-
세계최대의 웹사이트들은 고도의 자료 캐싱, 보안 , 가상화등을 이용해 아주 높은 가용성과 성능을 효율적이고도 유연하게 달성했다.
-
설계가 최대한 분리되어 각 추상화 수준과 범위에서 코드가 적당히 단순하기 때문이다.
-
최선의 시스템 구조는 각기 POJO객체로 구현되는 모듈화된 관심사 영역 ( 도메인 ) 으로 구성한다.
-
이렇게 서로다른 영역은 해당 영역코드에 최소한의 영향을 미치는 관점이나 유사한 도구를 사용해 봉합한다.
-
이런 구조 역시 코드와 마찬가지로 테스트 주도 기법을 적용할 수 있다.
의사결정을 최적화 하라
- 최대한 정보를 모아 가능한 마지막 순간까지 결정을 미뤄라
- 관심사를 모듈로 분리한 POJO 시스템은 기민함을 제공한다.
- 이런 기민함 덕택에 최신 정보에 기반해 최선의 시점에 최적의 결정을 내리기가 쉬워진다.
- 또한 결정의 복잡성도 줄어든다.
- ( 뭔가 만들면서 선택지를 점점 제거해간다는 느낌 )
명백한 가치가 있을때 표준을 현명하게 사용하라
- 너무 과장되게 포장된 표준은 사용하지 않는 것이 좋다.
- 표준을 사용하면 아이디어와 컴포넌트를 재사용하기 쉽고, 적절한 경험을 가진 사람을 구하기 쉬우며, 좋은 아이디어를 캡슐화하기 쉽고, 컴포넌트를 엮기 쉽다.
- 하지만 표준을 만드는 시간이 너무 오래걸릴 수 있다.
시스템은 도메인 특화 언어가 필요하다.
-
DSL은 간단한 스크립트 언어나 표준 언어로 구현한 API
-
좋은 DSL은 도메인 개념과 그 개념을 구현한 코드 사이에 존재하는 의사소통의 간극을 줄여준다.
-
애자일 기법이 팀과 프로젝트 이해관계자 사이에 의사소통 간극을 줄여주듯이.
-
효과적으로 사용한다면 DSL은 추상화 수준을 코드 관용구나 디자인 패턴 이상으로 끌어올린다.
-
그래서 개발자가 적절한 추상화 수준에서 코드 의도를 표현할 수 있다.
-
DSL을 사용하면 고차원 정책에서 저차원 세부사항에 이르기까지 모든 추상화 수준과 모든 도메인을 POJO로 표현할 수 있다.
결론
-
시스템 역시 깨끗해야 한다.
-
( 보기 좋아야 된다는 말 , solid 원칙을 지켜야 된다는 말)
-
도메인 논리가 흐려지면 제품 품질이 떨어진다.
-
기민성도 떨어진다.
-
기민성이 떨어지면 생산성이 낮아져 TDD가 제공하는 이점도 사라진다.
-
모든 추상화 단계에서 의도는 명확히 표현해야 한다.
-
POJO를 이용해 관심사를 분리하자
-
( Entity를 포조로 )
-
시스템을 설계하든 개별 모듈을 설계하든, 실제로 돌아가는 가장 단순한 수단을 사용해야 한다는 사실을 명심하자.