[클린코드] 11장 시스템

이준기·2022년 2월 11일
0

깨끗한 코드를 구현하면 낮은 추상화 수준에서 관심사를 분리하기 쉬워진다.

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

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

  • 소프트웨어 시스템은 (애플리케이션 객체를 제작하고 의존성을 서로 '연결'하는) 준비 과정과 (준비 과정 이후에 이어지는) 런타임 로직을 분리해야 한다.
  • 시작 단계는 모든 애플리케이션이 풀어야 할 관심사다. 관심사 분리는 우리 분야에서 가장 오래되고 가장 중요한 설계 기법중 하나이다.

Main 분리

  • 시스템 생성과 시스템 사용을 분리하는 한 가지 방법으로, 생성과 관련된 코드는 모두 main이나 main이 호출하는 모듈로 옮긴다.
  • main 함수에서 시스템에 필요한 객체를 생성한 후 이를 애플리케이션에 넘긴다. 애플리케이션은 그저 객체를 사용할 뿐 이다.
  • 즉, 애플리케이션은 main이나 객체가 생성되는 과정을 전혀 모른다. 단, 모든 객체가 적절히 생성되었다고 가정한다.

팩토리

  • 객체가 생성되는 시점을 애플리케이션이 결정할 필요가 있을때는 ABSTRACT FACTORY 패턴을 사용한다.
  • 애플리케이션이 Factory 인터페이스의 인스턴스를 생성하게 함!
  • 마찬가지로 모든 의존성이 main에서 애플리케이션으로 향하게 된다.
  • 애플리케이션은 객체가 생성되는 구체적인 방법은 모르지만 생성되는 시점은 완벽하게 통제 가능하게 된다.

추상 팩토리 패턴?

  • 많은 수의 연관된 서브 클래스를 특정 그룹으로 묶어 한번에 교체할 수 있도록 만든 디자인 패턴
  • 예를 들어, 검은 테마와 하얀 테마가 있다고 가정할때, 검정색 테마를 사용할 경우엔 검은색 버튼과 검은색 체크박스 등등이 보일테고 하얀색 테마를 사용할 경우엔 하얀색 버튼과 하얀색 체크박스 등등이 보일 것이다.
  • 이처럼 다양한 구성 요소 별로 '객체의 집합'을 생성해야 할 때 유용하다.

의존성 주입

사용과 제작을 분리하는 강력한 매커니즘 중 하나가 의존성 주입 이다. 의존성 주입은 제어 역전 기법을 의존성 관리에 적용한 메커니즘이다.

  • 제어 역전 에서는 한 객체가 맡은 보조 책임을 새로운 객체에게 전적으로 떠넘기고, 새로운 객체는 넘겨받은 책임만 맡으므로 SRP (단일 책임 원칙) 를 지키게 된다.
  • 의존성 관리 맥락 에서 객체는 의존성 자체를 인스턴스로 만드는 책임을 지지 않고, 다른 '전담' 메커니즘에 넘긴다. 이렇게 제어 역전.
MyService myService = (MyService)(jndiContext.lookup("NameOfMyService"));

lookup 메소드가 반환되는 객체의 유형을 제어하지 않음.

  • 대신 setter나 생성자 인수를 통하여 의존성 주입 ! -> 전담 메커니즘
  • 스프링 프레임워크는 자바 DI 컨테이너를 사용하며 객체 사이의 의존성은 XML 파일에 정의한다.

확장

  • 우리는 오늘 주어진 사용자 스토리에 맞춰 시스템을 구현해야 한다. 그리고 내일은 새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다.
  • 이것이 반복적이고 점진적인 애자일 방식 의 핵심이다. 테스트 주도 개발 ( TDD ), 리팩토링, 깨끗한 코드는 코드 수준에서 시스템을 조정하고 확장하기 쉽게 만든다.
  • 하지만 시스템 수준에서는 다르다. 시스템 아키텍처는 관심사를 적절히 분리 해 관리해야 점진적으로 발전할 수 있다.

횡단(cross-cutting) 관심사

  • 현실적으로는 영속성 방식을 구현한 코드들은 온갖 객체로 흩어진다.
  • AOP(관점 지향 프로그래밍)를 활용하면 횡단 관심사에 대처해 모듈성을 확보할 수 있다.

AOP에서 관점 이라는 모듈 구성 개념은 "특정 관심사를 지원하려면 시스템에서 특정 지점들이 동작하는 방식을 일관성 있게 바꿔야 한다" 라고 명시한다.

자바에서 사용하는 관점 혹은 관점과 유사한 메커니즘으로는 자바 프록시, 순수 자바 AOP 프레임워크, AspectJ 관점이 있다고 한다.

POJO란?

특정 '기술'에 종속되어 동작하는 것이 아닌 순수한 자바객체.

  • 객체지향 설계에 장점들을 잃어버리지 않기 위해 POJO를 지향함

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

애플리 케이션 도메인 논리를 POJO로 작성할 수 있다면, 즉 코드 수준에서 아키텍처 관심사를 분리할 수 있다면, 진정한 테스트 주도 아키텍처 구축이 가능해진다.

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

의사 결정을 최적화하라

모듈을 나누고 관심사를 분리하면 지엽적인 관리와 결정이 가능해진다.

  • 가능한 마지막 순간까지 결정을 미루면 최선의 결정을 내릴 수 있다.
  • 분리된 POJO 시스템은 기민함을 제공한다. 기민함 덕에 최신 정보에 기반해 최선의 시점에 최적의 결정을 내리기 쉽다.

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

가볍고 간단한 설계로 충분하다면 너무 표준에 집착하지 않아도 된다.

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

DSL(Domain-Specific Language)은 간단한 스크립트 언어나 표준 언어로 구현한 API를 가리킨다. DSL로 짠 코드는 구조적인 산문처럼 읽힌다.

  • 효과적으로 사용한다면 DSL은 추상화 수준을 끌어 올려, 개발자가 적절한 추상화 수준에서 코드 의도를 표현할 수 있다.
  • 모든 추상화 수준과 모든 도메인을 POJO로 표현할 수 있다.

결론

시스템 역시 깨끗해야 한다. 깨끗하지 못한 아키텍처는 도메인 논리를 흐리며 기민성을 떨어트린다.

모든 추상화 단계에서 의도를 분명히 표현하기 위해 각 구현 관심사를 분리해야 한다.

Reference

클린 코드: 애자일 소프트웨어 장인 정신 - 로버트 마틴 지음

profile
Hongik CE

0개의 댓글