데미안
브로콜리 펀치 (이유리 소설집)
클린 아키텍처: 소프트웨어 구조와 설계의 원칙 (살아있는 전설이 들려주는 실용적인 소프트웨어 아키텍처 원칙)
브로콜리 펀치 (이유리 소설집)
소설에서 기이하고 신기한 현상들이 일어나지만 우리가 상상해 보거나 우리에게도 일어날 법한 일들도 적혀있어 더욱 공감이 가고 재미있었다. 이 책의 공통적인 키워드는 위로라고 생각한다. 브로콜리 펀치에서 격투기 경기에서 이기기 위해 상대방을 미워하는 노력을 하는 복싱선수에게 이제 힘들다면 그만해도 괜찮다고 다독여주며 복싱 선수의 마음을 알아주는 것과 손톱 그림자에서 다시 살아서 돌아온 전 남자친구를 대하는 태도에서 느껴지는 미안한 마음을 보며 책 인물뿐만 아니라 독자에게도 공감과 위로를 건네주며 힘을 주는 소설이라는 생각이 들었다.
클린 아키텍처: 소프트웨어 구조와 설계의 원칙 (살아있는 전설이 들려주는 실용적인 소프트웨어 아키텍처 원칙)
Y의 비극
오브젝트 (코드로 이해하는 객체지향 설계)
역할 책임 협력
- 객체지향에서 가장 중요한 것은 역할,책임,협력이다.
- 역할,책임,협력을 고려하지 않은 채 상속,클래스,지연 바인딩과 같은 구현요소에 초점을 맞추면 유연하지 못한 코드를 낳는 원인이 된다.
영화 예매 시스템 돌아보기
- 다양한 객체들이 영화예매라는 usecase를 달성하기 위해 메시지를 주고받으며 상호작용(협럭) 한다.
협력
- 다른 객체에게 무언가 요청하는 것
- 메서드 : 메시지를 처리하는 방법
- 객체의 자율성을 보장하기 위해서는 필요한 정보와 정보에 기반한 행동을 클래스 안에 모아두어야 한다. => 응집
- 객체를 자율적으로 만드는 기본적인 방법은 캡슐화이다.
- 자신에게 할당된 정보 이외의 정보가 필요하면 다른객체에게 협력을 요청하자.
협력은 설계를 위한 문맥을 결정한다.
객체가 가질 행동과 상태를 결정하는 기준은?
- 객체가 참여하고 있는 협력이 기준이 된다.
- ex: movie객체는 어떤 행동을 수행해야 할까?
- movie의 관점에서 생각을 하면 movie.play()를 떠올릴 수 있다 -> x
- 협력의 관점에서 생각해야한다. movie는 예매라는 협력에 참여하고 있다.
- 협력에 의거하여 행동을 결정한다.
- 행동은 상태를 결정한다
- 협력 –(결정)–> 책임(=행동->메시지) –(결정)–> 상태
책임
- 책임은 행동이다.
- 책임은 하는 것과 아는 것으로 나뉜다.
- ex 영와 예메 협력
- 메시지 -> 예매,요금 계산,할인 계산, 할인 조건 … [하는 것 책임]
- 예매 메시지에서 영화요금을 알아야 한다.[아는 것 책임]
- 메시지 <= 책임
- Movie 에게 요금 계산 책임을 할당
- 요금계산 메시지를 받는다 -> calculateFee() -> 할인정보는 모름으로 메시지 요청한다.
- 영화(요금) 정보를 알아야한다. -> fee
책임할당 자세히
- 책임할당은 정보전문가에게 책임을 할당하자 (정보전문가 전략)
- 협력을 설계하는 출발점은 시스템의 책임
- 시스템 책임이 영화예매 일때
- 영화 예매라는 책임을 달성하기위해 다른 객체에게 메시지를 보내야 한다.
- 이로써 메시지 이름을 도출할 수 있다 -> 예매하라(reserve)
- 메시지를 처리할 객체를 선택한다
- 정보 전문가는 누구인가? -> 상영+요금을 알야아한다. -> ‘상영’도출
- 요금에 대한 전문가는 ‘상영’이 아니다
- ‘요금계산하라’ 라는 메시지를 보내야한다.
- 정보 전문가는 누구인가? -> 요금과 할인정보를 알고있어야 한다. -> ‘할이정책’ 도출
- …
정리
- 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
- 시스템 책임을 더 작은 책임으로 분할한다.
- 분할된 책임을 수행할 수 있는 적절한 객체 또는 역할을 찾아 책임을 할당한다.
- 객체가 책임을 수행하는 도중 다른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
- 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 된다.
메시지가 객체를 선택하는 이유
- 최소 인터페이스를 가질 수 있고 추상적인 인터페이스가 도출된다는 장점
- 협력 ->행동(=책임->메시지) -> 정보전문가 도출(객체) 맟 상태 도출
역할과 협력
- 역할: 책임의 집합
- 역할에 책임을 할당한다고 생각하자.
- 역할을 통해 유연하고 재사용 가능한 협력을 얻을 수 있다.
- ex: 퍼센트 요금계산, 금액 요금계산 -> 객체관점 -> x
- 요금계산 역할 -> 추상화 -> o
- 역할은 일종의 슬롯이다. 누구든지(객체) 역할의 책임을 다한다면 교체될 수 있다. -> 추상화
역할의 구현방법
- 추상클래스 -> 책임의 일부를 구현해논다.
- 인터페이스 -> 책임에 대해서 정의(나열)만 해논다.
- 단 협력에 참여할 수 있는 대상은 후보(역할,객체)인데 한객체만 참여할 필요가 있다면 후보는 객체가 된다. 쉽게 말해 항상 역할을 고려할 필요는 없다는 것
- “객체가 무슨역할을 수행해야 되는가?” 라고 자문하자
- 역할과 객체가 동일한지 아닌지로 후보를 결정하자
- 설계 초반에는 절절한 책임과 협력의 큰그림을 탐색하는 것이 우선되어야한다.
- 이후 반복적으로 책임과 협력을 정제해 가면서 필요한 순간에 객체로부터 역할을 분리하는 전략을 취하자
- 후보의 상세결정은 초반에 고려하지 않는다
- 도메인 모델에 개념을 후보로 생각하고 책임할당한 뒤 이후에 정제하자
역할과 추상화
- 객체는 협력에 따라 역할이 달라질 수 있다.
- 역할은 협력에 참여하는 잠시동안에만 존재하는 개념이다
- 문맥(협력)안에서 무엇을 하는지에 의해서만 정의된다.
객체지향의 사실과 오해 (역할, 책임, 협력 관점에서 본 객체지향)
객체 상태 행동 식별자에 관한 이야기
행동은 외부의 메세지에 따라 수행되고 행동의 결과는 상태에 의존적이며 행동은 상태를 변경한다.
행동은 사이드이펙트가 발생하며 다른 객체의 상태를 변경하도록 행동을 요청할 수 있다
우리는 자율적인 객체를 설계하도록 노력해야한다. 객체가 자율적일 수록 OCP 원칙을 지키게 되며 유지보수가 용이한 코드가 완성된다.
Entity에 관한 이야기
entity는 외부세계에 노출하지 말아야 한다. 때문에 request dto를 사용하는 것이다.
커맨드와 쿼리를 분리하여라, 예를들어 update메소드에서 갱신 후에 entity를 반환하면다면 갱신명령과 조회쿼리가 혼합된다. 이를 분리하는 것은 유지보수성에 용이하다.
객체설계시 상태가 아닌 행동중심적 사고를 가져야한다. 행동중심적 사고로 설게하면 객체지향의 본질을 보다 지킬 수 있다.
객체지향은 현실세계를 모방하는 것이 아니라 은유에 가깝다. 현실객체를 기반으로 새로은 세계를 창조하는 것. 다만 현실객체를 은유하기 위해 해당하는 특징과 일치하는 현실세계의 객체의 이름을 사용하는 것이 좋다.
헨리백이 지하철 노선을 단순화 한것 처럼. 추상화는 단순화라는 목적을 가진다. 먼저 구체적인 사물들을 하나로 묶기위해 차이점을 버리는 일반화를 진행하고, 목적에 불필요한 속성들을 제거하면 된다. 이로보아 추상화는 목적에 의존적인 것을 알 수 있다.
분류는 추상화하기 위한 도구이고 개념을 가지면 분류를 할 수 있다.
개념의 3가지 속성
심볼,내연,외연
심볼은 각 개념을 구별할 수 있는 이름
내연은 각 개념에 속하는지 판별할 수 있느 특징
외연은 각 개념에 속하는 집합
타입은 개념이다
타입 은 1010101로 표현되는 데이터에게 특정한 행동을 할 수 있도록 분류해 놓은 것
클래스도 타입이다 정확히 타입을 구현하는 방법중 하나가 클래스이다 클래스는 코드의 재사용성을 위해서도 사용될 수 있다
클래스를 만든다는 것은 특정한 행동을 할 수 있도록 분류하는 것이고 때문에 클래스를 설계할 때
행동 중심적 사고가 이루어져야한다
행동은 책임이다
객체를 설계힐때 어떤행동이 필요한지 탐구하고 상태는 부수적인것
일반화 특수화 , 특수화는 일반화의 부분집합이다. 트럼프 인간은 트럼프에 속하는 것처럼
이 관계에서는 리스코프 치환원칙이 권장된다 개념의 내연이 많아질수록 외연은 적어진다
기억할 것은 행동을 기준으로 타입을 분류하고 타입을 기준으로 객체를 구성하면 된다
협력관점에서 보는 것이 가장 중요하다
어떤 협력이 필요한지 파악하고, 해당협력을 위해 어떤 메시지들이 필요한지 생각한다. 그다음 메시지를 수신할 객체를 정하거나 생성하고 해당 객체는 메시지에 대한 책임을 가지고 그에 응하는 행동을가진다. 이런 책임이 여러객체에서 가지게 된다면 그것은 역할로 추상화 되도록 설계한다.
다른 객체에게 메시지를 던질 때 해당 객체의 자율성을 해치는 수준의 메시지를 던지게 되면 유연성이 떨어진다. 객체는 자율성을 가지면서 해당 메시지에 대한 책임을 수행하는 방법을 선택하게 되어 많은 장점을 가지기때문이다. 그렇다고 너무 추상화된 메시지를 던지게되면 책임이 불분명해질 수 있다,
메시지는 해당객체에게 협력에 대한 책임을 수행하도록 요청할때 사용되며 수신자는 해당 책임을 수행하기 위한 방법을 선택하는 수단을 메소드라고 한다.
다형성은 메시지를 기반으로 객체간의 결합도를 낮추면서 수신자에 대한 정보를 최대한 모르게 구성하여 같은 책임을가지는 다른객체도 협력을 위해 사용될 수 있게 구성되는 것이다.
책임주도설계과 메시지의 중요성
협력문맥내에서 메시지 중심 사고를 해야하고 메시지를 정하고 객체를 찾아야한다. 쉽게 방법을 정의하면 협력을 책임지는 객체를 정하고 해당 책임을, 협력을 이루기위한 메시지들을 구성한뒤 적절한 객체에 메시지를 수신할 수 있도록 한다. 그러면 객체의 자율성과 캡슐화를 증진시킬 수 있고 메시지 기반사고는 인터페이스를 발견할 수 있다. 메시지를 기반으로 협력을 구성하는 것은 객체지향 장점을 극대화한다
인터페이스란 사물간의 상호작용을 위한 통로이다.
메시지가 인터페이스를 결정하고 인터페이스는 공용 인터페이스와 사적인터페이스로 나뉜다. 공용은 외부와 협력하기 위한 수단이고 사적은 객체 자신이 자신에게 메시지를 보내기 위한 수단이다. 이렇게 분리하는 것은 변경으로부터 안전한공간과 위험한공간을 분리하기 위함이고 이는 캡슐화를 의미한다.
객체의 자율성
인터페이스와 구현의 분리를 가지게 되면 객체의 자율성을 확보할 수 있다.
객체의 자율성을 확보하게 되면 외부객체는 객체의 추상화된 행동으로 메시지를 송신할 수 잇고 이는 다른 객체여도 같은책임을 한다면 대체할 수 있음을 의미한다. 또한 같은 메시지안에서 수신받는 객체는 다른 메소드를 선택하더라도 협력관점에서의 변경은 일어나지 않는다. 또한 객체의 자율성을 해치는 추상적이지 않은 메시지를 송신할 경우, 즉 객체의 처리순서까지 강제할경우 처리순서가 바뀌면 협력관점에서의 변경이 일어난다. 이처럼 객체가 자율성을 가지게 설계한다는 것은 변경에서 자유로워 지고 협력을 파악하는데 간단해진다는 것을 의미한다.
도메인 설정
요구사항을 기반으로 현실세계를 은유하여 존재하는 객체를 식별하고 타입으로 추상화하여 관계를 나타낸 것은 도메인 모델이라고 한다
협력 식별
도메인 모델간 필요한 협력을 식별하고 협력에 필요한 메시지들을 식별한다. 메시지가 식별되면 해당메시지를 수신하기에 적절한 도메인을 설정한다 이 메시지를 기반으로 인터페이스가 발견된다
구현 단계
발견된 인터페이스를 기반으로 실제 구현작업에 들어가며 내부적인 속성이나 메시지의 책임를 수행할 수 있는 코드를 작성한다. 이때 인터페이스가 수정될 수 있다 이것은 자연스러운 일이다
