ReactMasters / study

스터디 기록
1 stars 0 forks source link

클린코드 11장 시스템 #46

Open 56aiden90 opened 1 year ago

56aiden90 commented 1 year ago

Chapter 11 System

도입

클린 코딩은 낮은 추상화(abstraction) 단계에서의 모듈화와 관심분리(separation of concerns)에 도움을 준다. 그렇다면 높은 추상화 즉 시스템 단계에서의 모듈화와 관심분리는 어떻게 구현할 수 있을까?

시스템 실행(startup)과 시스템 사용(use)을 구분하라.

  1. 안티패턴 예시

시스템 실행은 그 자체로 하나의 관심(concern)이다. 관심분리의 원칙에 따라 시스템 실행은 당연히 어플리케이션의 다른 관심들로부터 분리되어야 한다. 다음 예를 보자.

class Controller {
    service: Service | null = null;

    getService(): Service {
        if (this.service === null){
            this.service = new ServiceImpl(...constructorArgs);
            return this.service;
        }
    }
}

장점

단점

위의 예시와 같은 lazy init은 어플리케이션의 모듈화를 저해하고 SRP에 위배된다

  1. main 함수를 통한 실행과 사용 분리
    1. 시스템 실행을 담당하는 main 함수 만들어라. main 함수는 런타임 시 필요한 인스턴스들을 생성하는 역할을 한다.
    2. 생성해야하는 인스턴스 타입이 런타임에 결정되는 경우 Abstract Factory 패턴으로 해결할 수 있다.
  2. 의존성 주입을 통한 실행과 사용 분리
    1. IoC(Inversion of Control)는 어떤 오브젝트가 갖고 있는 부차적인 기능을 해당 기능만을 전문적으로 담당하는 다른 오브젝트에게 전가시킴으로써 SRP를 달성하는 기법이다.
    2. Dependency Injection은 IoC를 의존성 관리에 적용시킨 것이다. 즉, 어떤 오브젝트의 의존성들을 인스턴스화하는 기능을 다른 오브젝트에게 맡기는 것을 DI라고 한다.
    3. DI를 가능케 하는 세 가지 핵심 요소
      1. 의존성 관계를 설정하기 위한 configuration
      2. 의존성을 넘겨 받을 수 있는 setter 혹은 생성자
      3. 의존성을 주입하는 컨테이너

확장 가능한 시스템을 만들어라

  1. 안티패턴 예시

    1. EJB(Enterprise JavaBeans) EJB는 대형 어플리케이션을 위해 고안된 설계 스펙이다. 구성 요소는 아래와 같다.

    EJB Local/Remote Interface

    클라이언트가 EJB 어플리케이션를 사용하기 위해 필요한 API를 제공

    public interface BankLocal extends java.ejb.EJBLocalObject {
        String getName() throws EJBException;
        void setName(String name) throws EJBException;
    
        Account getAccount() throws EJBException;
        void setAccount(Account account) throws EJBException;
        void addAccount(AccountDTO accountDTO) throws EJBException;
    }

    **EJB Entity Bean**

    관계형 데이터베이스의 레코드를 메모리 상에 로드하기 위한 클래스

    public abstract class Bank implements javax.ejb.EntityBean {
        public abstract String getName();
        public abstract void setName(String name);
    
        public Account getAccount();
        public void setAccount(Account account);
        public void addAccount(AccountDTO accountDTO){
            InitialContext context = new InitialContext();
            AccountHomeLocal accountHome = context.lookup("AccountHomeLocal");
            AccountLocal account = accountHome.create(accountDTO);
            this.setAccount(account);
        }
        // EJB container logic
        ...
        // The rest
        ...
    }

    **EJB Local/Remote Home Interface**

    클라이언트가 EJB Bean을 생성, 제거, 검색할 수 있는 API를 제공

    ****XML 파일****

    데이터베이스 테이블과 Entity Bean 클래스의 프로퍼티를 매핑하고, 트랜스액션 정책, 보안 정책 등을 설정하기 위한 파일

    EJB 디자인의 문제점

    • 비즈니스 로직이 컨테이너와 얽혀있다. 비즈니스 도메인을 구성하는 클래스들이 컨테이너를 상속하고 컨테이너와 관련된 라이프사이클 함수들을 구현해야 한다. 결과적으로 테스트가 어렵고, 해당 클래스들을 EJB 외의 환경에서 전혀 사용할 수 없다.
    • OOP에 적합하지 않다. bean 클래스간의 상속을 지원하지 않고, DTO 클래스들은 단순히 데이터를 담고 있을 뿐 어떠한 행동(함수)도 갖고 있지 않다.
      1. AOP
      2. Java Proxies
      3. Spring AOP / JBoss AOP
      4. AspectJ Aspects

    확장 가능한 시스템의 장점 및 주의점

    • 테스트 용이 : AOP 등으로 분리/확장 가능한 시스템을 만들면 새로운 기능을 추가하거나 테스트하기 쉽다.
    • 빠른 의사결정 : 시스템의 각 요소들이 독립적으로 모듈화 되어 있기 때문에 전문적인 의사결정을 빠르게 내릴 수 있다.
    • 증명가능 한 명확한 가치가 있는 시스템 표준을 사용하라 : 많은 팀들이 EJB가 업계 표준이라는 이유만으로 채택했다. 유행에 따라 시스템 표준을 정하지 말고 고객에게 최대한 많은 가치를 제공할 수있고, 어플리케이션 복잡도에 맞는 시스템을 도입해라.
    • 비즈니스 도메인 specific한 언어를 사용하라 : 해당 도메인 전문가의 요구사항을 제대로 이해할 수 있게 된다. 또한, 개발자들이 특정 코딩 방식이나 디자인 패턴에 종속되지 않는 시스템 레벨에서 통용가능한 코드를 작성할 수 있다.