얼마 전, 약 2년간 다녔던 회사를 퇴사했다.
퇴사 후 한두 달 정도는 아예 코드를 쳐다보지 않고 푹 쉬었다.
이직을 바로 할까 고민하다가, 실업급여를 받을 수 있는 기회도 생겨서 이번 기회에 부족한 부분을 채우기로 했다.
무작정 코드를 작성하기보다는, 내 코드의 구조를 고민하다가 객체지향에 대해 좀 더 깊이 있게 알고, 코드에 적용해보고 싶어졌다.
그러던 중 조영호 저자의 "객체지향의 사실과 오해" 와 "오브젝트" 라는 책을 알게 되었다.
찾아보니 둘다 객체지향 관련 책이지만
"오브젝트"는 실질적인 구현에 관한 코드 위주의 책이고,
"객체지향의 사실과 오해"는 제목 그대로 객체지향의 개념과, 사람들이 오해하는 포인트를 잡아서 설명하는 설명해주는 책이다.
나는 CS지식이 탄탄하지 않아서 평소 코딩을 할 때에도 "왜??" 라는 의문을 품었던 적이 많았다.
그래서 나는 좀 더 개념을 다루는 "객체지향의 사실과 오해"를 선택하게 되었다.
객체지향 프로그래밍이란?
이 책에서는 “커피 주문”이나 “이상한 나라의 앨리스”와 같은 비유를 들어 객체지향 개념을 설명하고 있다.
복잡하다고 느꼈던 개념들이 비유를 통해 훨씬 쉽게 다가왔다.
시너지를 생각하라. 전체는 부분의 합보다 크다. - 스티븐 코비
객체지향 프로그래밍은 현실 세계에 존재하는 사물을 최대한 유사하게 소프트웨어 내부로 옮겨오는 작업이다.
하지만 이 과정은 단순히 현실 세계를 모방하는 것이 아니다.
이 작업은 신세계를 창조하는 것에 가깝다.
객체지향 패러다임의 목적은 현실 세계를 기반으로 새로운 세계를 창조하는 것이다.
책에서는 “커피 주문”을 예시로 들어 설명하고 있다.
손님, 캐시어, 바리스타는 각각의 역할과 책임을 갖고 있으며, 이들은 협력을 통해 문제를 해결한다.
어떤 객체도 단독으로 존재하지 않으며, 항상 협력한다.
"객체는 다른 객체가 무엇(what)을 수행하는지 알 수 있지만 어떻게(how) 수행하는지에 대해서는 알 수 없다"
클래스가 아닌 객체 중심의 사고
객체지향의 중심은 클래스가 아니라 객체다.
메시지를 주고받는 객체의 관점에서 사고의 중심을 전환해야 한다.
클래스는 객체들의 협력 관계를 코드로 옮기는 도구에 불과하다.
소프트웨어 세계와 현실 세계의 가장 큰 차이점은 소프트웨어 세계의 객체들이 모두 “스스로” 행동한다는 점이다.
예를 들어, 전등이 외부의 도움 없이 스스로 켜지고, 자동차가 스스로 시동을 거는 것처럼 말이다.
객체지향의 세계에서 모든 객체는 자신의 상태를 스스로 관리하는 자율적인 존재다.
객체의 상태와 행동
객체는 상태를 통해 과거의 행동을 기억하며, 상태 변경에 따라 유일하게 식별될 수 있다.
상태가 중요한 이유는 과거의 행동이 현재의 행동에 영향을 미치기 때문이다.
하지만 객체지향에서 더 중요한 것은 행동이다.
행동이 상태를 결정하고, 객체를 결정하는 것도 행동이다. 중요한 것은 상태가 아닌 행동에 초점을 맞추는 것이다.
객체지향 입문자들이 자주 하는 실수는 상태를 중심으로 객체를 바라보는 것이다.
상태를 먼저 결정하고 행동을 나중에 결정하면, 설계에 부정적인 영향을 미칠 수 있다.
구체적으로, 이런 접근 방식은 캡슐화를 저해하고, 객체를 고립된 섬처럼 만들며, 결과적으로 객체의 재사용성을 떨어뜨린다.
왼쪽과 오른쪽에 차이점은 지도가 당연히 가져야한다고 생각되는 "정확성"을 버리고 그 "목적"에 집중했다.
즉 상태가 아닌 행동에 초점을 둔 것이다.
결론적으로 객체의 타입을 결정하는것은 객체의 행동뿐이다.
동일한 행동 === 동일한 책임 === 동일한 메시지 수신
일반화/특수화 = 슈퍼 타입/서브 타입
이 개념 역시 행동과 관련이 있다.
슈퍼 타입과 서브 타입을 구분하는 기준은 다른 타입보다 더 특수하게 행동하는지, 아니면 더 일반적으로 행동하는지에 따라 결정된다.
다형성과 책임
다형성이란 서로 다른 유형의 객체가 동일한 메시지에 대해 다르게 반응하는 것을 의미한다.
이러한 다형성은 코드의 유연성을 극대화하며, 객체지향 설계에서 역할과 책임의 명확한 분리를 가능하게 한다.
코드의 재사용성을 높이고, 새로운 객체를 추가할 때 기존 코드를 수정할 필요 없이 확장할 수 있게 만들어준다.
결국 다형성은 객체들이 동일한 인터페이스를 통해 다양한 방식으로 행동할 수 있도록 하여,
설계를 더욱 유연하고 강력하게 만든다.
객체의 책임과 메시지
객체의 책임은 외부에 제공할 수 있는 정보와 서비스의 목록을 의미한다.
이는 객체의 인터페이스를 구성하며, 객체의 역할을 대체할 수 있는 다른 객체는 동일한 메시지를 이해할 수 있어야 한다.
테스트 주도 개발(TDD)의 목표는 역할, 책임, 협력을 명확히 식별하고, 이를 코드로 구현한 후 피드백을 받는 것이다.
테스트는 단지 TDD를 통해 얻을 수 있는 별도의 보너스 같은것이다.
이 과정에서 객체가 자율적이기 위해서는 객체에게 부여되는 책임의 수준 또한 자율적이어야 한다.
“메시지는 어떻게(how)가 아니라 무엇(what)을 해야 하는지를 요청하는 것이다.”
메시지 중심의 설계에서 중요한 것은 메시지가 객체에 무엇을 요청하는가이다.
설계의 품질을 높이기 위해서는 훌륭한 메시지를 선택해야 하며,
객체지향의 강력함은 클래스가 아니라 객체들이 주고받는 메시지에서 비롯된다.
메시지 중심의 설계
객체지향 설계의 핵심은 객체 자체가 아닌 객체들이 주고받는 메시지에 있다.
메시지는 객체가 무엇을 해야 하는지를 요청하며, 이는 객체의 공용 인터페이스를 통해 외부로 노출된다.
책임 주도 설계(Responsibility-Driven Design) 방식에서는 What/Who 사이클을 따른다.
먼저 어떤 행위(What)를 수행할지를 결정한 후, 누가(Who) 그 행위를 수행할지를 결정하는 것이다.
여기서 어떤 행위가 바로 메시지에 해당한다.
이러한 책임 주도 설계는 객체가 아닌 객체들이 주고받는 메시지에 초점을 맞추어, 객체지향의 장점을 극대화한다.
메시지는 어떻게가 아닌 무엇을 해야 하는지를 요청하는 방식으로 설계를 단순화하고, 객체의 인터페이스 크기를 줄인다.
객체의 공용 인터페이스는 외부에서 전송 가능한 메시지의 집합으로 정의되며,
이는 객체가 외부와 어떻게 상호작용하는지를 명확하게 나타낸다.
결론
객체지향 프로그래밍은 객체들의 협력과 메시지에 초점을 맞춘다.
행동이 상태를 결정하며, 객체는 자율적인 존재로서 자신의 상태를 관리한다.
설계의 중심은 객체가 아니라 객체들이 주고받는 메시지에 있으며, 이를 통해 유연하고 확장 가능한 소프트웨어를 만들 수 있다.
역할, 책임, 협력 등 객체지향의 핵심 개념들을 이해하고 적용함으로써, 더 유연하고 확장 가능한 설계를 할 수 있을 것 같다.
이 책을 다 읽고 나니, 객체지향이 무엇인지에 대한 개념이 대략적으로 잡히는 것 같다.
객체지향이라는 주제를 깊이 있게 다루면서도 실생활의 예시를 통해 쉽게 이해할 수 있게 해준 덕분에
복잡하게만 느껴졌던 개념들이 점점 명확해졌다.
특히, 객체지향의 본질과 설계 원칙에 대해 고민하게 되어, 앞으로의 코드 작성에 큰 도움이 될 것 같다.
책에는 "비개발자가 책을 읽더라도 이해하는 데는 큰 무리가 없을 정도로 일반적이고 평이한 난이도를 유지하기 위해 노력했습니다."
라고 써 있지만 나는 아예 객체지향에 낯선 사람보다 객체지향 코드를 적어도 1년 정도 다뤄본 사람에게 더 적합해 보인다.
객체지향의 구조를 고민해본 사람이라면 꼭 읽어보길 권한다.
그리고 어쩌다보니 이 책의 저자인 조영호님께 피드백을 받았다...!
감사합니다 😆