Post

객체, 설계

1. 객체, 설계

소프트웨어 개발에서는 아직 실무가 이론보다 앞서 있는 분야가 많음

1.1 티켓 판매 에플리케이션 구현하기

소극장 이벤트를 통해 관람권을 나눠준 상황

관람객을 입장시키기 전에 이벤트 당첨 여부를 확인해야 하고 이벤트 당첨자가 아닌 경우에는 티켓을 판매 후 입장

구현 했지만 문제 발생

1.2 무엇이 문제인가

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

모듈이란 크기와 상관 없이 클래스나 패키지, 라이브러리와 같이 프로그램을 구성하는 임의의 요소

  • 실행 중에 재대로 동작하는 것
  • 변경을 위해 존재하는 것
  • 코드를 읽는 사람과 의사소통하는 것

현재 애플리케이션에서 1번 조건만 만족함

예상을 빗나가는 코드

관람객과 판매원이 소극장의 통제를 받는 수동적인 존재!!

이해 가능한 코드란 그 동작이 우리의 예상에서 크게 벗어나지 않은 코드(하지만, 현재는 소극장에서 티켓을 꺼내가는 등 우리의 예상에서 벗어남)

코드를 이해하기 위해서는 여러 가지 세부적인 내용들을 한꺼번에 기억하고 있어야 하기 때문에 이해하기 어려움

하나의 클래스나 메서드에서 너무 많은 세부사항을 다루기 때문에 코드를 작성하는 사람뿐만 아니라 코드를 읽고 이해해야 하는 사람 모두에게 큰 부담을 준다.

변경에 취약한 코드

더 큰 문제는 변경에 취약하다는 것!

이것은 객체 사이의 의존성(dependency)과 관련된 문제

의존성은 변경에 대한 영향을 암시

의존성이라는 말 속에는 어떤 객체가 변경될 수 있다는 사실이 내포돼 있다.

객체사이의 의존성을 완전히 없애는 것이 정답은 아니다.

객체지향 설계는 서로 의존하면서 협력하는 객체들의 공동체를 구축하는 것

따라서 최소한의 의존성만 유지하고 불필요한 의존성을 제거하는 것

객체 사이의 의존성이 과한 경우를 가리켜 결합도(coupling)가 높다고 말한다.

반대로 객체들이 합리적인 수준으로 의존하는 경우에는 결합도가 낮다고 한다.

결합도는 의존성과 관련돼 있기 때문에 결합도 역시 변경과 관련이 있다.

설계의 목표는 객체 사이의 결합도를 낮춰 변경이 용이한 설계를 만드는 것

1.3 설계 개선하기

변경과 의사소통이라는 문제가 서로 엮여 있다.

너무 세세한 부분까지 알지 못하도록 정보를 차단

자율적인 존재로 만든다.

자율성을 높이자

개념적이나 물리적으로 객체 내부의 세부적인 사항을 감추는 것을 캡슐화(capsulization)

캡슐화의 목적은 변경하기 쉬운 객체를 만드는 것

캡슐화를 통해 객체 내부로의 접근을 제한하면 객체와 객체 사이의 결합도를 낮출 수 있기 때문에 설계를 좀 더 쉽게 변경할 수 있다.

Theater는 오직 TicketSeller의 인터페이스(interface)에만 의존

TicketSeller가 내부에 TicketOffice 인스턴스를 포함하고 있다는 사실은 구현(implementaion)의 영역에 속한다.

객체를 인터페이스와 구현으로 나누고 인터페이스만을 공개하는 것은 객체 사이의 결합도를 낮추고 변경하기 쉬운 코드를 작성하기 위해 따라야 하는 가장 기본적인 설계의 원칙

TicketOffice와 협력하는 TicketSeller의 내부 구현이 성공적으로 캡슐화됨

캡슐화를 개선한 후에 가장 크게 달라진 점은 내부 구현을 외부에 노출하지 않고 자신의 문제를 스스로 책임지고 해결한다는 것

무엇이 개선됐는가

의사소통 개선

변경용이점 개선

어떻게 한 것인가

자기 자신의 문제를 스스로 해결하도록 코드를 변경

객체의 자율성을 높이는 방향으로 설계하여 이해하기 쉽고 유연한 설계를 얻음

