# LARGE SCALE STRUCTURE(대규모 구조)
### 위성통신 시스템 사례
* 네트워크 시뮬레이팅 소프트웨어
* 설계를 관리 가능한 크기의 응집력 있는 모듈로 분해하자 **너무 많은 모듈**이 생겨났다.
* *"기능의 특정 측면을 보려면 어떤 패키지의 어떤 모듈을 보아야 하지?"*
* *"새 클래스는 어디에 넣으면 되지?"*
* 너무 많은 모듈로 인한 인지 과부하가 발생했다.
* 프로젝트 리더의 고민
* 앞으로 설계가 더 복잡해질 때 **기존 설계를 이해하고 쉽게 변경할 수 있는 방법**이 필요하다.
* 아이디어: 패키지 구조 변경, 시스템의 전체적인 개요를 보여주는 문서 작성, 모델링 도구로 클래스 다이어그램 생성, 작동 방식 설명
* *'아... 이걸로는 충분하지 않은데...'*
* 프로젝트 리더의 결정
* 기존 설계에 **계층 구조**를 도입한다!
* ex) 물리적 인프라 계층, 라우팅 계층, ...
* 모듈이 여러 계층에 걸치지 않도록 다시 정의한다.
* 한 객체는 한 계층에만 속하게 만든다.
* 전체 설계가 이러한 계층적 구조가 될 때까지 리팩터링한다.
* 결과
* 계층은 **모듈이나 객체, 다른 시스템과의 인터페이스에 대한 경계와 관계를 제약하는 규칙의 집합**이 되었다.
* *"특정 기능을 어디서 찾아야 할 지 이제 좀 알겠다!"*
* *"계층이 이렇게 나눠져 있으니깐 이 기능은 이 계층에 속하면 되겠다!"*
* 계층을 도입하자 복잡성이 줄어들었다.
### 모듈화의 한계
* 큰 모델은 모듈로 분해해도 너무 복잡해서 파악하기 어려울 수 있다.
* 관리 가능한 단위의 모듈로 설계를 계속 나누다보면 모듈이 너무 많아진다.
* 모듈화 자체로 설계에 균일함이 생기지는 않는다.
### 업무의 독립성
* 프로젝트 규모 크든 작든 사람들은 시스템의 각기 다른 부분에서 어느 정도 독립적으로 일해야 한다.
* **조율과 규칙**이 없다면?
* 동일한 문제에 대해서도 다양한 형식과 별개의 해법 때문에 혼동이 일어난다.
* 각 부분을 어떻게 맞춰야 할지 이해하기 힘들어진다.
* 큰 그림을 보기가 불가능해진다.
* 설계의 한 부분에 관해 학습한 바가 다른 부분으로 전해지지 않는다.
* 결과적으로 서로 도움을 주지 못하고 각 모듈의 전문가만 남는다.
* 지속적 통합은 실패하고 바운디드 컨텍스트는 단편화된다.
* **결론: 조율과 규칙이 반드시 필요하다!**
* 시스템의 특정 요소를 전체 설계 패턴 관점에서 해석할 수 있는 **지배적인 원칙**이 필요하다!
* 지배적인 원칙이 없다면 나무만 보고 숲은 보지 못한다.
* 디테일을 깊이 파고들지 않고도 각 부분이 담당하는 역할을 이해할 수 있어야 한다.
## 대규모 구조
* **대규모 구조**: 고수준의 개념, 규칙, 관계로 이루어진 **전체 시스템에 대한 설계 패턴**을 확립하는 것
* 대규모 구조를 통해 다양한 부분의 역할이 어떻게 전체적인 모습을 형성하는지 큰 그림으로 볼 수 있게 된다.
* 각 부분의 책임을 디테일하게는 몰라도 된다.
* 전체적인 관점에서 해당 부분의 위치를 대략적으로 알 수 있으면 된다.
* 독립적인 업무를 조율하는데 도움이 된다.

