Ch1 객체, 설계 요약

본문


들어가며

오브젝트의 첫 챕터로써 간단한 극장 표 판매 코드를 프로세스와 데이터가 격리된 절차 지향적 코드에서 데이터와 프로세스가 통합된 객체 지향적 코드로 적절하게 리팩토링 하는 과정을 보여주며 객체 지향적인 설계란 무엇인가에 대해 보여준다.


핵심

  • 절차지향적 설계는 프로세스데이터가 별도의 모듈에 위치한다. 하나의 메인 프로세스에서 전체적인 흐름이 이어진다.

  • 객치지향적 설계는 책임의 이동으로 프로세스가 수행된다. 하나의 메인 프로세스가 존재하는 것이 아니라, 시스템(어플리케이션)의 책임이 각 객체들에게 적절히 분배되고 각 객체들은 자신에게 할당된 책임을 자율적인 방식으로 수행한다.

  • 객체가 자율적이라는 의미는 외부로부터 어떤 요청(메시지)를 수신했을 때 객체 자신의 책임을 스스로 수행한다는 것을 의미한다.

  • 객체가 자율적인 존재로 거듭나기 위해서는 적절한 캡슐화가 필수적이다.

  • 캡슐화를 통해 불필요한 세부사항(구체적인 구현)을 객체 내부로 감추고 스스로 처리한다. 이에 따라 내부적으로는 높은 응집도를, 외부적으로는 낮은 결합도를 얻을 수 있다.

  • 외부에서는 캡슐화된 객체에 인터페이스에만 의존하므로 낮은 결합도를 얻을 수 있고, 객체 내부적으로는 스스로의 데이터를 처리하는 등 세부적인 구현 내용(HOW)에 대한 처리를 스스로 수행할 수 있기 때문에 응집도를 높일 수 있다.



소프트웨어 모듈이 가져야 하는 세 가지 기능

로버트 마틴에 따르면 소프트웨어 모듈이 가져야 하는 세 가지 기능이 있다고 한다. 여기서 모듈이란 크기와 상관 없이 클래스나 패키지, 라이브러리와 같이 프로그램을 구성하는 임의의 요소를 의미한다.

  1. 실행 중에 제대로 동작해야 한다.

  2. 간단한 작업만으로 변경이 가능

  3. 코드를 읽는 사람과 의사소통이 가능

소프트웨어가 소프트웨어로써 존재하기 위해서는 제대로 동작해야 함이 당연하다. 아무리 좋은 성능, 설계라고 할지라도 제대로 동작하지 않는다면 그 소프트웨어는 가치가 없을것이다. 중요한 것은 두 번째와 세 번째 항목들이다. 절차지향의 단점이자 객체지향의 장점이기도 하다.


절차지향 설계의 단점

절차지향 설계의 단점 중 하나는 프로세스와 데이터가 서로 분리되어있다는 점이다. 우리가 객체지향 프로그래밍 언어의 대표자인 자바C#을 사용한다고 하더라도 프로세스와 데이터가 서로 분리되어 있다면 그 코드는 절차지향적 설계를 따르는 것이다.

프로세스와 데이터가 서로 분리되어 있게 된다면, 즉 메인 프로세스에서 필요한 데이터들을 각 객체로부터 얻어와 기능을 수행하게 된다면 한 번에 많은 것들을 기억해야 하기 때문에 기능 개발 및 코드 독해에 악영향을 끼치게 된다. 이는 추상화 수준이 다른 프로세스들이 하나의 메인 프로세스에 섞여 공존하기 때문이기도 하다.

다시말해 메인 프로세스에서 기능을 수행하기 위해 필요한 데이터들이 어떤 것들이 있는지, 그리고 그 데이터들은 어떤 객체들이 가지고 있는지 등을 추상화 수준에 상관 없이 모두 파악해야만 한다.

그리고 더 중요한 것은 바로 변경이 용이하지 않다는 점이다. 절차지향적 설계는 변경에 유연하지 못하다. 이는 위에서 언급한 프로세스와 데이터의 분리와도 관련이 있다. 바로 강한 결합도가 그 원인이다.

프로세스와 데이터가 서로 분리되어 있다면 자연스럽게 메인 프로세스에서는 필요한 데이터를 갖는 모든 객체들과의 의존성이 생기기 마련이다. 이 뿐만 아니라 데이터의 데이터의 데이터..와 같이 보다 깊숙한 곳까지 접근해야 할 수도 있다.

이 경우 의존하는 객체 중 단 한 가지만이라도 변경되게 된다면 이는 해당 객체에 의존하는 다른 객체, 나아가 메인 프로세스에까지 큰 파급효과를 미치게 된다.


객체지향 설계의 장점

객체지향적 설계는 위에서 언급한 절차지향적 설계의 단점들을 보완함으로써 장점을 갖게된다.

절차지향적 설계의 가장 큰 단점은 강한 결합도로 인한 변경의 어려움이라고 하였다. 객체지향 설계가 도대체 어떤 방법으로 이와같은 문제를 풀어낼 수 있을까?

한 마디, 아니 한 단어로 요약하자면 자율성 이다. 자율적인 객체자신의 데이터를 자신이 직접 처리하는 객체를 의미한다. 그리고 이를 가능케 해주는 개념이 바로 캡슐화이다.