캡슐화와 응집도

핵심은 객체 내부의 상태를 캡슐화하고 객체 간에 오직 메시지를 통해서만 상호 작용하도록 만드는 것

밀접하게 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도(cohesion)가 높다고 말함

자신의 데이터를 스스로 처리하는 자율적인 객체를 만들면 결합도를 낮출 수 있을뿐더러 응집도를 높일 수 있다.

객체의 응집도를 높이기 위해서는 객체 스스로 자신의 데이터를 책임져야 한다.

외부의 간섭을 최대한 배제하고 메시지를 통해서만 협력하는 자율적인 객체들의 공동체를 만드는 것이 훌륭한 객체지향 설계를 얻을 수 있는 지름길

절차지향과 객체지향

절차적 프로그래밍(procedual programming): 프로세스(process)데이터(Data)를 별도의 모듈에 위치시키는 방식

일반적으로 절차적 프로그래밍은 우리의 직관에 위배됨

절차적 프로그래밍의 세계에서는 관람객과 판매원이 수동적인 존재일 뿐

절차적 프로그래밍의 세상에서는 데이터의 변경으로 인한 영향을 지역적으로 고립시키기 어려움

변경하기 쉬운 설계는 한 번에 하나의 클래스만 변경할 수 있는 설계

절차적 프로그래밍은 프로세스가 필요한 모든 데이터에 의존해야 한다는 근본적인 문제점 때문에 변경에 취약할 수밖에 없다.

객체지향 프로그래밍(object-oriented programming): 데이터와 프로세스가 동일한 모듈 내부에 위치하도록 프로그래밍하는 방식

훌륭한 객체지향 설계의 핵심은 캡슐화를 이용해 의존성을 적절히 관리함으로써 객체 사이의 결합도를 낮추는 것

책임의 이동

두 방식 사이에서 근본적인 차이를 만드는 것은 책임의 이동(shift of responsibility)

책임: 기능을 가리키는 객체지향 세계의 용어

변경 후에 Theater에 몰려 있던 책임이 개별 객체로 이동

객체지향 설계에세는 독재자가 존재하지 않고 각 객체에 적절하게 책임이 분배

따라서 각 객체는 자신을 스스로 책임진다.

객체지향 설계에서의 핵심은 적절한 객체에 적절한 책임을 할당하는 것

설계를 어렵게 만드는 것은 의존성

해결 방법은 불필요한 의존성을 제거함으로써 객체 사이의 결합도를 낮추는 것

결합도를 낮추는 방법은 캡슐화

불필요한 세부사항을 객체 내부로 캡슐화하는 것은 객체의 자율성을 높이고 응집도 높은 객체들의 공동체를 창조할 수 있게 함

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

더 개선할 수 있다

어떤 기능을 설계하는 방법은 한 가지 이상

동일한 기능을 한 가지 이상의 방법으로 설계할 수 있기 때문에 결국 설계는 트레이드오프의 산물

설계는 균형의 예술

훌륭한 설계는 적절한 트레이드오프의 결과물

그래, 거짓말이다!

객체지향의 세계에 들어오면 모든 것이 능동적이고 자율적인 존재로 바뀐다. -> 의인화(anthropomorphism)

1.4 객체지향 설계

설계가 왜 필요한가

설계란 코드를 배치하는 것

좋은 설계란 오늘 요구하는 기능을 온전히 수행하면서 내일의 변경을 매끄럽게 수용할 수 있는 설계

변경을 수용할 수 있는 설계가 중요한 이유는 요구사항이 항상 변경되기 때문

변경을 수용할 수 있는 설계가 중요한 또다른 이유는 코드를 변경할 때 버그가 추가될 가능성이 높기 때문

객체지향 설계

객치지향 프로그래밍은 의존성을 효율적으로 통제할 수 있는 다양한 방법을 제공함으로써 요구사항 변경에 좀 더 수월하게 대응할 수 있는 가능성을 보여준다.

변경 가능한 코드란 이해하기 쉬운 코드

훌륭한 객체지향 설계란 협력하는 객체들 사이의 의존성을 적절하게 조절함으로써 변경에 용이한 설계를 만드는 것

참조

  1. 오브젝트
This post is licensed under CC BY 4.0 by the author.