* 대규모 구조는 한 바운디드 컨텍스트에 한정될 수도, 여러 바운디드 컨텍스트에 걸쳐 있을 수도 있다.
* 프로젝트에 관련된 모든 팀과 하위 시스템을 하나로 묶는 개념적 구성을 제공한다.
* 대규모 구조는 UML로 표현할 수도 없고, 그럴 필요도 없다.
* 리스크: 프로젝트에 어울리지 않는 구조는 개발에 장애물이 될 수도 있다.
## EVOLVING ORDER (발전하는 질서)
> 구조를 발견/정제
* 구조화되지 않은 설계에서는 비용이 발생한다.
* 개발자들은 이를 해결하고자 **개발을 제약하는 아키텍처**를 부과한다.
* 하지만 요구사항이 바뀌고 이해가 깊어짐에 따라 아키텍처는 **속박**으로 작용할 수 있다.
### 대규모 구조는 사전에 확정 짓지 마라
* 대규모 구조를 사전에 확정 짓는 것은 비용이 많이 들 수 있다.
* 왜? 개발이 진행됨에 따라 더 적합한 구조를 찾게 되기 때문이다.
* 미리 규정해둔 구조 탓에 더 좋은 설계를 택할 수 없을 수도 있다.
* 관리자는 아키텍처가 완성되었다고 생각한다.
* *"아키텍처 확정됐다면서? 이제 애플리케이션에 관련한 업무를 하면 될텐데 왜 아직 아키텍처 문제를 붙잡고 있어?"*
### 대규모 구조는 양날의 검이다
* 아무나 설계할 수 있다면 전체적으로 이해하기 어렵고 유지보수도 어려운 시스템이 만들어진다.
* 아키텍처는 사전 설계와 관련한 가정을 둠으로써 일관성을 확보할 수 있다.
* 하지만 동시에 특정 부분에서 개발자와 설계자의 권한을 너무 많이 앗아갈 수도 있다.
#### 순응이냐 혁멱이냐
1. 애플리케이션의 수준이 떨어지든 말든 어떻게든 구조에 맞추어 개발한다. (*될대로 되라..*)
2. 구조를 무시하고 애플리케이션을 뒤엎어 아무런 구조도 없게 만든다. (*혁명이다!!*)
### 설계를 관장하는 규칙
* 설계를 관장하는 규칙은...
1. 방해가 되지 않아야 한다.
2. 일관성이 있어야 한다.
3. 실질적으로 도움이 되는 방향으로 개발을 이끌어야 한다.
### 발전하는 대규모 구조
* 대규모 구조는 애플리케이션과 함께 발전해야 한다.
* 발전 과정에서 전혀 다른 형식의 구조로도 변화할 수 있어야 한다.
* 디테일한 설계 및 모델과 관련된 의사결정을 과도하게 제약해서는 안 된다.
### 구조의 단일화 VS 개별 컴포넌트의 최적화
* 개별 부분에는 전체에 적용되지는 않지만 자연스럽고 유용한 구성 및 표현 방법이 있을 수 있다.
* 개별 부분에 전역적인 규칙을 부과하면 이러한 이점을 취할 수 없다.
* 대규모 구조를 쓴다는 것: 개별 부분을 최적화된 방법으로 구성하기보다 전체적인 모델의 관리에 집중한다는 것
* 구조의 단일화와 개별 컴포넌트의 최적화 사이의 트레이드 오프를 적절히 선택해야 한다.
* 도메인에 대한 실제 경험과 지식을 바탕으로 구조를 선택하고 너무 속박된 구조를 피해야 한다.
### 대규모 구조와 바운디드 컨텍스트
* 대규모 구조는 여러 바운디드 컨텍스트에 걸쳐 적용할 필요가 있다.
* 구조는 개별 컨텍스트의 개발팀에 해당 팀에만 해당하는 요구사항을 다룰 수 있는 방식으로 다양하게 모델을 취할 자유를 부여해야 한다.
### 대규모 구조와 실질적인 제약조건
* 대규모 구조는 개발 과정에서 실질적인 제약조건을 수용해야 한다.
* 설계자는 시스템의 특정 부분의 모델이나 외부 시스템, 레거시 하위 시스템 등을 통제하지 못할 수 있다.
#### 설계자가 외부 요소를 통제하지 못할 때 해결법
1. 구조를 어떤 외부 요소에 더 잘 맞는 구조로 변경한다.
2. 애플리케이션이 외부와 관계를 맺는 방법을 명시한다.
3. 구조를 충분히 느슨하게 만든다.
### 대규모 구조는 선택 사항이다
* 비용과 편익 측면에서 대규모 구조가 존재하는 것이 유리하고 알맞은 경우에만 시스템에 적용해야 한다.
* 모델을 개발하는 데 부자연스러운 제약조건을 강제하지 않고도 시스템을 명확하게 만들 수 있을 때만 적용해야 한다.
* **맞지 않는 구조는 차라리 없느니만 못하다!**
* 모듈로 분해했을 때 충분히 이해할 수 있을 정도로 시스템이 간단하다면 대규모 구조는 필요 없다.
* 종합적인 구조를 얻으려 애쓰지 말고, 발생한 문제를 해결하는 최소한의 집합을 찾아라!
#### 대규모 구조에 예외가 발생하면?
* 대규모 구조에 예외가 발생하면 이를 손쉽게 파악할 수 있게 해두어야 한다.
* 예외가 많아지면 구조를 변경하거나 폐기해야 한다.
### 결론
* **개발자들에게 필요한 자유를 주는 동시에 혼란을 방지하는 구조를 만들어야 한다.**
#### 앞으로 살펴볼 대규모 구조의 패턴 4가지:
1) SYSTEM METAPHOR (시스템 은유)
2) RESPONSIBILITY LAYER (책임 계층)
3) KNOWLEDGE LEVEL (지식 수준)
4) PLUGGABLE COMPONENT FRAMEWORK (착탈식 컴포넌트 프레임워크)
## SYSTEM METAPHOR (시스템 은유)
> 사고를 이끄는 수단
* XP의 은유 실천법: 은유를 써서 전체 시스템 개발에 질서를 부여한다.
* 은유는 우리의 사고방식을 특정한 방향으로 유도한다.
### 방화벽 은유

