본문 바로가기

책/Object

유연한 설계

개방 폐쇄 원칙(OCP)

확장에 대해 열려 있고, 변경에 대해서는 닫혀 있어야 한다.

 - 확장에 대해 열려 있다 : 요구사항이 변경될 때 새로운 '동작'을 추가해서 애플리케이션의 기능을 확장할 수 있다

 - 변경에 대해 닫혀 있다 : 기존의 '코드'를 수정하지 않고도 애플리케이션의 동작을 추가하거나 변경할 수 있다


컴파일 타임 의존성을 고정시키고 런타임 의존성을 변경하라

컴파일 타임 의존성 : 코드에서 드러나는 클래스들 사이의 관계

런타임 의존성 : 실행시에 협력에 참여하는 객체들 사이의 관계

개방 폐쇄 원칙을 따르는 설계를 하자


추상화가 핵심이다

개방 폐쇄 원칙의 핵심은 추상화에 의존하는 것

추상화

 - 핵심적인 부분만 남기고 불필요한 부분은 생략함으로써 복잡성을 극복하는 기법

 - 문맥이 바뀌더라도 변하지 않는 부분만 남게 되고 문맥에 따라 변하는 부분은 생략됨

 - 생략된 부분을 문맥에 적합한 내용으로 채워넣음으로써 각 문맥에 적합하게 기능을 구체화하고 확장할 수 있음


생성 사용 분리

유연하고 재사용 가능한 설계를 원한다면 객체와 관련된 두 가지 책임을 서로 다른 객체로 분리해야 한다

1. 객체를 생성할 책임을 클라이언트로 옮기는 것

2. 객체 생성과 관련된 책임만 전담하는 별도의 객체를 추가 - Factory

3. 순수한 가공물에게 책임 할당하기

 - 정보 전문가(information expert)에게 책임을 할당

 - 표면적 분해 : 도메인에 존재하는 사물 또는 개념을 표현하는 객체들을 이용해 시스템을 분해하는 것

 - 행위적 분해 : 책임을 할당하기 위해 창조되는 도메인과 무관한 인공적인 객체(순수한 가공물 - pure fabrication)에게 책임을 할당


의존성 주입

사용하는 객체가 아닌 외부의 독립적인 객체가 인스턴스를 생성한 후 이를 전달해서 의존성을 해결하는 방법

생성자 주입(constructor injection) : 객체를 생성하는 시점에 생성자를 통한 의존성 해결

setter 주입(setter injection) : 객체 생성 후 setter 메서드를 통한 의존성 해결

메서드 주입(method injection) : 메서드 실행 시 인자를 이용한 의존성 해결

Service Locator 패턴 : 의존성을 해결할 객체들을 보관하는 저장소를 통해 의존성을 해결해줄 것을 요청

 - 의존성을 구현 내부로 감추기 때문에 런타임에 에러가 발생할 수 있음

 - 의존성을 이해하기 위해 코드 내부의 구현을 이해할 것을 강요함

명시적인 의존성이 숨겨진 의존성이 좋다


의존성 역전 원칙(DIP)

상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다

추상화는 구체적인 사항에 의존해서는 안 된다. 구체적인 사항은 추상화에 의존해야 한다

인터페이스의 소유권을 서버 모듈이 아닌 클라이언트 모듈에 위치 시키자


유연성에 대한 조언

유연한 설계는 유연성이 필요할 때만 옳다

 - 변경하기 쉽고 확장하기 쉬운 구조를 만들기 위해서는 단순함과 명확함의 미덕을 버리게 될 가능성이 높다

 - 유연한 설계는 복잡하고 암시적이다

 - 설계가 유연할수록 클래스 구조와 객체 구조 사이의 거리는 점점 멀어진다

협력과 책임이 중요하다

 - 설계를 유연하게 만들기 위해서는 먼저 역할, 책임, 협력에 초점을 맞춰야 한다

 - 객체를 생성하는 방법에 대한 결정은 모든 책임이 자리를 잡은 후 가장 마지막 시점에 내리는 것이 적절하다


' > Object' 카테고리의 다른 글

합성과 유연한 설계  (0) 2020.07.27
상속과 코드 재사용  (0) 2020.07.27
의존성 관리하기  (0) 2020.07.06
객체 분해  (0) 2020.07.02
메시지와 인터페이스  (0) 2020.06.29