클린코드(Clean Code) 11장. 시스템

클린코드(Clean Code) 11장. 시스템

11장에서는 높은 추상화 수준, 즉 시스템 수준에서도 깨끗함을 유지하는 방법에 대해서 다룹니다.

소프트웨어 시스템은

애플리케이션 객체를 제작하고 의존성을 서로 연결하는 준비 과정과 준비 과정 이후에 이어지는 런타임 로직을 분리해야 한다.

관심사 분리

모든 소프트웨어 개발의 핵심은 복잡성을 극복하는 것입니다.

여러 가지를 동시에 신경 쓰면 복잡하니까, 각각 따로 분리해서 생각하자는 내용입니다.

하지만 불행히도 대다수의 애플리케이션은 시작 단계라는 관심사를 분리하지 않습니다.

코드를 주먹구구식으로 구현할 뿐만 아니라 런타임 로직과 마구 뒤섞어 작성합니다.

전형적인 예입니다.

private Service service; public Service getService() { if(service == null) { service = new MyServiceImpl(...); } return service; }

초기화 지연( Lazy Initialization ) 혹은 계산 지연 ( Lazy Evaluation )이라는 기법이다.

장점은 여러 가지입니다.

실제로 필요할 때까지 객체를 생성하지 않으므로 불 필요한 부하가 걸리지 않습니다. 어떤 경우에도 null 포인터를 반환하지 않습니다.

하지만 getService() 메서드가 MyServiceImpl와 생성자 인수에 의존합니다.

테스트도 문제입니다.

MyServiceImpl가 무거운 객체라면 단위 테스트에서 getService 메서드를 호출하기 전에

테스트 전용 객체를 service 필드에 할당해야 합니다.

또한 일반 런타임 로직에 객체 생성 로직을 섞어 놓은 탓에 모든 실행 경로도 테스트해야 합니다.

책임이 둘이라는 말은 메서드가 두 가지 이상 수행한다는 의미입니다.

즉, SRP 원칙 위반입니다.

초기화 지연 기법을 한 번 정도 사용한다면 별로 심각한 문제가 아닙니다.

하지만 많은 애플리케이션이 이런 좀스러운 설정 기법을 수시로 사용합니다.

따라서 모듈성은 저조하며 대개 중복이 심합니다.

체계적이고 탄탄한 시스템을 만들고 싶다면 흔히 쓰는 좀스럽고 손쉬운 기법으로 모듈성을 깨서는 절대로 안 됩니다.

객체를 생성하거나 의존성을 연결할 때도 마찬가지 입니다.

설정 논리는 일반 실행 논리와 분리해야 모듈성이 높아집니다.

Main 분리

시스템 생성과 시스템 사용을 분리하는 한 가지 방법입니다.

생성과 관련한 코드는 모두 main이나 main이 호출하는 모듈로 옮기고, 나머지 시스템은 모든 객체가 생성되었고,

모든 의존성이 연결되었다고 가정하는 방법입니다.

즉, 애플리케이션은 main이나 객체가 생성되는 과정을 전혀 모른다는 뜻입니다.

단지 모든 객체가 적절히 생성되었다고 가정합니다.

팩토리

객체가 생성되는 시점을 애플리케이션이 결정할 필요도 있습니다.

그 예가 추상 팩토리 패턴 (ABSTRACT FACTORY PATTERN)입니다.

추상 팩토리 패턴은 많은 수의 연관된 서브 클래스를 특정 그룹으로 묶어 한번에 교체할 수 있도록 만든 디자인 패턴입니다.

실제 코드 부분이 작성되지 않고 어떻게 사용할지 명세(인터페이스)만 정의하는 것입니다.

추상 팩토리 패턴은 서로 다른 객체들을 하나의 팩토리에서 생성과 관리를 한다고 보면 됩니다.

하나의 인터페이스에서 객체의 생성을 처리하고, 다양한 성격의 객체를 하나의 그룹으로 형성해 그것을 객체 단위로 취급하여 생성해야 할 때 유용합니다.

의사 결정을 최적화하라

모듈을 나누고 관심사를 분리하면 관리와 결정이 쉬워집니다.

도시든 소프트웨어 프로젝트든, 아주 큰 시스템에서든 한 사람이 모든 결정을 내리기는 어렵습니다.

가장 적합산 사람에게 책임을 맡기면 가장 좋습니다.

우리는 때때로 가능한 마지막 순간까지 결정을 미루는 방법이 최선이라는 사실을 까먹곤 합니다.

게으르거나 무책임해서가 아니라, 최대한 정보를 모아 최선의 결정을 내리기 위해서입니다.

성급한 결정은 불충분한 지식으로 내린 결정입니다.

너무 일찍 결정하면 고객 피드백을 더 모으고, 프로젝트를 더 고민하고, 구현 방안을 더 탐험할 기회가 사라집니다.

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

표준을 사용하면 아이디어와 컴포넌트를 재사용하기 쉽고, 적절한 경험을 가진 사람을 구하기 쉬우며,

좋은 아이디어를 캡슐화하기 쉽고, 컴포넌트를 엮기 쉽다.

하지만 때로는 표준을 만드는 시간이 너무 오래 걸려 업계가 기다리지 못합니다.

표준은 사용하는 명백한 이유, 가치가 있을 때 현명하게 사용해야 합니다.

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

도메인 특화 언어(DSL)란 관련한 특정 분야에 최적화된 언어입니다. 예를 들어 SQL 등이 있습니다.

C 언어 나 Java 와 같은 범용 프로그래밍 언어 와 UML 같은 범용 모델링 언어 와 대조되는 용어입니다.

특정 영역의 문제 해결을 위해서는 그에 맞는 도구가 필요합니다.

따라서 특정 시스템의 문제를 해결하기 위해선 그에 맞는 언어가 필요합니다.

시스템 역시 깨끗해야 합니다.

깨끗하지 못한 아키텍처는 도메인 논리를 흐리며 기민성을 떨어뜨립니다.

시스템을 설계하든 개별 모듈을 설계하든,

실제로 돌아가는 가장 단순한 수단을 사용해야 한다는 사실을 명심합시다.

from http://bang-jh.tistory.com/19 by ccl(A) rewrite - 2021-10-05 22:00:59