코딩하는 털보

클린 코드, 11. 시스템 본문

Book/클린 코드

클린 코드, 11. 시스템

이정인 2021. 8. 25. 13:30

클린 코드, 11. 시스템

시스템 수준에서 깨끗함을 유지하는 방법, 높은 추상화 수준.

  • 시스템 제작과 시스템 사용을 분리하라
    소프트웨어 시스템은 준비 과정과 런타임 로직을 분리해야 한다.
    좀스럽고 손쉬운 기법으로 모듈성을 깨서는 안 된다. 설정 로직을 일반 런타임 로직과 분리하면 모듈성이 높아진다.

    • SOC(관심사 분리)
      프로그램을 기능 면에서 가능한 중복이 아닌 여러 모듈로 명확히 나누는 것
      SOC를 적용하면 자연스럽게 단일 책임 원칙, 개방 폐쇄 원칙, 인터페이스 분리 원칙을 달성하게 된다.

    • 초기화 지연(Lazy initialization)

        public FieldType getField() {
          if (fieldType == null) {
            fieldType = new FieldType();
          }
          return fieldType;
        }

      실제로 필요할 때까지 객체를 생성하지 않는 방법. 부하가 적고 null을 절대 반환하지 않는다는 장점이 있지만 메서드가 FieldType 객체에 의존하고 있고 null인 경로와 null이 아닌 경로 모두를 테스트해야 하며 SRP를 위반한다.
      가장 큰 문제는 null인 경우 기본적으로 생성되는 클래스가 과연 적합한 클래스인지 알 수 없다는 것. 사실 클라이언트 클래스는 알아야 할 필요도 없어야 한다.

    • Main 분리
      시스템 생성과 시스템 사용을 분리하는 한가지 방법.
      main 함수에서 시스템에 필요한 객체를 생성하고 애플리케이션은 모든 객체가 생성되었고 모든 의존성이 연결되었다고 가정하고 객체를 사용한다.

    • 팩토리
      abstract factory 패턴을 사용하면 애플리케이션이 팩토리 인터페이스를 통해서 객체를 생성하는 시점은 정할 수 있지만 객체를 생성하는 코드는 감출 수 있다.

    • 의존성 주입(Dependency Injection)
      의존성 주입은 제어 역전(IoC) 기법을 의존성 관리에 적용하여 사용과 제작을 분리하는 강력한 메커니즘 중 하나이다.
      의존성 관리에 대한 책임을 전적으로 전담하는 'main' 루틴이나 특수 컨테이너를 사용한다.
      진정한 의존성 주입에서는 클래스는 완전히 수동적이며 setter 메서드나 생성자 인수를 제공할 뿐 의존성을 해결하려고 시도하지 않는다.
      DI 컨테이너는 필요한 인스턴스를 만든 후 제공되는 setter 메서드나 생성자 인수를 이용하여 의존성을 설정한다. (제어 역전(IoC))

  • 확장
    테스트 주도 개발 리팩터링, 깨끗한 코드는 코드 수준에서 시스템을 조정하고 확장하기 쉽게 만든다.
    시스템 수준에서의 확장은 관심사의 분리가 중요하다. 비즈니스 로직이 덩치 큰 컨테이너와 밀접하게 결합되어 있다면 독자적인 단위 테스트가 어렵고 확장도 하기 어렵다.
    관심사는 AOP의 관점(Aspect)이라는 모듈 구성 개념("특정 관심사를 지원하려면 시스템에서 특정 지점들이 동작하는 방식을 일관성 있게 바꿔야 한다")으로 분리할 수 있다.

  • 자바 Aspect 메커니즘

    • 자바 프록시
      프록시 패턴 : 실제 기능을 수행하는 객체 대신 가상의 객체를 사용해 로직의 흐름을 제어하는 디자인 패턴
      프록시는 깨끗한 코드를 작성하기 어렵고 시스템 단위로 실행 '지점'을 명시하는 메커니즘을 제공하지 않는다.

    • 순수 자바 AOP 프레임워크
      순수 자바 Aspect를 구현하는 스프링 AOP, JBoss AOP등과 같은 여러 자바 프레임워크는 내부적으로 프록시를 사용하며 프록시 패턴을 자동화 할 수 있다.
      스프링은 비즈니스 코드를 POJO로 구현한다. 클라이언트는 도메인 객체에서 직접 메서드를 호출하는 것 같지만 실제로는 POJO의 기본 동작을 확장한 중첨 DECORATOR 객체 집합의 가장 외곽과 통신한다. 그렇기 때문에 비즈니스 코드에 스프링 관련 자바 코드가 거의 필요 없으므로 애플리케이션은 사실상 스프링과 독립적이다. 즉, 코드를 테스트하고 개선하고 보수하기가 쉬워진다.

    • AspectJ

      AspectJ는 언어 차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장이다.
      AspectJ는 관점을 분리하는 강력하고 풍부한 도구를 제공하지만 새 도구를 사용하고 새 언어 문법과 사용법을 익혀야 한다는 단점이 있다. (AspectJ '애너테이션 폼'으로 어느정도 완화되었다.)

    • 요약
      최선의 시스템 구조는 각기 POJO 객체로 구현되는 모듈화된 관심사 영역(도메인)으로 구성된다. 이렇게 서로 다른 영역은 해당 영역 코드에 최소한의 영향을 미치는 관점이나 유사한 도구를 사용해 통합한다. 이런 구조 역시 코드와 마찬가지로 테스트 주도 기법을 적용할 수 있다.

Comments