* 실제 방화벽: 외부의 화재로부터 건물이나 시설을 보호한다.
* 소프트웨어의 방화벽: 외부 네트워크의 위험으로부터 지역 네트워크를 보호한다.
#### 방화벽 은유의 양면성
* 긍정적 효과: 방화벽 은유는 네트워크 아키텍처에 영향을 주고, 독자적인 제품군을 형성했다.
* 부정적 효과: 방화벽 은유로 인해 내부의 위협 요소에 대해서는 간과하게 되었다.
* ex) 무선랜의 취약한 보안: 외부 네트워크의 단일 진입점까지만 방화벽이 존재하면 된다는 생각을 무의식적으로 하게 된다. 내부에서는 어떤 식으로 데이터를 주고 받는지는 별 상관 안하게 되어 버렸다.
### 은유의 장점
* 소프트웨어 설계는 매우 추상적이고 파악하기 힘들다.
* 은유는 개발자와 사용자가 전체 시스템을 쉽게 이해하고, 전체적으로 바라보는 시각을 공유할 수 있는 수단이 될 수 있다.
* 개발자는 은유를 통해 일관성 있는 설계 결정을 내린다.
* 은유는 객체 패러다임과 조화를 이루는 느슨하고 쉽게 이해할 수 있는 대규모 구조다.
* 적절한 시스템 은유는 여러 바운디드 컨텍스트에 적용되어 서로의 업무를 조율하는 데 도움을 줄 수 있다.
* 유용한 은유는 시스템에 관한 의사소통을 촉진하고 개발을 이끈다.
* 성공적인 은유는 시스템의 여러 부분과 여러 바운디드 컨텍스트에 걸쳐 일관성을 증대한다.
### 은유의 단점
* 은유는 본질적으로 **부정확한 유추**이다.
* 은유는 도메인에 대한 일종의 비유에 불과하다.
* 실제로 유용한 은유를 찾아내는 경우는 거의 없다.
* 도메인에 억지로 은유를 적용해서 역효과만 내는 경우가 많다.
* 매력적이긴 하나 당면한 문제에는 적합하지 않을 수도 있다.
### 은유 도입 가이드라인
* 은유가 유용하다면 대규모 구조로 채택하라.
* 은유를 중심으로 설계를 구성하고 이를 보편 언어로 흡수하여 보편 언어를 확대하라.
* 하지만 모든 은유는 부정확하므로 은유가 지나치거나 적절치 못하다면 버려라.
### 미숙한 은유
* 성숙한 도메인 모델은 결코 미숙하지 않다.
* 모델은 수많은 반복주기를 거친 도메인 전문가와의 지식 탐구의 산물이며, 동작하는 애플리케이션의 구현에 긴밀하게 엮이면서 입증된 것이다.
## RESPONSIBILITY LAYER (책임 계층)
> 계층화의 대상
### 개별 객체에 손수 만든 책임이 할당되어 있다면
1) 가이드라인도 없다
2) 균일함도 없다
3) 넓은 범위에 걸친 도메인을 동시에 다룰 능력도 없다.
### 큰 규모에서의 책임 주도 설계
* 큰 모델에 응집력을 부여하려면 책임 할당에 특정 구조를 도입하는 것이 도움이 된다.
### 계층화
* 도메인을 깊이 있게 이해하면 모듈 간 의존성에 따라 자연적인 층이 보이는 경우가 있다.
* 이러한 자연적인 층을 토대로 계층을 나눌 수 있다.
#### 계층화의 특징
* 아래에 있는 계층의 서비스는 알고 이용할 수 있다.
* 위에 있는 계층은 알지 못하고 독립적으로 존재한다.
* 의존성 화살표는 언제나 아래를 향한다.
* A가 B에 의존한다면, A를 위에, B를 아래에 놓는다.

