Post
EN

객체지향의 사실과 오해

객체지향의 사실과 오해

저자

객체지향의 사실과 오해를 읽고 한번 정리해보고자 한다.

이 글은 나의 주관된 생각이고 다수 틀릴 수 있다.

OOP에 관련하여 대학시절에 듣게 되었고, 절자지향적 코드에서 벗어나 객체지향 사고 방식으로 real world에 속하는 것들을 설계하여 프로그래밍을 한다. 주로 이런 내용들을 듣게 되었다. 무엇인가 OOP라는 것이 C언어에서 구조적으로, 모듈같은 성격과는 다른 형태의 코드를 따라 치면서 이것이 OOP 방식으로 짯다고 많이 생각했던 것 같다.

그리고 시간은 흘러 어엿한 8년차 경력 개발자가 되었다. 처음보다는 더 노력하는 모습은 사라지는 것 같고, 책을 읽을 때 마다 나의 코드가 과연 내가 배워왔던데로 잘 짜여지고 있는가에 대해서 의문이 계속해서 들고 있었다.

물론 어느정도 나아진 점은 있다.

상속(inheritance) 인지 포함(composition)인지에 대해서 알아가는 것.

ex)

is a = 상속

has a = 포함

디자인패턴을 이용하여 코드를 분리하고 정리하는 것.

사용하는 프레임워크를 좀더 살펴본다던지, 다른 언어를(scala) 한번 공부해 보면서 함수형 프로그래밍에 관련하여 공부하면서 고통을 느끼는 등 나름 노력은 했던 것 같다.

그러던 중 이 책을 읽게 되었고, 다시금 한번 많은 생각을 하게 되었다.

책의 서문에서 처럼 이 책을 읽는다고해서 바로 나의 코드가 개선되어지거나 하는 것은 아니라는 점과, 저자 역시 모르고 시작했던 부분들에 대해서 후배들이 공부 했을 때 알았으면 하는 내용들로 채워놨다는 것이 마음에 들었다. 적절하게 표현한 것 같다.

객체지향이라는 것을 한번 살펴보자.

객체지향이란 실세계를 직접적이고 직관적으로 모델링할 수 있는 패러다임 으로 많이 설명된다고 한다. 따라서 현실 속에 존재하는 사물을 최대한 유사하게 모방해 소프트웨어 내부로 옮겨오는 작업. 사물에 대한 추상화 라고 한다. 자바의 정석 책을 봤을 때에도 TV라는 객체를 설계하는 예제가 있듯이 OOP를 처음 배우는 그 순간에도 우리는 이런 객체 설계를 하기 위하여 몇번씩은 연습했었다. 이제 앞서 이야기했던 클래스 객체설계를 넘어 비즈니스 로직 안에 객체를 설계하려 했을 때, DDD의 도메인 처럼 설계하려 했을 때, 나는 객체를 설계하지 못했다. 왜냐하면 해당 객체가 어떤 기준으로 잡아야하고 어떤 이름으로 식별되어야 하는지 몰랏기 때문에 설계를 못했었다. 그저 특정 행위에 맞춰 클래스를 설계하고 그것이 동작하는 코드를 작성하는 것 쯤이라고 생각하면 될 것 같다. 결국 이와 같은 코드는 이후에 다시보거나, 유지보수를 할때 엄청나게 스파게티 코드에 볼품없는 떡객체로 남아 있는 것을 보게 된다.

책에서는 이렇게 말한다.

객체를 현실 세계의 생명체에 비유하는 것은 상태와 행위를 캡슐화(encapsulation) 하는 소프트웨어 객체의 자율성(autonomous)을 설명하는데 효과적이다. 현실 세계의 사람들이 암묵적인 약속과 명시적인 계약을 기반으로 협력하며 목표를 달성해 나가는 과정은 메시지(message)를 주고 받으며 공동의 목표를 달성하기 위해 협력(collaboration)하는 객체들의 관계를 설명하는 데 적합하다.

이 내용에서 내가 중요하다고 느끼는 건 암묵적인 약속, 계약, 메시지와 협력이다.

내가 어떤 작업을 하기 위해 객체 설계를 하고 클래스를 만들고 각 객체가 어떻게 동작할지를 분류하고 구현한다.

이때 내가 설계한 객체들은 어떤 메시지에 따라서 동작하고 상태가 바뀌고, 어떤 메시지들만 받을 수 있기 때문에 행동을 제한할 수도 있다. 이런 내용들이 암묵적인 약속이나 설계에 의해서 계약이 되는 형태로 나타나는 것이 아닌가 생각했다.

하지만 내가 개발하는 것에 이러한 개념들을 잘 이해하고 설계했을까? 아닌것 같다. 앞서 이야기한대로 아직 객체 설계가 나에게는 어색하다. 명확한 객체 설계는 어느정도 가능하나 특정 비즈니스 로직이 포함된 부분을 객체화 하는 것이 너무나 애매하다. DDD에서 이야기 하듯 도메인 단위로 묶고 바운더리를 나누고 역할과 책임을 준다는 것. 이 부분에 대한 나의 경험치는 매우 부족하다. 책에서 설명하듯 주변에서 들어왔듯 역할, 책임 그리고 협력을 나누는 것을 명심하고 설계를 해야 된다고 요즘 생각하며 노력하는 중이다.

