책 읽기 전 적는 글
이번에 친구가 "객체지향의 사실과 오해"라는 책을 같이 읽어보자고 했다.(친구야 고마워🐶🐶🐶)
지금까지 자바나 스프링으로 개발을 몇 번 해봤는데, 중복코드를 줄이거나 캡슐화하는 것 외에는 객체지향 설계를 해본 기억이 없었다. 소프트웨어 설계과목을 들을 때도 다형성이 가장 중요하다고 했지만, 다형성이 중요한 코드를 본 적이 없어서 그런지 와닿지 않았다.
이 도서가 유명하다는 건 알았지만 읽어볼 시도를 하지 않은 건 객체지향이 왜 중요한지 느끼지 못해서였던 것 같다. 이번 기회에 책을 읽으면서 객체지향이 왜 중요한지 알게되었으면 좋겠다.
01. 협력하는 객체들의 공동체
시너지를 생각하라. 전체는 부분의 합보다 크다 -스티븐 코드
이 장에서는 객체지향의 핵심개념인 역할, 책임, 협력을 강조한다.
커피숍에서 캐시어와 바리스타의 예시를 들며 객체지향의 핵심개념을 설명하고, 이를 객체지향언어에 비유하여 이해가 쉽게 설명해준다.
서로 요청하고 응답하는 과정에서 협력이 일어남 -> 협력적, 책임할당의 중요성
또한 응답을 만드는 과정에서 객체의 자율성에 대해 설명해줌 -> 캡슐화
역할과 책임은 대체가능
객체지향이 절차지향과 구분되는 점은 데이터와 프로세스를 묶음으로써 자율성을 보장 -> 유지보수와 재사용이 용이한 코드를 만들 수 있다
객체지향의 핵심은 클래스, 상속이 아닌 책임과 협력이다!
02. 이상한 나라의 객체
객체지향 패러다임은 지식을 추상화하고 추상화한 지식을 객체안에 캡슐화함으로써 실세계 문제에 내재된 복잡성을 관리하려고 한다. 객체를 발견하고 창조하는 것은 지식과 행동을 구조화하는 문제다
- 레베카 워프스브룩
2장에서 핵심은 상태, 행동, 식별자라는 객체의 구성요소이다. 이를 통해 캡슐화를 설명하고, 동일성 및 동등성을 설명하며 객체를 바라보는 새로운 시각을 제공한다.
앨리스의 예시를 들어 상태와 행동의 관계에 대해 설명해준다. (앨리스 그림이 조금 무섭다)
- 상태는 행동의 결과를 결정하고
- 행동은 상태를 결정한다
그리고 뒤에 기계로서의 객체를 설명해주는데, 이 부분이 가장 와닿았다. 지금까지 설명한 모든 개념을 이 한가지 비유로 정리할 수 있는 것 같다.
- 상태는 객체 자신이 결정(자율성)
- 상태가 얼마나 변하는지는 알 수 없음(캡슐화)
- 버튼 인터페이스를 통해서만 접근가능(메시지를 통한 접근)
그리고 객체지향설계 시 상태를 먼저 결정하면 안된다는 새로운 사실을 알게되었다. 객체는 협력하는 존재이기 때문에 상태를 먼저 결정하는 것이 아닌, 행동을 우선적으로 고려해야한다.
객체 상태를 먼저 결정하면 단점은 다음과 같음
- 캡슐화 저하
- 객체를 협력자가 아닌 고립된 섬으로 만듦(협력 위주가 아님)
- 재사용성 저하
올바른 객체지향 설계 순서
- 애플리케이션에 필요한 협력을 먼저 생각
- 협력에 필요한 행동 생각
- 행동을 수행할 객체를 선택, 할당
객체지향설계를 할 때는 "어떤 책임이 필요한가"를 가장 염두해두고 진행해야한다. 이는 RDD(Responsibility-Driven Design, 책임-주도설계)라고 한다. 이를 통해 협력을 기준으로 객체 행동을 생각하여 응집도 높고 재사용 가능한 객체를 만들 수 있게 한다.
객체는 실제세계의 모방이 아니라, 완전히 새로운 세계를 창조하는 것
마지막으로는 객체가 실제세계의 모방이고, 추상화라는 시각을 전환해준다. 객체지향의 목적은 현실세계를 기반으로 새로운 세계를 창조하는 것이다. 객체가 현실의 추상화가 아닌 이유는 다음과 같음
- 객체는 능동적이고
- 자율성을 가지고 스스로 자신의 상태를 조작한다
- 아예 새로운 세계를 창조함
- (의인화: 현실의 객체보다 더 많은 일을 할 수 있는 소프트웨어 객체의 특성)
객체를 현실세계에 비유하는 건 은유의 느낌이라고 한다. 은유를 통해 객체와 현실의 표현적 차이를 줄이면 구조를 쉽게 예측가능하고, 이해쉽고 유지보수가 용이한 소프트웨어를 만들 수 있다. 그러므로 도메인(현실세계)에서 사용하는 이름을 객체에 부여하는 게 좋다.
+) 조금 더 정리
- 객체의 상태 = 값 + 객체
- 객체를 구성하는 모든 특징은 객체의 프로퍼티라고 한다
- 프로퍼티는 정적 특성을 가짐 (= 변수 height)
- 프로퍼티 값은 동적인 특성을 가짐 (= 150)
- 객체 간의 의미있는 연결은 링크라고 부르며, 링크를 통해 서로 협력한다
- 객체의 프로퍼티 = 단순값 속성 + 링크
- 객체는 스스로만 자신의 상태를 변경가능하다. 다른 객체는 내 상태에 절대 직접 접근할 수 없다.
- 상태는 나혼자만 변경 가능하고, 행동을 통해 간접적으로 내 상태를 변경할 수 있다.
- 상태는 절대 직접접근할 수 없고, 상태를 변경시킬 수 있는 행동만이 외부에 노출된다. 이를 캡슐화라고 함
- 행동만 알 수 있고, 상태는 외부에 노출하지 않음
- 상태 변경 여부는 객체 스스로 결정한다. 남이 손댈 수 없음
- 캡슐화를 통해 객체의 자율성을 높이면 협력이 유연해지고, 간결해진다
- 객체는 메시지를 전달하며 서로 상호작용을 하고, 각자의 책임을 완수한다.
- 객체끼리 구분가능한 특정 프로퍼티는 식별자라고 한다.
- 객체는 식별자를 가진다
- 단순값은 식별자를 가지지 않음. 인스턴스 구분위한 식별자가 필요 없다. 객체의 특성을 표현하는 값일 뿐
- 값(값 객체)은 식별자를 가지지 않음 -> 상태를 이용한 동등성 검사를 통해 두 인스턴스 비교
- 객체(참조객체, 엔티티)는 상태가 변경가능 -> 식별자를 이용한 동일성 검사를 통해 두 인스턴스 비교
동등성과 동일성
동등성
- 상태를 이용해 두 값이 같은지 판단할 수 있는 성질
- 상태가 같으면 동등한 것으로 판단한다
- 값은 상태가 변하지 않으므로, 상태를 이용하여 동등성을 판단할 수 있다 오직 상태만으로 동등성을 판단해도 됨
- 어떤 시점에 동일한 타입이 값이 같으면 -> 두 값은 항상 동등상태를 유지한다
동일성
- 객체의 상태는 변한다(가변상태)
- 상태가 달라도 식별자가 같으면 두 객체는 동일하다
- 식별자를 기반으로 같은지 다른지 판단한다
03 타입과 추상화
3장에서는 추상화에 다형성에 대해 이야기한다. "객체를 결정하는 것은 행동이다"가 가장 중요한 포인트다.
추상화를 통한 복잡성의 단순화
지하철 노선도를 예시로 목적에 집중하여 정확성을 버리고, 복잡도를 제거하는 추상화의 중요성을 알려준다. 사실적인 정보는 오히려 복잡성을 증가시켜 본질을 흐린다.
추상화는 복잡성을 단순화하는 것이고, 훌륭한 추상화는 목적에 부합하게 복잡성을 줄이는 것이다.
복잡성을 줄이기 위한 추상화의 두 차원
- 구체적인 사물들 간의 공통점은 취하고 차이점은 버리는 일반화 -> 단순하게 만듦
- 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거 -> 단순하게 만듦
개념과 분류를 이용한 단순화
추상화하여 여러 그룹으로 묶으면 상황을 단순화 할 수 있다
- 개념은 공통점을 기반으로 객체들을 묶기위한 그릇이다. 이 개념을 이용하여 객체들을 여러 그룹으로 분류할 수 있다.
- 객체는 특정한 개념을 적용할 수 있는 구체적인 사물이다. 어떤 객체가 그룹의 일원이 될 때 객체는 그 개념의 인스턴스라고 한다.
개념과 분류를 이용해 복잡성을 극복한다.
- 어떤 개념으로 분류하느냐에 따라 객체지향의 품질이 달라진다. 잘 분류하면 유지보수도 용이해지고, 변화에 쉽게 대처할 수 있다.
- 또한 분류는 객체를 쉽게 찾고 조작할 수 있는 정신적 지도를 제공해줄 수 있다.
개념은 type과 완전한 동일한 의미.
객체가 협력을 위해 어떤 책임을 가지는 지가 가장 중요하다.
- 그러므로 객체가 어떤 타입에 속하는지 결정하는 것은 객체가 수행하는 행동에 달렸다.
- 객체의 내부적인 표현은 감춰진다 (효과적으로 행동을 수행할 수 있다면 상태는 뭐든 상관 x)
객체지향 설계의 중요한 원칙
- 행동이 우선이다(동일 책임 = 동일 타입 = 동일 행동) -> 다형성
- 외부에 데이터를 감추고, 행동만이 고려 대상이다 -> 캡슐화
다형성: 동일한 요청에 대해 다른 방식으로 응답할 수 있는 능력
- 다형적 객체들은 동일 타입을 가지며, 동일한 메시지를 수신한다
행동에 따라 객체를 분류하기 위해선 데이터가 아닌 외부행동을 먼저 생각해야한다. 그러므로 객체지향 설계 순서는 다음과 같음 (DDD가 아닌 RDD)
- 책임 결정
- 책임을 수행할 적합한 데이터는 나중에 결정
- 데이터를 책임을 수행하는 데 필요한 interface 뒤로 캡슐화
일반화/특수화 관계를 결정하는 것도 행동이다. 일반적 행동 + a = 특수한 행동
타입을 사용하는 이유는 상태가 동적으로 변하는 객체의 복잡성때문이다.
- 타입을 사용한다면 상태가 변해도 식별성을 동일하게 유지할 수 있다
- 동적으로 변하는 상태를 시간과 무관한 정적인 모습으로 다룰 수 있음
- 동적인 특성을 추상화한다
정적모델과 동적모델
객체는 정적모델, 동적모델 두 가지를 동시에 고려한다
- 특정시점에 어떤 상태를 가지는지 = 스냅샷(객체 다이어그램) = 동적모델(상태변화 및 행동을 포착)
- 객체가 가질 수 있는 상태, 행동을 시간 독립적으로 표현 = 타입모델(타입의 정적인 모습) = 정적모델
객체지향적 애플리케이션을 설계 및 구현하는 방법은 (1)객체관점의 동적모델과 (2)객체를 추상화한 타입관점의 정적모델 두 가지를 혼용해야한다.
정적모델 중 한가지인 클래스는 타입을 구현하는 한 가지의 구현 매커니즘일 뿐이다.
객체를 분류하는 건 타입이고, 타입을 구현하는 방법 중 하나가 클래스다.
04. 역할, 책임, 협력
4장에서는 1~3장에서 입이 마르도록 강조한 역할, 책임, 협력을 더 강조한다.
(4장까지만 읽었는데도 객체지향을 떠올리면 역할, 책임, 협력이 떠오른다. 하도 강조해서 머리에 박힘)
타인과 협력을 맺는 과정에서의 상황이 사람의 행동을 결정하듯, 객체도 협력이라는 문맥이 객체의 행동방식을 결정한다고 한다.
협력을 먼저 생각하라
객체를 생각할 때는 ①협력을 먼저 생각한 후, ②행동과 ③상태를 결정해야한다.
협력에 맞춰 애플리케이션을 설계해야 객체지향 설계의 전체적인 품질이 좋아진다.
객체들은 동일한 목적을 달성하기 위해 협력함
요청과 응답을 받을 수 있는, 책임을 가질 수 있는 객체는 ①책임수행을 위한 지식을 알고있거나(아는것) ②책임을 수행할 수 있는(하는것) 객체이다.
객체지향 개발에서 가장 중요한 능력은 책임을 능숙하게 소프트웨어 객체에 할당하는 것
- 크레이그 라만
협력과 책임을 생각하지 않고 구현한다면 변경에 취약하고, 다양한 협력에 참여하지 못하는 비자율적 객체만 남게 된다.
명확한 책임이 어플리케이션의 미래를 결정한다
책임: 객체에 의해 정의되는 응집도 있는 행위의 집합 (객체가 알아야하는 정보/ 수행할 수 있는 행위)
책임은 객체지향 설계의 품질을 결정하는 가장 중요한 요소다. 적절한 객체에게 적절한 책임을 할당하는 게 포인트다.
메시지전송 = 책임
- 내가 책임을 수행하면서 다른 객체에게 메시지를 전송하여 책임 수행을 요청할 수 있다. 즉, 하나의 책임은 여러 메시지로 분할가능
설계 초반에는 어떤 객체가 어떤 책임을 가지고, 어떤 방식으로 협력하는지 결정하는 것에서 시작해야한다. 어떤 클래스가 어떤 메서드, 상태를 포함할 지는 절대 먼저하면 안된다. 책임과 메시지에 대한 윤곽을 잡은 후 하는 게 맞다
책임은 역할로 추상화
객체가 수행하는 책임의 집합은 협력 안에서 수행하는 역할을 암시한다.
역할로 뺌으로써 ①재사용 가능하고 ②유연한 객체지향 설계를 할 수 있다.
역할은 객체지향 설계의 단순성, 유연성, 재사용성을 뒷받침하는 핵심 개념이다.
- 유사한 협력을 하나의 협력으로 추상화 -> 인지과부하 줄임
- 다양한 객체가 협력에 참여가능함 -> 협력을 유연하게 만들고, 재사용성을 높임
설계자가 다뤄야하는 협력의 개수가 줄어들고, 객체는 추상적인 역할로 대체한다.
- 이는 협력양상을 단순화함으로써 어플리케이션 설계를 이해하고 기억하기 수월해진다.
- 또한 동일한 구조의 협력을 다양한 문맥에서 재사용이 가능해진다
유사한 과정을 하나의 협력으로 추상화하고, 책임을 수행하는 대상은 역할로 추상화한다. 역할은 협력 내에서 다른 객체로 대체할 수 있음을 나타내는 일종의 표식이다.
역할의 대체가능성
물론 역할을 대체할 수 있는 대상은 다음과 같은 조건을 만족해야한다.
- 각 역할이 수신가능한 메시지를 동일하게 이해
- 메시지를 수신하여 동일한 책임을 수행할 수 있어한다
동일한 역할을 수행할 수 있다(대체가능)
- 협력 안에서 역할이 수행하는 행동을 그대로 수행할 수 있다
- 협력 안에서 역할이 수행하는 모든 책임을 동일하게 수행할 수 있다 (= 동일한 책임집합을 수행가능하다 )
더 많은 책임을 가질 수 있는 객체
- 객체는 역할에 주어진 책임 외에 다른 책임을 수행할 수 있다
- 더 많은 책임을 가질 수 있음
- 일반적인 경우에는 객체의 타입과 역할사이에 일반화/특수화 관계가 성립한다. (역할로 추상화)
역할 자체는 객체의 추상화이다. 역할은 대체가 가능하고, 대체가능한 객체들은 동일한 책임을 수행할 수 있다.
견고하고 깔끔한 협력 설계를 위한 순서
- 협력을 구성하는데 필요한 책임을 고안
- 객체에 책임을 할당
- 책임을 수행하는 행동을 결정
- 행동을 수행하는 필요 데이터를 결정
- 클래스를 구현
좋은 객체지향설계는 정적인 클래스 구현보다 어떤 협력이고, 어떤 책임을 누구에게 할당할건지가 중요하다.
올바른 객체에 올바른 책임을 할당하기 위해서는 협력이라는 문맥 안에서 객체를 생각해야한다. 이를 통해 객체들은 충분히 협력적이고 자율적인 객체가 될 수 있다.
객체지향 설계 기법
- RDD(Responsibility Driven Design)
- Design Pattern
- TDD
RDD(Responssibility Driven Design, 책임주도설계)
위에서 올바른 책임을 올바른 객체에게 할당하는 게 좋은 객체지향설계기법이라고 하였다.
전체 개발단계에 걸쳐 객체의 역할, 책임, 협력을 도드라지게 만드는 기법과 체계를 따르는 건 중요하다.
객체지향 시스템을 장초자흔 작업은 지속적 훈련/ 견고한 기술/ 안정적인 가이드라인이 필요함
RDD는
- 시스템 기능을 더 작은 규모의 책임으로 분할하고 (시스템 책임 -> 객체의 책임으로 할당)
- 수행하기 적절한 객체에게 할당한다
- 책임 수행 도중 스스로 처리할 수 없는 정보나 기능이 필요한 경우 다시 적절한 객체를 찾아 필요한 작업을 요청한다
- 위임받은 객체도 책임을 수행
- 협력이 일어남
- 이런 협력관계를 구축
- +) 책임이 여러 종류의 객체가 가능한 일이라면 이를 역할로 대체한다.
디자인패턴
효과적으로 일하는 사람들의 한 가지 특징은 아무것도 없는 상태에서 작업을 시작하지 않고 이전의 훌륭한 결과물을 모방하고 약간의 수정을 거쳐 원하는 결과물을 만들어낸다
패턴은 모범이 되는 설계라는 뜻이다.
디자인 패턴은 과거의 설계 정보로, 반복적으로 발생하는 문제와 해법의 쌍으로 이루어져있다.
- 해결하려는 문제가 무엇인지 명확하게 서술하고, 적용할 수 있는 상황과 없는 상황을 함께 설명한다.
- 또한 특정 상황에서 어떤 설계가 왜 더 효과적인지 설명한다
디자인 패턴은 책임-주도 설계의 결과물이자 지름길이다.
특정 상황에 적용가능한 디자인패턴을 안다는 것은 RDD절차를 순차적으로 따르지 않아도 시스템 안에 구현할 객체들의 역할,책임,협력관계를 빠르고 손쉽게 포착할 수 있다는 것이다.
TDD
- TDD는 테스트를 작성하고, 테스트를 통과하는 간단한 코드를 만든 후, 리팩터링으로 중복을 제거하는 방법
TDD는 책임-주도 설계의 기본 개념을 따른다
- 사전 설계 없이 TDD를 진행한다 = RDD의 단계적인 절차와 기법들을 단시간에 감각적으로 수행가능
- 협력 안에서 객체의 역할과 책임이 무엇인지 알고, 이것의 구현방식에 대한 감각을 갖춰야 효과적인 테스트 작성가능
- TDD는 RDD를 통해 도달해야 하는 목적지를 테스트라는 안전장치를 통해 좀 더 빠르고 견고한 방법으로 도달할 수 있도록 해주는 최상의 설계 프로세스
TDD는 객체지향에 대한 깊이 있는 지식을 요구한다. 그러므로 다양한 설계 경험과 패턴에 대한 지식이 없는 사람들은 TDD의 온전한 혜택을 누리기 어렵다.
역할, 책임, 협력에 집중하고 객체지향의 원칙을 적용하려는 깊이 있는 노력을 통해서만 TDD의 혜택을 누릴 수 있음
05. 책임과 메시지
- 5장이 이 책에서 가장 중요한 부분이라고 하였다
명확한 책임의 객체들이 협력에 참여해야한다
- 객체는 요청을 수신하여 행동함
- 행동한다는 건 책임을 수행한다는 것
- 객체지향 설계의 아름다움은 적절한 책임을 적절한 객체에 할당하는 과정에서 드러남
- 적절한 책임을 선택하는 것으로 전체 설계 방향을 결정하는 방식 = 책임주도 설계
객체의 자율성
- 협력하는 객체가 얼마나 자율적인지에 따라 전체 애플리케이션의 품질이 결정됨
- 자율적인 책임이 자율적 객체를 낳고, 이들이 모여 유연하고 단순한 협력을 만듦
- 지나치게 상세한 수준의 책임은 자율적으로 책임을 수행할 수 없는 객체를 만든다
- 책임은 자율성을 충분히 보장할 수 있을만큼 포괄적/추상적이여야힌디. 추상적이고 포괄적인 책임은 협력을 다양한 환경에서 재사용 가능하게 만들고, 유연성을 보장한다
- 동시에 해야할 일을 명확하게 지시해야함.
- 협력의 의도를 뚜렷하게 나타내면서, 충분히 추상적인 책임이 좋다.
- 자율적인 책임은 객체가 "어떻게"하는가가 아닌 "무엇"을 하는가를 설명한다.
메시지는 메서드들의 추상화 -> 다형성
- 객체는 메시지를 수신하여 책임을 수행한다. 메시지전송이 다른 객체에 접근가능한 유일한 방법임
- 메시지를 처리할 수 있다 = 행동을 수행할 책임이 있다
- 수신가능한 메시지 모양 = 객체가 수행할 책임의 모양 ( 메시지 이름 + 메시지 인자 )
- 객체는 수신한 메시지 처리방법을 자유롭게 선택함
객체의 내부와 외부는 메시지를 기준으로 분리됨.
메시지를 처리하기 위해 내부적으로 선택하는 방법 = 메서드
객체는 실행시간에 메시지를 처리하는 메서드를 선택할 수 있다. 컴파일시간 x (객체지향이 전통적인 방법과 구별됨)
다형성
- 서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는 것(동일 메시지를 서로 다른 메서드로 처리)
- 다형성 = 객체들이 동일한 책임을 공유한다
- 메시지 송신자는 메시지를 이해하고 수행할 수만 있다면 누가 수신자가 되든 상관하지 않는다. 수신자를 구분할 필요없고, 처리방식도 알 필요가 없음
- 이로써 동일한 역할을 수행하는 다양한 타입의 객체와 협력가능하다(대체가능)
- 다형성은 설계를 유연하고, 확장이 가능하며, 재사용 가능하게 만든다
- 핵심은 메시지
송신자가 수신자에 대한 적은 정보만 알아도 협력이 가능하다는 것은 설계품질에 큰 영향을 준다.
- 협력이 유연해짐
- 협력이 수행되는 방식을 확장할 수 있다
- 협력의 세부적인 수행방식을 쉽게 수정가능
- 협력의 동작방식을 변경해도 협력의 구조 자체는 변하지 않음 -> 변경의 파급력 적음
- 협력이 수행되는 방식 재사용가능
다형성을 지탱하는 건 메시지다! 설계품질을 높이기 위해서는 훌륭한 메시지를 선택하는 게 중요하다.
메시지를 따라라
객체지향 애플리케이션의 중심 사상은 메시지를 통한 협력관계를 기반으로 사용자에게 기능을 제공하는 것이다.
객체지향의 강력함은 메시지에서 나온다.
- 시스템을 메시지를 주고받는 동적인 걕체들의 집합으로 보자.
- 클래스는 객체의 속성, 행위를 담는 틀일 뿐이다.
- 객체들 사이의 커뮤티케이션에 초점을 맞추자
- 견고하고 유연한 협력관계가 만들어짐
- 데이터 구조를 먼저 생각하는 데이터주도 설계는 자율성을 저해한다
- 협력이라는 문맥에서 고민해야 훌륭한 책임을 만들어낼 수 ㅇ
- 메시지 중심 협력설계: 객체가 메시지를 선택하지 않고, 메시지가 객체를 선택하게 해야한다.
객체지향 설계는
- 적절한 책임을 적젏나 객체에 할당하면서
- 메시지를 기반으로 협력하는 객체들의 관계를 발견하는 과정이다
책임주도 설계는
- 책임을 완수하기 위해 협력하는 객체를 이용해 시스템을 설계한다
- 객체들간 주고받는 메시지를 기반으로 절적한 역할, 책임, 협력을 발견하는 게 기본 아이디어다
책임주도 설계에서 역할과 책임, 협력을 식별하는 방법
- 애플리케이션이 수행하는 기능을 시스템의 책임으로 보기
- 시스템의 책임을 구현하기 위해 협력관계를 시작할 적절한 객체를 찾아 시스템의 책임을 할당
- 객체가 책임완수를 위해 다른 객체의 도움이 필요하면 어떤 메시지가 필요한지 결정한다
- 메시지를 수신하기 적합한 객체를 선택한다
- 시스템의 책임이 달성될 때까지 메시지를 송수신하는 협력과정을 거침
시스템이 수행해야하는 전체 행위 = 협력하는 객체들의 책임모음
RDD의 핵심: What/Who 사이클
- ①어떤 행위가 필요한지(메시지) 결정하고 ②행위를 수행할 객체를 결정
- 메시지 중심 설계 = 메시지 수신자의 캡슐화 증진, 송수신자의 느슨한 결합
- 이 설계 방식은 객체가 외부에 제공하는 인터페이스가 "묻지말고 시켜라"라는 스타일을 따르게 함
묻지말고 시켜라(데메테르 법칙)
- 객체가 누군지는 모르겠지만 내 메시지를 잘 처리할거야 -> 캡슐화, 결합도를 낮게 유지
- 자율적인 객체들의 공동체라는 사실을 강조/ 자율성을 보장
- 설계를 유연하게 만듦
- 메시지가 어떻게 해야하는지 지시 ㄴㄴ 무엇을 해야하는지 요청 - 의도가 명확해진다
- 이는 객체의 인터페이스 크기를 감소시키고, 외부에서 해당 객체에 의존해야하는 부분이 적어진다
- 메시지가 협력에 필요한 객체를 발견하라!
인터페이스
- 수신가능한 메시지가 인터페이스의 모양을 만든다
- 인터페이스 종류
- 공용 인터페이스 (외부접근 가능)
- 내부 private 인터페이스
메시지가 협력에 참여하기 위해 수신하는 메시지 = 객체의 공용 인터페이스
(RDD의 What/Who 사이클) -> 메시지가 수신자의 인터페이스를 결정
메시지가 공용 인터페이스를 자극함으로써 책임을 수행(다형성)
공용 interface를 기준으로 내부와 외부가 명확하게 분리된다.
인터페이스와 구현의 분리
객체지향 사고방식의 원칙
- 좀 더 추상적인 인터페이스 - 자율성
- 최소 인터페이스
- 외부 사용할 필요없는 인터페이스는 최대한 노출하지 않는다
- 가능한 한 적은 정보를 외부 노출 -> 내부를 수정해도 외부에 미치는 영향을 최소화
- RDD를 따를 때 달성가능(메시지 먼저 결정) - 협력에 필요한 메시지만 외부노출
- 인터페이스와 구현 간에 차이가 있다는 인식
- 휼륭한 객체는 구현을 모르고 인터페이스만 보고 쉽게 상호작용할 수 있는 객체이다
구현을 분리해야하는 이유: sw는 항상 변한다
- 공개된 게 많으면 적은 수정으로도 변경 파급효과가 크다
- 외부 영향을 미치는 위험지대와 언전지대를 구분하여, 안전지대 부분은 자율적으로 수정가능하도록
- 상태와 메서드는 내부이므로, 수정해도 외부에 영향을 미치면 안된다
- 느슨한 인터페이스에 대해서만 결합함으로써 캡슐화 (인터페이스를 수정하지 않는 한 변경을 해도 외부영향이 없다)
객체지향: 내부와 외부를 명확히 분리하는 객체들로 구성된 협력공동체
객체의 책임이 자율적일수록
- 협력의 단순화, 의도를 명확하게 표현하여 이해하기 쉬움
- 변경에 유연
- 전체적인 설계품질 좋아짐
내부와 외부를 명확하게 분리할 수록
- 변경해도 외부에 영향이 많이 없음 - 파급효과 낮다
- 변경에 의해 수정되어야하는 범위가 좁아지고 명확해진다 - 캡슐화
- 두 객체간 결합도가 낮아짐 - 협력하는 대상을 다양하게 선택가능 (유연성)
- 재활용성 높아짐
- 역할이 이해하기 쉽다 - 존재이유가 명확함
(정리하는 시간이 너무 많이 걸려서 6장부터는 다음에 정리하려고 한다. 6장에서는 기능에 초점을 맞추지 말고 구조에 신경쓰는 프로그래밍을 하라는 말이 나오고, 도메인 다이어그램과 유즈케이스를 다룬다. 이 둘을 메시지와 협력의 관점에서 사용하는 방법도 알려준다. 뒤에는 추상화 기법에 대한 설명도 나온다)
이 책은 생소한 용어의 경우 예시를 들어가며 쉽게 설명해주고, 계속 반복적으로 설명해줘서 이해가 쏙쏙된다. 하지만 객체지향에 대해 잘 모르는 사람에게는 만만한 책이 아닌 것 같다(나는 5장이 조금 힘들었다) 그래도 힘내서 읽으면 남는게 참 많은 책이다. 객체지향에 대한 오해를 풀고 새로운 시각을 얻게해준 너무 좋은 책이라고 생각한다. 객체지향 프로그래밍을 하는 사람이라면 필독서인 듯 하다!
'소프트웨어 설계' 카테고리의 다른 글
복잡한 쿼리를 보내더라도 디비에서 처리 vs 서버에서 처리 (0) | 2024.03.14 |
---|---|
디미터 법칙(The Law of Demeter)이란? (0) | 2023.11.15 |
단위테스트란? (0) | 2023.10.24 |