캡슐화를 통해 느슨한 결합도, 높은 응집도, 변경의 용이함을 취할 수 있다.

캡슐화단편적인 의미개념적 또는 물리적으로 객체 내부의 세부적인 사항을 감추는 것을 의미한다. 캡슐화의 목적은 변경하기 쉬운 객체를 만드는 것이다. 다시말해 인터페이스와 구현을 분리하고 외부에는 인터페이스만을 노출함으로써 객체의 세부 사항에는 접근하지 못하게 한다.

객체가 적절히 캡슐화된다면 자연스럽게 외부에서는 인터페이스를 통해서만 객체에게 요청을 하게 되고 요청을 받은 객체는 자신의 데이터를 직접 처리함으로써 자율성을 갖게된다.

이는 곧 데이터와 프로세스가 통합된 객체가 무엇을 의미하는지를 깨닫게 해준다.

단순히 상태(데이터)메서드를 갖는다고 해서 자율적인 객체가 아니다. 자신의 데이터를 자신이 직접 처리하는 객체일 때 비로소 자율성을 갖게된다.


캡슐화와 응집도

위에서 ‘캡슐화’를 단순히 객체에만 적용시킴으로써 객체 내부를 감추는 것에만 국한하여 언급했지만. 보다 정확한 의미는 ‘변경되는 모든 것을 감추는 것’을 의미한다. 이에 대해서는 차후 챕터에서 깊히 다루도록 하자.

핵심은 캡슐화다. 객체 내부의 데이터, 구현 방식과 같은 변경 가능성이 높은 세부사항을 캡슐화하고 객체 간에 오직 메시지를 통해서만 상호작용 하도록 만드는 것이다.

캡슐화된 객체는 밀접하게 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임한다. 이러한 객체를 가리켜 응집도가 높다고 말한다. 자신의 데이터를 스스로 처리하는 자율적인 객체를 만들면 결합도를 낮출 수 있을 뿐더러 응집도를 높일 수 있다.

훌륭한 객체지향 설계의 핵심은 ‘캡슐화’를 이용해 의존성을 적절히 관리함으로써 객체 사이의 결합도를 낮추는 것이다. 객체지향 코드는 자신의 문제를 스스로 처리해야 한다는 우리의 예상을 만족시켜주기 때문에 이해하기 쉽고, 객체 내부의 변경이 객체 외부에 파급되지 않도록 제어할 수 있기 때문에 변경하기가 수월하다.


캡슐화와 결합도

절차지향 설계에서 설계를 어렵게 만드는 것이 높은 결합도라고 말했던 것을 기억하자. 해결 방법은 불필요한 의존성을 제거함으로써 객체 사이의 결합도를 낮추는 것이다. 결합도를 낮추기 위해 할 수 있는 가장 기본적이고 좋은 선택지는 바로 캡슐화이다. 적절히 캡슐화된 객체는 외부에 인터페이스만을 노출하고 메시지를 통해서만 의사소통하기 때문에 단지 인터페이스에만 의존할 수 있게된다. 즉, 캡슐화를 통해 인터페이스에만 의존하게끔 함으로써 낮은 결합도를 유지할 수 있게 된다.


결국 캡슐화다.

결과적으로 불필요한 세부사항을 객체 내부로 캡슐화하는 것은 외부에서 인터페이스에만 의존하게 함으로써 결합도를 낮추고 객체는 자신의 데이터를 스스로 처리함으로써 자율성은 높아지며, 관련없는 사항은 다른 객체에게 위임함으로써 응집도는 높아진다.

불필요한 세부사항을 캡슐화하는 자율적인 객체들이 낮은 결합도와 높은 응집도를 가지고 협력하도록 최소한의 의존성만을 남기는 것이 훌륭한 객체지향 설계다.


책임의 이동

객체지향 설계에서는 독재자(메인 프로세스)가 존재하지 않고 각 객체에 책임이 적절히 분배된다. 따라서 각 객체는 자신의 책임을 스스로 수행한다. 객체지향 어플리케이션은 스스로 책임을 수행하는 자율적인 객체들의 공동체를 구성함으로써 완성된다.

사실 객체지향 설계의 핵심은 적절한 객체에 적절한 책임을 할당하는 것이다. 객체는 다른 객체와의 협력이라는 문맥 안에서 특정한 역할을 수행하는 데 필요한 적절한 책임을 수행해야 한다. 따라서 객체가 어떤 데이터를 가지느냐 보다는 객체에 어떤 책임을 할당할 것이냐에 초점을 맞춰야 한다.


객체지향 설계

우리가 진정으로 원하는 것은 변경에 유연하게 대응할 수 있는 코드다. 객체지향 프로그래밍은 의존성을 효율적으로 통제할 수 있는 다양한 방법을 제공함으로써 요구사항의 변경에 좀 더 수월하게 대응할 수 있는 가능성을 높여준다.

객체지향 패러다임은 우리가 세상을 바라보는 방식대로 코드를 작성할 수 있게 돕는다. 세상에 존재하는 모든 자율적인 존재처럼 객체 역시 자신의 데이터를 스스로 책임지는 자율적인 존재다.


참고 및 출처

  • 오브젝트