책에서는 객체의 다양한 특성을 효과적으로 설명하기 위해서는 객체를 상태(state), 행동(behavior), 식별자(identity)를 지닌 실체로 보는 것이 가장 효과적이라고 한다.

상태란 특정 시점에 객체가 가지고 있는 정보의 집합으로 객체의 구조적 특징을 표현한다. 결국 객체가 가지고 있는 멤버 변수의 값들이 곧 상태이다.

행동이란 외부의 요청 또는 수신된 메시지에 응답하기 위해 동작하고 반응하는 활동이다. 결과로 상태를 변경하거나 다른 객체로 메시지를 전달할 수 있다. 객체는 행동을 통해 다른 객체와 협력에 참여하므로 행동은 외부에 가시적이어야 한다. 그리고 행동은 부수효과(side effect)를 초래할 수 있다.

식별자란 어떤 객체를 다른 객체와 구분하는 데 사용하는 객체의 프로퍼티다. 값은 식별자를 가지지 않기 때문에 상태를 이용한 동등성 검사를 통해 두 인스턴스를 비교해야 한다. 객체는 상태가 변경될 수 있기 때문에 식별자를 이용한 동일성 검사를 통해 두 인스턴스를 비교할 수 있다.

그리고 훌륭한 객체지향 설계는 어떤 객체가 어떤 메시지를 전송할 수 있는가와 어떤 객체가 어떤 메시지를 이해할 수 있는가를 중심으로 객체 사이의 협력 관계를 구성하는 것이며, 중심에는 메시지가 위치한다. 객체가 메시지를 선택하는 것이 아니라 메시지가 객체를 선택하게 해야 한다. 이 말은 특정 메시지를 정의 하고 이 행위가 무엇인지 생각하고 이 행위를 하는 객체는 무엇인가를 생각하면 더 나은 설계가 될 수 있을까?

훌륭한 객체란 구현을 모른 채 인터페이스만 알면 쉽게 상호작용할 수 있는 객체를 의미한다. 이것은 객체를 설계할 때 객체 외부에 노출되는 인터페이스와 객체 내부에 숨겨지는 구현을 명확하게 분리해서 고려 한다는 것을 의미하는데, 이를 인터페이스와 구현의 분리 원칙이라고 한다.

결론적으로 객체 설계의 핵심은 객체를 두 개의 분리된 요소로 분할해 설계하는 것이다. 그것은 바로 외부에 공개되는 인터페이스와 내부에 감춰지는 구현이다. 결론적으로는 송신자와 수신자간 느슨한 인터페이스에 대해서만 결합되도록 하는 것. SOLID에도 나오지만 결국엔 왜 분리해야 하는가에 대해서는 서로 의견이 분분하다. 하지만 나는 인터페이스를 분리하는 것에 맞다고 생각한다. 느슨한 결합 그리고 인터페이스에 명시된 내용을 보고서 아 이런 행동을 하겠구나 라는 것을 예상 할 수 있게 하는 것. 앞서 이야기한 훌륭한 객체 설계를 할 수 있는 방법이 되지 않을까 싶다. 인터페이스와 구현을 분리하는 것은 객체지향 설계를 낳는 가장 기본적인 원칙이다. 안타깝게도 대부분의 객체지향 언어가 인터페이스와 구현을 클래스 안으로 섞어 버리기 때문에 많은 설계자들이 인터페이스와 구현을 분리하는 것의 중요성을 잊곤한다. 객체지향의 오래된 격언인 “구현이 아니라 인터페이스에 대해 프로그래밍 하라 [GOF 1994]” 를 따르는 것은 명세 관점과 구현 관점을 명확하게 분리하는 것에서 부터 시작된다.

마틴 파울러는 개념적인 관점과 명세 관점 사이는 그렇게 중요하지 않은 경우가 많지만 명세 관점과 구현 관점을 분리하는 것은 매우 중요하다고 주장한다.

그리고 6장에서는 이런 문구가 앞에 적혀있다.

유일하게 변하지 않는 것은 모든 것이 변한다는 사실 뿐이다. - 헤라클레이토스 (Heraclitus of Ephesus)

위 말이 무엇을 의미 하는 것일까?

결론은 요구사항은 변경된다는 것. 소프트웨어 분야에서 예외가 없는 유일한 규칙은 요구사항이 항상 변경 된다는 것이다. 내가 정확한 기획이 되지 않고 계속해서 변경될 때마다 화를 냈던 내모습이 비춰진다. 이건 진리였는데 왜 화를 냈을까? 결론적으로 좋은 설계는 나중에라도 변경할 수 있는 여지를 남겨 놓는 설계다. 설계를 하는 목적은 나중에 설계하는 것을 허용하는 것이며, 설계의 일차적인 목표는 변경에 소모되는 비용을 낮추는 것이라 한다.

이러한 사항들을 생각하며 다시 한번 설계할 때 최선을 다하면 나의 코드도 달라지지 않을까? 한다.

This article is licensed under CC BY 4.0 by the author.