#### RELAXED LAYERED SYSTEM(느슨한 계층화 시스템)
* 느슨한 계층화 시스템에서는 한 계층의 구성요소가 자신의 바로 아래에 있는 계층뿐만 아니라 모든 하위 계층에 접근할 수 있다.
### 계층화와 책임 주도 설계
* 자연적인 층이 나타나는 모델에서는, 계층화와 책임 주도 설계를 묶어서 주요 책임을 기준으로 개념적 계층을 정의하고 여기에 이름을 붙일 수 있다.
* 계층의 책임은 개별 객체에 할당하는 책임에 비해 범위가 넓다.
* 이름이 있는 책임 그룹은 모듈화 시스템의 이해를 향상시킬 수 있다.
#### 계층화 도입 가이드라인
* 모델에 존재하는 개념적 의존성과 도메인의 여러 부분에 대한 다양한 변화율과 변화의 근원을 검토하라.
* 도메인에서 자연적인 층을 식별하면 그것을 광범위한 추상적 책임으로 간주하라.
* 이러한 책임을 통해 높은 수준에서 시스템의 목적과 설계를 이해할 수 있다.
* 각 도메인 객체(애그리거트, 모듈 등)의 책임이 한 계층의 책임 안에 들어맞도록 모델을 리팩터링하라.
### 책임 계층
* 책임으로 계층을 구분하면 각 부분의 역할과 의존성을 더 쉽게 파악할 수 있다.
* 시스템은 운영이나 잠재 기능과 같은 계층에 의존한다.
| 계층 | 구분 | 상태 변화 |
| --- | --- | --- |
| 의사결정 지원 | 분석적 메커니즘 | 매우 적음 |
| 정책 | 업무상의 목표나 법률 | 느림 |
| 계약 | 고객과의 업무 거래와 계약 | 적정 |
| 운영 | 실제 업무 활동과 계획 | 신속 |
| 잠재 기능 | 실제 업무 자원 | 적정 |
#### 잠재 기능 계층
* *무엇을 할 수 있는가?*
* 잠재 기능 계층은 운영 계층을 참조하면 안 된다.
#### 운영 계층
* *무엇이 행해지는가?*
* 바라는 바가 아닌 실제 상황을 반영해야 한다.
#### 계약 계층
* *우리가 약속한 바는 무엇인가?*
* 향후 운영 방향을 제시할 목표를 명시한다.
#### 정책 계층
* *규칙과 목표는 무엇인가?*
* 정교한 업무 규칙이나 법적 요구사항.
* 수동적이지만 다른 계층의 행위를 제약한다.
#### 의사결정 지원 계층
* *어떤 행동을 취하고 어떤 정책을 수립해야 하는가?*
* 운영상의 현실이나 계획, 기능에 대한 것이 아니라 계획을 변경하는 결정을 내리는 데 도움을 주는 것
* 대체로 데이터 웨어하우스 기술을 이용해 구현한다.
* 의사결정 지원 계층은 운영 소프트웨어와 고객/공급자 관계를 맺은 별도의 바운디드 컨텍스트가 된다.
### 적절한 계층을 선택하자
* 대규모 구조의 가치는 복잡성이 증가할수록 증대된다.
* 프로젝트에 참여한 모든 이가 일관된 방식으로 결정을 내린다면 전체적으로 설계가 이해하기 쉬워진다.
* 알맞은 책임 계층이나 대규모 구조를 찾을 때는 문제 도메인을 이해하고 실험하는 것이 중요하다.
### 계층이 변경될 때 지켜야 할 몇 가지 특징
1. **스토리 텔링**: 계층은 도메인의 기본적인 실제 상황과 우선순위를 전해줘야 한다. 대규모 구조를 선택하는 것은 기술적 결정이 아니라 업무와 관련된 모델링 결정이다. 계층은 업무의 우선순위를 드러내야 한다.
2. **개념적 의존성**: 상위 계층에 있는 개념은 하위 계층을 배경으로 하는 의미를 지녀야 한다. 동시에 하위 계층의 개념은 독자적인 의미를 지녀야 한다.
3. **개념적 윤곽**: 계층은 변화율이나 변화의 근원이 서로 다른 객체 간에 구획을 짓게 도와준다.
## KNOWLEDGE LEVEL(지식 수준)
> 인공적인 행위를 분리하는 대상
### 지식 수준
* 다른 객체 집단이 어떻게 행동해야 하는지를 기술하는 객체의 그룹
* 구성 가능한 행위를 갖춘 소프트웨어의 요구사항을 다룬다.
* 구성 가능하다: 여러 엔티티 간의 역할과 관계를 동적으로 변경할 수 있다
* 도메인을 모델링하기보다 모델을 구조화한다.
### 애플리케이션의 가정
* 애플리케이션은 사용자가 어떻게 사용할 것이라는 가정을 한다.
* 사용자가 생각한 가정과 애플리케이션의 가정이 서로 맞지 않으면 사용자는 개발자가 의도한 바와 다른 방식으로 애플리케이션을 사용한다.
* 애플리케이션의 가정이 맞지 않기 때문에 사용자는 애플리케이션의 도움을 받지 못한다.
* 사용자는 자신의 행위의 효과를 얻기 위해 꼼수를 사용하거나 애플리케이션 상위 수준의 기능을 막을 수도 있다.
* 개발자는 나중에서야 해당 시스템의 기능이 보이는 것과는 의미가 다르다는 사실을 알게된다.
* 기능은 다른 사용자 집단이나 다른 상황에서는 굉장히 다른 의미를 가질 수 있다.
* 의미가 덧씌워진 사용법을 건드리지 않으면서 새로운 시스템으로 데이터를 이전하는 것은 아주 힘들다.
> "아... 이거 그렇게 쓰라고 만든거 아닌데..."
### 정적인 모델 VS 동적인 모델
* 너무 정적인 모델은 요구사항을 유연하게 받아들이지 못한다.
* 너무 동적인 모델(완전히 유연한 시스템)은 쓰기가 불편하다.
### 커스터마이징 함정
* 엔티티간의 역할과 관계가 상황마다 다양하게 작용하는 애플리케이션에서는 복잡성이 폭발적으로 증가할 수 있다.
* 유연함을 추가할수록 소프트웨어는 점점 더 복잡해지기만 한다.
* 완전히 커스터마이징이 가능한 소프트웨어는 실용적이지 않다.
* 완전히 일반화된 모델이나 고도로 맞춤화가 가능한 모델은 사용자의 욕구를 충족시키지 못한다.
* 굉장히 특화된 제약조건이 일반화된 프레임워크보다 더 유용할 수 있다.
* 더 단순하고 구체적인 설계자의 의도를 전달하는 것이 가능하기 때문이다.

