• 높은 추상화 수준, 즉 시스템 수준에서도 깨끗함을 유지하는 방법을 살펴본다.

시스템 제작과 시스템 사용을 분리하라.

  • 제작 ( 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를 포조로 )

  • 시스템을 설계하든 개별 모듈을 설계하든, 실제로 돌아가는 가장 단순한 수단을 사용해야 한다는 사실을 명심하자.

'book > 클린코드' 카테고리의 다른 글

13장 동시성  (0) 2021.01.05
12장 - 창발성  (0) 2021.01.03
10장 - 클래스  (0) 2020.12.22
9장 - 단위 테스트  (0) 2020.12.02
8장 - 경계  (0) 2020.11.30

+ Recent posts