[CleanCode] -11. 시스템

Young Min Sim ·2021년 4월 26일
0

CleanCode

목록 보기
11/16

💁🏻‍♂️ 이 장에서는 높은 추상화 수준, 즉 시스템 수준에서도 깨끗함을 유지하는 방법을 살펴본다.


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

제작은 사용과 다르다.
준비 과정런타임 로직을 분리해야 한다.

즉, 객체 생성객체 사용을 분리해야 한다는 뜻인 것 같습니다.

public Service getService() {
    if (service == null)
        service = new MyServiceImpl(...); // 모든 상황에 적합한 기본값일까?
    return service;
}

발생하는 문제

  1. 초기화 지연을 사용하게 되면 구체 타입에 의존하게 되고 따라서 테스트하기 어렵다
  2. MyServiceImpl 이 모든 상황에 적합한 객체인지 모른다는 사실

체계적이고 탄탄한 시스템을 만들고 싶다면, 흔히 쓰는 좀스럽고 손쉬운 기법으로 모듈성을 깨서는 안 된다.
주요 의존성을 해소하기 위한 방식이 필요하다.

  • Main 분리
  • 팩토리

둘 다 결국 객체의 생성과 사용을 분리하라는 것을 뜻함

  • 의존성 주입
    사용과 제작을 분리하는 강력한 메커니즘 하나가 의존성 주입이다.
    제어 역전 기법을 의존성 관리에 적용한 메커니즘으로,
    제어 역전에서는 한 객체가 맡은 보조책임(객체 생성)을 새로운 객체에게 전적으로 떠넘긴다.

의존성 주입 방법

  • 생성자
  • 필드(프로퍼티)
  • 메서드

2. 확장

성장할지 모른다는 기대로 자그만 마을에 6차선을 뚫는데 들어가는 비용을 정당화할 순 없다.

마찬가지로 SW에서도 처음부터 올바르게 시스템을 만들 수 있다는 믿음은 미신이다.
대신 우리는 오늘 주어진 사용자 스토리에 맞춰 시스템을 구현해야 한다.

(처음부터 한꺼번에 다 하려기 보다는) 내일 새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다.
-> 이것이 반복적이고 점진적인 애자일 방식의 핵심이다.

켄트백의 구현패턴에서도 프로그래밍에서 추구해야 할 가치 중 단순성을 소개하며
확실하지 않은 미래의 확장을 위한 불필요하게 복잡한 패턴은 경계의 대상이라고 언급


횡단(cross-cutting) 관심사

영속성, 로그와 같이 이론적으로는 독립된 형태이지만, 코드 전체에 걸쳐 산재해있는 부분들은 AOP(관점 지향 프로그래밍)를 사용하는 것이 좋다. AOP 는 횡단 관심사에 대처해 모듈성을 확보하는 일반적인 방법론이다.

예시로 자바 프록시, 순수 자바 AOP 프레임워크, AspectJ 등이 나오는데 각각을 정확히 이해하진 못했지만,
영속성과 관련된 부분을 클라이언트로부터 모듈화하여 분리하고 기존 기능을 유지한 상태에서 확장(Decorator 패턴)

프록시 패턴
프록시: 대리자, 대변인
실제 객체를 바로 이용하는 것 대신 가상 객체에 실제 객체를 선언하여
실제 객체의 기능과 추가적인 기능을 사용함으로 써 기능의 흐름을 제어하는 디자인 패턴
https://bamdule.tistory.com/154

예제나 설명 읽어보면 결국 프록시 클래스를 Wrapper 클래스로 사용하여
간접적으로 주체 클래스(subject)에 접근하는 일반적인 패턴으로 보임

어노테이션을 이용하여 감싼다는 개념을 보고 나서 Swift 의 PropertyWrapper 가 떠올라서 AOP 와 같이 검색해봤더니
와 같이 Property Wrapper 혹은 objective-C 메서드를 이용한 AOP 지원 방법이 있습니다.

Swift 에서 Property wrapper 이용하여 AOP 흉내내기 -> 어노테이션을 메서드에 적용 못한다는 점이 아쉬운 점
objective-C 의 dynamic dispatch 를 이용하여 Swift 에서 메서드 인터셉트하기
Swift 에서 AOP에 대해


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

물리적 구조는 짓기 시작하면 극적인 변경이 힘들기 때문에 건축가는 BDUF(구현 시작 전 모든 사항을 설계하는 기법)를 취한다.
하지만 소프트웨어는 관점(Aspect)를 효과적으로 분리한다면, 극적인 변화가 가능하다.

서로 다른 영역은 해당 영역 코드에 최소한의 영향을 미치는 관점이나 유사한 도구를 사용해 통합한다.
이런 구조 역시 코드와 마찬가지로 테스트 주도 기법을 적용할 수 있다.


4. 시스템은 도메인 특화 언어가 필요하다

좋은 DSL은 도메인 개념과 그 개념을 구현한 코드 사이에 존재하는 '의사소통 간극'을 줄여준다.
도메인 전문가가 사용하는 언어로 도메인 논리를 구현하면 도메인을 잘못 구현할 가능성이 줄어든다.
효과적으로 사용한다면 DSL은 추상화 수준을 코드 관용구나 디자인 패턴 이상으로 끌어올린다.
그래서 개발자가 적절한 추상화 수준에서 코드 의도를 표현할 수 있다.

DSL: 특정 범주를 타겟하고 있는 언어
Swift 에서는 오토레이아웃을 위한 스냅킷이 있음


결론

(코드와 마찬가지로) 시스템 역시 깨끗해야 한다.
모든 추상화 단계에서 의도를 명확히 표현해야 하며
그러기 위해서는 관점 혹은 관점과 유사한 메커니즘을 적용하여 각 구현 관심사를 분리해야 한다.

0개의 댓글