* 설정보다 관례(CoC, Convention over Configuration)식 접근이 이러한 복잡성을 해결하기 위한 방법이 아닐까?
### 지식 수준과 반영 패턴
* 지식 수준은 모델에서 자기 규정적인 측면을 분리해서 제약조건을 명시적으로 만든다.
* 지식 수준은 반영 패턴의 도메인 계층을 응용한 것이다.
* 메타 수준(Meta Level): 소프트웨어의 구조와 행위에 대한 지식 (지식 수준)
* 기반 수준(Base Level): 애플리케이션의 운영적 책임을 수행 (운영 수준)
* 지식 수준은 반영 패턴과 달리 애플리케이션 도메인에 초점을 맞춘다.
* 지식 수준은 완전한 보편성을 달성하려고 애쓰지 않는다.
* 지식 수준은 계층화가 아니다
* 왜? 지식 수준 간에는 상호의존성이 있지만, 계층 간에는 의존성이 상위 계층에서 하위 계층으로 일방향이다.
### 지식 수준이 복잡해지면?
* 사용자(개발자 포함)들이 시스템의 행위를 이해하기가 힘들어진다.
* 시스템을 구성하는 사용자(또는 관리자)가 메타 수준의 프로그래머가 되어야 한다.
* 혹시 실수라도 하면 애플리케이션이 뻗을 수도 있다.
> "그럴 바엔 내가 개발자 하지!"
### 지식 수준 도입 가이드라인
* 설계는 개발 과정에서 제시된 시나리오뿐 아니라 향후 사용자가 소프트웨어를 구성해서 처리할 수도 있을 어떠한 시나리오도 처리할 정도로 강건해야 한다.
* 커스터마이징이 효과적이면서도 설계를 왜곡하지 않을 정도로 신중하게 적용해야 한다.
## PLUGGABLE COMPONENT FRAMEWORK (착탈식 컴포넌트 프레임워크)
> 개별 기여도를 분리
### 통합의 어려움
* 같은 추상화에 기반을 두지만 서로 독립적으로 설계되어 있는 다양한 종류의 애플리케이션이 상호운용되어야 할 때, 여러 바운디드 컨텍스트 사이의 번역 때문에 통합이 힘들어진다.
* 중복과 단편화는 개발과 설치 비용을 높이고 상호운영성은 달성하기 어려워진다.
### 중앙 허브
* 모든 컴포넌트는 각자 특정 기능을 제공하며, 중앙 허브에 연결된다.
* 중앙 허브는 연결된 컴포넌트가 제공하는 인터페이스와 통신하는 방법을 알고 있다.
### 추상 핵심
* 추상 핵심 = 고수준 추상화
* 인터페이스와 상호작용에 대한 추상 핵심을 정제하라.
* 인터페이스의 다양한 구현이 자유롭게 대체될 수 있는 프레임워크를 만들어라.
* 중앙 허브는 공유 커널 안의 추상 핵심에 해당한다.
* 특수화는 모듈에서 일어난다.
* 바운디드 컨텍스트는 캡슐화된 컴포넌트 인터페이스 너머로 숨길 수 있다.
### PCF의 장점
* 애플리케이션이 추상 인터페이스를 엄격히 준수한다면 애플리케이션은 구현과 무관하게 인터페이스가 약속한 서비스에 의지할 수 있다.
* 즉, 서로 독립적으로 개발한 소프트웨어를 거대한 시스템에 매끄럽게 통합할 수 있다.
* 시스템의 디테일은 몰라도 큰 그림은 쉽게 이해할 수 있다.
### PCF의 단점
* 매우 적용하기 힘든 패턴이다.
* 추상 핵심의 인터페이스를 설계할 때 충분히 심층적인 모델이 필요하다.
* 한 마디로, 애플리케이션을 다 개발하고 나서야 좀 괜찮은 PCF를 만들 내공이 생긴다.
### 에이즈 추모 퀼트 사례
> 이거 하지마 저거 하지마 이거 해 저거 해
* "완성된 패널의 크기는 90cm x 180cm여야 합니다. 더 커도 안 되고 더 작아도 안 됩니다"
* "천을 자를 때는 단에 쓸 수 있게 측면마다 2~3인치 정도 남기세요"
* "안감은 넣을 수 있으면 넣으세요"
* "접착제는 쓰지 마세요"
* "직물 페인트나 빛이 바래지 않는 도료로 칠하거나 안 지워지는 잉크 펜을 사용하세요"
* "제발 볼록 페인트는 쓰지 마세요"
* "천 위에 연필로 디자인 윤곽을 그리고 스텐실을 올리고 붓으로 직물 페인트나 안 지워지는 마커를 칠하세요"
* "천이 찢어지지 않게 하기위해서 유리나 금속 조각, 부피가 큰 물체는 쓰지 마세요"
* "사진이나 글자를 넣을 때는 전사용지에 사진이나 글자를 사진복사하고 100% 순면 천 위에 다림질한 다음 그 천을 패널에 꿰매세요. 아니면 깨끗한 플라스틱 비닐에 사진을 넣고 패널에 꿰매세요."
## 구조는 얼마나 제약성을 지녀야 하는가??
> (매우 느슨) 시스템 은유 <-------> PCF (제약적)
### 하위 계층의 신호 전달
* 하위 계층에서 일어난 예외적인 상황은 상위 계층에 전달되어야 한다.
* 하위 계층은 상위 계층에 관해 아무것도 알지 못한다.
* 따라서 통신은 하위 계층에서 상위 계층으로 양방향 의존성을 만들어내지 않는 방식으로 일어나야 한다.
* 신호 전달은 일반적으로 이벤트 메커니즘을 통해 이뤄진다.
* 하위 계층의 객체는 상태가 변경될 때마다 이벤트를 발생시킨다.
* 상위 계층의 객체는 하위 계층으로부터 이벤트를 기다린다.
### 제약은 과해서는 안 된다
* 제약은 개발자가 필요로 하는 유연함을 앗아갈 수도 있다.
* 프레임워크를 만들고 대규모 구조의 구현을 엄격히 통제하고자 하는 유혹을 이겨내야 한다.
* 대규모 구조의 가치: 개념적 응집성과 도메인에 대한 통찰력을 주는 것
* 각 구조적 규칙은 개발을 용이하게 해야 한다.
### 답은 끊임없는 반복뿐
* 유용한 구조가 발견되는 유일한 방법: 도메인과 문제를 매우 심층적으로 이해하는 것
* 그러려면? 반복적인 개발 과정뿐
* 프로젝트 라이프사이클 내내 대규모 구조를 재고해야 한다.
* 초기에는 도메인이나 요구사항을 잘 이해하는 사람이 아무도 없다.
* 초기에 구상한 구조는 도메인과 맞지 않는 구조일 가능성이 높다.
* 최종 구조는 처음에는 가용하지 않다.
* 계속해서 리팩터링을 거쳐서 그러한 구조가 나오게 해야 한다.
### 비용을 통제하고 이익을 극대화하는 방법
#### 최소주의
* 구조를 간단하고 가볍게 유지한다.
* 포괄적인 구조로 만들지 마라.
* 가장 중요한 관심사만 다루고 나머지는 케바케로 처리한다.
* 초반에는 시스템 은유나 몇 가지 책임 계층과 같은 느슨한 구조를 택한다.
#### 의사소통과 자기 훈련
* 모든 팀원은 새로운 개발과 리팩터링 시 반드시 구조를 이해하고 구조에 따른다.
* 용어와 관계는 반드시 보편 언어에 들어가야 한다.
* 대규모 구조는 시스템을 폭넓게 다루고 다양한 사람들이 독립적으로 조화로운 결정을 내릴 수 있게 어휘를 제공할 수 있다.
* 대부분의 대규모 구조는 느슨한 개념적 지침이므로 팀은 반드시 자기 훈련을 수행해야 한다.
* 많은 사람들이 일관되게 따르지 않으면 구조는 쇠퇴한다.
* 팀 내 대화는 시스템 내의 대규모 구조를 일관되게 유지하기에 충분하지 않다.
* 대화는 프로젝트의 보편 언어에 통합해서 모든 팀원이 끊임없이 해당 언어를 연습하게 만들어야 한다.
#### 재구조화가 유연한 설계를 낳는다.
* 구조를 변경하다 보면 상당한 양의 리팩터링이 필요할 수 있다.
* 구조는 시스템의 복잡성이 증가하고 이해가 깊어질수록 발전한다.
* 구조가 바뀔 때마다 전체 시스템은 새로운 질서를 따르도록 바뀌어야 한다.
* 구조가 있는 설계가 구조가 없는 설계보다 변경하기 쉽다.
* 현재 배치를 이해할 수 있어야 재배치하기가 쉽다.
* 여러 번에 걸친 올바른 변형을 거쳐 반복적으로 변형된 모델:
* 안정적인 측면은 단순화된다.
* 늘어나는 지식은 모델에 녹아들고 변화의 중심축이 식별되어 유연해진다.
#### 디스틸레이션은 부하를 줄인다.
* 지속적인 디스틸레이션은 구조 변경의 어려움을 덜어준다.
* 처음에는 도메인에 대한 피상적 이해에 근거해 계층을 선택할 수도 있다.
* 계층은 점차 시스템의 근본적인 책임을 표현하는 추상화로 대체되어 명료해진다.
* 시스템의 근본적인 책임이 명료해지면 사람들은 설계를 심층적으로 들여다 볼 수 있다. (목표)
* 그 결과 시스템의 대대적인 조작이 쉽고 안전해진다.