## 목차 ##



## 도시를 세운다면? ##

  • 도시는 한 사람의 힘으로 세우고 관리하기는 무리다.

    • 수도 관리 팀, 교통 관리 팀, 전력 관리 팀 등 각 분야를 담당하는 팀이 있어 잘 돌아간다.
    • 도시가 잘 돌아가는 이유는 적절한 추상화와 모듈화 때문이다.
    • 전기를 쓰기위해 발전설비의 세세한 사항까지 모두 알 필요가 있는가? 사용하기위한 적절한 인터페이스가 존재하기 때문에 사용자는 편안하다.
    • 소프트웨어팀도 도시처럼 구성한다.
  • 이번 장에서는 함수, 클래스를 넘어 시스템 수준에서도 깨끗함을 유지하는 방법을 살펴본다.



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

  • 제작은 사용과 다르다.

  • 소프트웨어 시스템은 준비과정(프로그램 구동준비 - 프로그램 전반적으로 사용하는 객체생성, 초기설정 등)과 런타임 로직(프로그램 동작 중 실행되는 로직)을 분리해야한다.

    • 관심사 분리
    • 관심사 분리는 소프트웨어에서 가장 중요한 설계기법들 중 하나다.
public Service getService() {
    //초기화 지연을 사용한 객체 생성 및 할당
    if (service == null)
        service = new MyServiceImpl(...); // 모든 상황에 적합한 기본값일까?
    return service;
}
  • 초기화 지연(lazy initialization)
    • 객체가 필요한 시점에 생성하는 방법이다.
    • 프로그램 초기화 시에 객체를 생성하지 않으므로 초기 로딩시간이 빨라진다.
    • 어떠한 경우에도 null을 반환하지 않는다.
    • 그러나 정말로 필요하지 않으면 초기화 지연은 하지마라!


  • Main 분리
    • 관심사 분리의 한 가지 방법
    • 생성과 관련된 코드는 main이나 main이 호출하는 모듈로 옮긴다.
    • 나머지 시스템에서는 필요한 모든 객체가 생성되고 의존성이 연결되었다고 가정한다.

main_separation


  • 팩토리
    • 객체가 필요한 시점 애플리케이션이 객체 생성
    • 그러나 애플리케이션은 객체 생성의 세부사항을 알지 못한다.

factory_separation

주문처리 시스템에서 애플리케이션(orderProcession)이 주문(LineItem)을 생성해 추가한다. 이 때 팩토리 패턴을 사용하면 객체(주문) 생성시점은 애플리케이션이 결정하면서도 객체 생성 코드는 애플리케이션이 모른다.




## 확장 ##

  • 군락은 마을로, 마을은 도시로 성장한다.

    • 이처럼 소프트웨어도 성장한다.
  • 마을이 커지며 6차선 도로 확장공사를 할때가 되면…

    • 왜 처음부터 크게 만들지 않았을까?
    • 처음부터 조그마한 마을이 커질거란 기대로 6차선 도로를 뚫을 순 없는 것이다.
  • 소프트웨어도 '처음부터 올바르게' 나중에 수정할 필요가 전혀 없도록 시스템을 만들 수 있다는 믿음은 미신이다.

    • 애자일 개발, TDD, 리팩토링을 통해 시스템은 코드 수준에서 확장된다.
    • '확장이 필요 없도록'이 아닌 '확장이 쉽도록'하는 시스템을 만들어야한다.
    • 관심사 분리를 통해 설계한 소프트웨어 아키텍처는 점진적으로 발전할 수 있다.
  • AOP(Aspect Oriented Programming)

    • 관점 지향 프로그래밍
    • 애플리케이션 전체에 걸쳐 반복적으로 쓰이는 부가적인 알고리즘, 혹은 코드를 모듈화하여 재사용
    • 흩어져 있던 관심사(로직)이라하여 흩어진 관심사(cross-cutting concerns)라 한다.
    • 흩어진 관심사를 모듈화하고 핵심 비지니스 로직에서 분리하여 재사용하는 것이 AOP의 취지이다.

aop



## 자바 프록시 ##

  • 프록시(Proxy) : 대변인

  • 자바에서 제공하는 AOP 매커니즘

  • 프록시 패턴에서는 객체가 아닌 객체를 직접 조작하는 대리 객체를 통해 객체와 상호작용한다.

    • 객체 생성과 관련된 부가적인 처리(흐름제어)를 한다.
    • 흐름제어만 할 뿐 결과값을 조작하거나 변경시키면 안된다.
    • 비지니스 로직의 변경 없이도 기능을 추가하거나 수정할 수 있다.
//인터페이스
public interface CommandExecutor {
    public void runCommand(String cmd) throws Exception ;
}

//프록시 클래스
public class CommandExecutorProxy implements CommandExcutor {
    private boolean isAdmin;
    private CommandExecutor executor;

    //프록시 객체 생성 시 유저 id와 pw를 넘겨받아 부가적인 처리를 한다.
    public CommandExecutorProxy(String user, String pwd) {
        if ( "seotory".equals(user) && "pw".equels(pwd) ) {
            isAdmin = true;
        }
        executor = new CommandExcutorImpl();
    }

    @Override
    public void runCommand(String cmd) throws Exception {
        if (isAdmin) {
            executor.runCommand(cmd);
        } else {
            if (cmd.trim().startsWith("rm")) {
                throw new Exception("rm is only admin");
            } else {
                executor.runCommand(cmd);
            }
        }
    }
}
  • 프록시 패턴을 사용하면 아래와 같은 것이 가능

    • 가상 프록시 : 필요 시점까지 실제 객체를 생성하지 않고 통제하여 메모리 절약
    • 원격 프록시 : 다른 머신에 있는 객체 사용
    • 보호 프록시 : 객체에 대한 액세스 권한 부여
    • 정교한 참조 : 객체 생성과 관련하여 추가적인 처리
  • 코드 양이 많아지며 깨끗한 코드를 작성하기 어렵다.



## 순수 자바 AOP 프레임워크 ##



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

  • POJO를 통해 아키텍처 관심사를 엔터프라이즈 관심사로부터 분리한다면 진정한 TDD가 가능하다.
    • BDUF(Big Design Up Front)가 필요없다. 오히려 해롭다.



## 의사 결정을 최적화하라 ##

  • 모듈을 나누고 관심사를 분리하면 효율적인 관리 및 결정이 가능하다.
    • POJO 시스템은 관심사를 효율적으로 분리하고 집중할 수 있게 해주어 최적의 결정을 위한 복잡성이 줄어든다.



## 명백한 가치가 있을 때 표준을 현명하게 사용하라 ##

  • EJB2(Enterprise Java Bean 2)는 단지 표준이라는 이유만으로 사람들이 사용했다.
    • 심지어 가벼운 설계로 충분했을 프로젝트에도..
    • 표준을 사용하면 재사용이 쉽고, 경력자를 구하기 쉬우며 캡슐화도 쉽다.
    • 그러나 그만한 사용 가치가 있는지 잘 판단하고 사용해야한다.

+ Recent posts