이 글은 오브젝트라는 책을 읽고 정리한 글입니다.
15장에서는 설계를 재사용하는 디자인 패턴과 설계와 코드를 재사용하는 프레임워크에 관해 살펴봅니다.
- 디자인 패턴
- 소프트웨어 설계에서 반복적으로 발생하는 문제에 대해 적용할 수 있는 해결 방법이다.
- 설계를 재사용하기 위한 것이다.
- 다양한 변경을 다루기 위해 반복적으로 재사용할 수 있는 설계의 묶음이다.
- 특정한 변경을 일관성 있게 다룰 수 있는 협력 템플릿을 제공한다.
- 프레임워크
- 설계와 코드를 재사용하기 위한 것이다.
- 애플리케이션의 아키텍처를 구현 코드의 형태로 제공한다.
- 특정한 변경을 일관성 있게 다룰 수 있는 확장 가능한 코드 템플릿을 제공한다.
디자인 패턴과 프레임워크 모두 협력을 일관성 있게 만들기 위한 방법이다.
디자인 패턴과 설계 재사용
소프트웨터 패턴
패턴이란 무엇인가를 논의할 때면 반복적으로 언급되는 몇 가지 핵심적인 특징이 있다.
- 패턴은 반복적으로 발생하는 문제와 해법의 쌍으로 정의된다.
- 패턴을 사용함으로써 이미 알려진 문제와 이에 대한 해법을 문서로 정리할 수 있으며, 이 지식을 다른 사람과 의사소통 할 수 있다.
- 패턴은 추상적인 원칙과 실제 코드 작성 사이의 간극을 메워 주며 실질적인 코드 작성을 돕는다.
- 패턴의 요점은 패턴이 실무에서 탄생했다는 점이다.
패턴은 한 컨텍스트에서 유용한 동시에 다른 컨텍스트에서도 유용한 '아이디어'다. 다양한 크기의 프로젝트 조직을 구성하는 방법, 프로젝트 일정을 추정하는 방법, 스토리 카드나 백로그를 통해 요구사항을 관리하는 방법과 같이 반복적인 규칙을 발견할 수 있는 모든 영역이 패턴의 대상 될 수 있다.
패턴은 홀로 존재하지 않는다. 특정 패턴 내에 포함된 컴포넌트와 컴포넌트 간의 관계는 더 작은 패턴에 의해 서술될 수 있으며, 패턴들을 포함하는 더 큰 패턴 내에 통합될 수 있다.
패턴 분류
- 아키텍처 패턴
- 프트웨어의 전체적인 구조를 결정하기 위해 사용할 수 있다.
- 미리 정의된 서브시스템을 제공하고, 각 서브시스템들의 책임을 정의하며, 서브시스템들 사이의 관계를 조직화하는 규칙과 가이드라인을 포함한다.
- 분석 패턴
- 도메인 내의 개념 적인 문제를 해결하는 데 초점을 맞춘다.
- 업무 모델링 시에 발견되는 공통적인 구조를 표현하는 개념들의 집합이다.
- 디자인 패턴
- 중간 규모의 패턴으로 특정한 설계 문제를 해결하는 것을 목적으로 하며, 프로그래밍 언어나 프로그래밍 패러다임에 독립적이다.
- 특정 정황내에서 일반적인 설계 문제를 해결하며, 협력하는 컴포넌트들 사이에서 반복적으로 발생하는 구조를 서술한다.
- 이디엄
- 특정 프로그래밍 언어에만 국한된 하위 레벨 패턴으로, 주어진 언어의 기능을 사용해 컴포넌트, 혹은 컴포넌트 간의 특정 측면을 구현하는 방법을 서술한다.
특정한 상황에 적용 가능한 패턴을 잘 알고 있다면 책임 주도 설계의 절차를 하나하나 따르지 않고도 시스템 안에 구현할 객체들의 역할과 책임, 협력 관계를 빠르고 손쉽게 구성할 수 있다.
패턴과 책임-주도 설계
패턴은 공통으로 사용할 수 있는 역할, 책임, 협력의 템플릿이다. 중요한 것은 패턴의 세부적인 내용이 중요하다기보다 특정 상황에서 적용할 수 있는 설계를 빠르고 쉽게 떠올릴 수 있다는 사실이다.
패턴의 구성 요소는 클래스가 아니라 '역할'이다. 디자인 패턴의 구성요소가 클래스와 메서드가 아니라 역할과 책임이라는 사실을 이해하는 것이 중요하다.
캡슐화와 디자인 패턴
- STRATEGY 패턴
- 알고리즘의 변경을 캡슐화하는 것이고 이를 구현하기 위해 객체 합성을 이용한다.
- TEMPLATE METHOD 패턴
- 알고리즘을 캡슐화하기 위래 합성 관계가 아닌 상속 관계를 사용하는 것
- 부모 클래스가 알고리즘의 기본 구조를 정의하고 구체적인 단계는 자식 클래스에서 정의하게 함으로써 변경을 캡슐화할 수 있는 디자인 패턴
- 합성보다는 결합도가 높은 상속을 사용했기 때문에 STRATEGY 패턴처럼 런타임에 객체의 알고리즘을 변경하는것은 불가능하다.
- 알고리즘 교체와 같은 요구사항이 없다면 상대적으로 STRATEGY 패턴보다 복잡도를 낮출 수 있다는 면에서는 장점이라고 할 수 있다.
- DECORATOR 패턴
- 객체의 행동을 동적으로 추가할 수 있게 해주는 패턴으로서 기본적으로 객체의 행동을 결합하기 위해 객체 합성을 사용한다.
- 선택적인 행동의 개수와 순서에 대한 변경을 캡슐화 할 수 있다.
패턴은 출발점이다
패턴을 익힌 후에는 모든 설계 문제를 패턴으로 해결하려고 시도하기 쉽다. 조슈아 케리에브스키는 이를 '패턴 만능주의'라고 부른다.
부적절한 상황에서 부적절하게 사용된 패턴으로 인해 소프트웨어의 엔트로피가 증가하는 부작용을 낳기 쉽다. 패턴을 남용하지 않기 위해서는 다양한 트레이드 오프 관계 속에서 패턴을 적용하고 사용해 본 경험이 필요하다.
패턴을 적용할 때는 함께 작업하는 사람들이 패턴에 익숙한지 여부를 확인하고, 그렇지 않다면 설계에 대한 지식과 더불어 패턴에 대한 지식도 함께 공유 하는 것이 필요하다.
프레임워크와 코드 재사용
코드 재사용 대 설계 대사용
디자인 패턴을 적용하기 위해선 설계 아이디어를 프로그래밍 언어의 특성에 맞춰 가공해야 하고 매번 구현 코드를 재 작성해야 한다는 단점이 있다.
가장 이상적인 형태의 재사용 방법은 설계 재사용과 코드 재사용을 적절한 수준으로 조합하는 것이다.
프레임워크란 '추상 클래스나 인터페이스를 정의하고 인스턴스 사이의 상호작용을 통해 시스템 전체 혹은 일부를 구현해 놓은 재사용 가능한 설계', 또는 '애플리케이션 개발자가 현재의 요구사항에 맞게 커스터마이징할 수 있는 애플리케이션의 골격'을 의미한다. 프레임워크는 코드를 재사용함으로써 설계 아이디어를 재사용한다.
상위 정책과 하위 정책으로 패키지 분리하기
상대적으로 상위 정책은 변경에 안정적이지만 세부 사항은 자주 변경된다. 그러므로 상위 정책은 세부 사항에 비해 재사용될 가능성이 높다. 하지만 상위 정책이 세부 사항에 의존하게 되면 상위 정책이 필요한 모든 경우에 세부 사항도 항상 함께 존재해야 하기 때문에 상위 정책의 재사용성이 낮아진다.
이 문제를 해결할 수 있는 가장 좋은 방법은 의존성 역전 원칙에 맞게 상위 정책과 세부 사항 모두 추상화에 의존하게 만드는 것이다. 의존성 역전 원칙의 관점에서 세부 사항은 '변경'을 의미한다.
이를 위한 첫걸음은 변하는 부분과 변하지 않는 부분을 별도의 패키지로 분리하는 것이다. 중요한 것은 패키지 사이의 의존성 방향이다. 의존성 역전 원리에 따라 추상화에만 의존하도록 의존성의 방향을 조정하고 추상화를 경계로 패키지를 분리했기 때문에 세부 사항을 구현한 패키지는 항상 상위 정책을 구현한 패키지에 의존해야 한다.
제어 역전 원리
객체지향 설계의 재사용성은 개별 클래스가 아니라 객체들 사이의 공통적인 협력 흐름으로 부터 나온다.의존성 역전 원리에 따라 구축되지 않은 시스템은 협력 흐름을 재사용 할 수도 없으며 변경에 유연하게 대처할 수도 없다.
의존성을 역전시킨 객체지향 구조에서는 프레임워크가 애플리케이션에 속하는 서브클래스의 메서드를 호출한다. 따라서 프레임워크를 사용할 경우 개별 애플리케이션에서 프레임워크로 제어 흐름의 주체가 이동한다.의존성을 역전시키면 제어 흐름의 주체 역시 역전된다. 이를 제어 역전 원리 또는 할리우드 원리라고 한다.
제어의 역전이 프레임 워크의 핵심 개념인 동시에 코드의 재사용을 가능하게 하는 힘이라는 사실을 이해해야 한다.
'📖 > 오브젝트' 카테고리의 다른 글
[오브젝트] 부록 B 타입 계층의 구현 (0) | 2024.03.21 |
---|---|
[오브젝트] 부록 A 계약에 의한 설계 (0) | 2024.03.19 |
[오브젝트] 14장 일관성 있는 협력 (0) | 2024.03.14 |
[오브젝트] 13장 서브클래싱과 서브타이핑 (0) | 2024.03.11 |
[오브젝트] 12장 다형성 (1) | 2024.03.07 |