지금껏 객체지향에 대해 모호하게 알고 있을 뿐 뚜렷한 개념이 잡혀있지 않았다. 이 책을 통해 내가 모호하게 알고 있던 그 부분마저 오해였다는 것을 알게 되었다. 책을 읽으며 오해하고 있던 부분, 새로 알게 된 부분을 정리해봤다.
객체지향의 목표는 실세계를 모방하는 것이 아니다. 오히려 새로운 세계를 창조하는 것이다.
객체지향이란 현실 세계를 추상화해 구현해 놓은 것이라고 들었었다. 하지만 소프트웨어 객체는 현실 속의 객체가 가지지 못한 추가적인 능력을 보유하게 된다고 한다.
현실 세계 속에서 계좌는 스스로 돈을 이체할 수 없고, TV는 스스로 채널을 바꿀 수 없다. 하지만 객체지향 세계에서는 현실 속에서 할 수 없는 어떤 일이라도 할 수 있다.
레베가 워프스브룩은 현실의 객체보다 더 많은 일을 할 수 있는 소프트웨어 객체의 특징을 의인화
라고 부른다.
객체 공동체에 속한 객체들은 공동의 목표를 달성하기 위해 협력에 참여하지만 스스로의 결정과 판단에 따라 행동하는 자율적인 존재다
협력적이라는 말은 다른 객체의 명령에 복종하는 것이 아니라 요청에 응답함을 말한다. 객체지향에서는 협력을 위해 유일한 의사소통 수단인 메시지
를 통해 요청을 전송하고 수신한다.
메시지를 수신한 객체는 자신만의 방법에 따라 메시지를 처리하는데 , 이 방법을 메서드
라고 한다.
객체는 다른 객체가 ‘무엇(what)’을 수행하는지 알 수 있지만 ‘어떻게(how)’ 수행하는지에 대해서는 알 수 없다.
객체의 자율성은 객체의 내부와 외부를 명확히 구분하는데서 나온다. 객체의 내부 동작은 객체 스스로 관리하고, 다른 객체가 간섭할 수 없도록 해야 한다. 그리고 다른 객체의 내부 동작을 외부에서는 알 수 없다.
객체지향의 핵심은 클래스가 아니다. 핵심은 적절한 책임을 수행하는 역할 간의 유연하고 견고한 협력 관계를 구축하는 것이다.
객체지향에서 중요한 것은 어떤 클래스가 필요한가가 아니라 어떤 객체들이 어떤 메시지를 주고받으며 협력하는가다. 클래스는 객체들의 협력 관계를 코드로 옮기는 도구에 불과하다.
그래서 객체지향이 무엇인가? 이 책에 따르면 객체지향의 개념은 다음과 같다.
객체란?
객체를 상태(state), 행동(behavior), 식별자(identity)를 지닌 실체로 보는 것이 가장 효과적이다.
객체의 행동이 상태를 변경시킨다. 그러니 객체를 설계할 때 상태보다 행동을 먼저 결정해야 한다.
객체지향 설계는 애플리케이션에 필요한 협력
-> 협력에 필요한 행동
-> 행동을 수행할 객체
순서로 결정한다.
객체지향 패러다임은 객체라는 추상화를 통해 현실의 복잡성을 극복한다.
추상화란 불필요한 부분은 무시하고 중요한 부분을 강조해 사물의 본질을 드러나게 하는 과정이라 할 수 있다. 공통점을 기반으로 객체을 묶기 위한 그릇을 타입(type)이라 한다. 객체에 어떤 객체에 타입을 적용할 수 있을 때 그 객체를 타입의 인스턴스(instance)라고 한다.
객체의 타입을 결정하는 것은 객체의 행동뿐이다
객체가 어떤 데이터를 보유하는지, 어떻게 데이터를 표현하는지 등은 상관이 없다. 같은 타입에 속한 객체들은 동일한 행동, 즉 동일한 책임만 가지고 있으면 된다. 이는 동일한 메시지를 수신함을 의미한다.
동일한 메시지를 수신하더라도 메시지 처리 방법은 다를 수 있다. 동일한 요청에 대해 서로 다른 방식으로 응답할 수 있는 능력을 다형성 이라고 한다. 이는 객체들이 동일한 책임을 공유한다는 말과 같다. 같은 타입에 속하는 객체들은 다형적이다.
행동만이 고려된다는 점은 다시 말해 객체의 내부는 감춰야 한다는 말과 같다. 외부에는 행동만을 노출하며, 송신자는 수신자의 내부 상태 변화를 알 수 없다. 이러한 원칙을 캡슐화라고 한다.
협력
협력의 어떤 문제를 해결하기 위해 참여하는 객체들 간의 연쇄적인 요청과 응답의 흐름으로 구성된다.
책임
어떤 객체에 대한 요청은 그 객체가 요청을 처리할 책임이 있다고 본다. 책임의 객체의 외부에 제공해 줄 수 잇는 정보와 외부에 제공해 줄 수 있는 서비스의 목록이다. 즉, 메시지는 책임을 의미한다고 할 수 있다.
역할
역할은 협력을 추상화할 수 있고, 대체 가능하기 때문에 객체지향 설계의 단순성, 유연성, 재사용성을 뒷받침하는 핵심 개념이다. 역할을 대체 가능할 객체는 동일한 책임을 수행할 수 있는 객체로 제한한다. 즉, 동일한 타입 내의 객체들끼리만 가능하다(라고 나는 이해했다).
이 책에서는 협력, 역할, 책임의 관점에서 애플리케이션을 설계하는 방법을 다음과 같이 소개했다.
책임-주도 설계(RDD)
협력에 필요한 책임을 식별하고, 적합한 객체에게 책임을 할당하는 방식이다.
디자인 패턴
전문가들이 특정 문제를 해결하기 위해 이미 식별해 놓은 역할 책임, 협력의 모음이다.
테스트-주도 개발(TDD)
테스트를 먼저 작성하고 테스트를 통과하는 구체적인 코드를 작성해 나가는 방식이다.
객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택해야 한다.
어떤 객체가 메시지를 처리할지를 먼저 생각하지 말고, 메시지를 우선 생각하자. 객체를 독립된 단위로 보고 객체의 상태나 행위에 집중하게 되면 객체의 자율성을 저해한다.
인터페이스는 객체가 책임을 수행하기 위해 외부로부터 메시지를 받기 위한 통로이다.
인터페이스 사용법을 안다면 대상의 내부 구조를 몰라도 상호작용할 수 있다. 인터페이스가 동일하다면 어떤 대상과도 상호작용이 가능하며, 내부 구조가 변경되어도 인터페이스가 변하지 않으면 사용자에게 아무런 영향을 미치지 않는다.
공용 인터페이스 : 객체의 외부에 공개된 인터페이스
구현 : 객체를 구성하지만 공용 인터페이스에 포함되지 않는 모든 것. 객체의 내부 구성을 말함
앞에서 자율성은 객체의 내부와 외부를 명확히 구분하는데서 나온다고 했다. 이는 공용 인터페이스와 구현을 명확히 분리하라는 말과 동일하다.
훌륭한 객체란 구현을 모른 채 인터페이스만 알면 쉽게 상호작용할 수 있는 객체를 의미한다. 이를 인터페이스와 구현의 분리 원칙이라고 한다.
소프트웨어는 항상 변경된다. 수많은 객체가 얽힌 객체지향의 세계에서 어떤 객체가 수정되었을 때 다른 어떤 객체가 영향을 받는지 판단하는 것은 거의 불가능하다.
그래서 객체를 수정해도 다른 객체에 영향이 가지 않도록 객체 내부 구현에 정보를 감춰둬야 한다.
객체지향 설계 안에는 세 가지 관점이 존재한다
개념 관점(Conceptual Perspective)
도메인 안에 존재하는 개념과 개념들 사이의 관계
명세 관점(Specification Perspective)
객체가 협력을 위해 '무엇' 을 할 수 있는가(책임)에 초점을 맞줌 -> 인터페이스
구현 관점(Implementation Perspective)
객체의 책임을 '어떻게' 수행할 것인가에 초점을 맞추며 코드를 작성하는 것 -> 클래스 내부 구현
세 관점은 동일한 코드를 바라보는 서로 다른 관점이다. 코드를 작성할 때 세 가지 관점이 명확하게 드러날 수 있게 작성해야 한다.
책에는 구현 부분이 많이 나오지 않기 때문에 협력과 책임, 역할을 어떻게 코드에 적용해야 하는지는 명확히 이해하지 못했다. 그래도 어떤 부분에 신경써야 하는지 이제 알게 되었기 때문에 앞으로 코드를 작성할 때 계속 생각하면서 적용해봐야겠다.
이 책에서 딱 하나의 단원만 읽는다면 6장을 읽어야 한다고 들었다. 그만큼 중요한 단원이라고들 하는데, 경험이 부족해서인지 개념이 부족한 것인지 나는 이해를 못했다...여러번 다시 읽어보고 추후에 다시 정리할 예정이다.