오브젝트 1 3장 객체지향설계

코드로 이해하는 객체지향 설계

객체, 설계

로버트 마틴이 설명한 소프트웨어 모듈이 가져야 하는 세 가지 기능

첫 번째 목적은 실행 중에 제대로 동작하는 것이다.
두 번째 목적은 변경을 위해 존재하는 것이다 .
세 번째 목적은 코드를 읽는 사람과 의사소통하는 것이다.

이해 가능한 코드란 그 동작이 우리의 예상에서 크게 벗어나지 않는 코드다.

이 구절을 읽기 전까지는 이해 가능한 코드란 그저 가독성이 좋은 코드라고 생각했다. 코드가 무슨 동작을 하는지 알기 쉬운 변수명이라든지 한 가지의 일만 한다든지. 그런데 다시 생각해 보면 납득 가지 않는 동작을 한다면 이해가 가능한 코드일까? 우리의 상식처럼 동작을 해야 코드를 읽는 사람과 제대로 의사소통을 할 수 있다.

캡슐화란?

개념적이나 물리적으로 객체 내부의 세부적인 사항을 감추는 것을 캡슐화라 한다.

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

다른 객체는 다른 객체가 무슨 일을 하는지 세부적인 건 몰라도 된다.

객체 자기 자신의 문제를 스스로 해결하도록 코드를 변경하면 코드는 변경이 용이하고 이해 가능해진다. 객체의 자율성이 높아진 것이다.

변경하기 쉬운 설계는?

객체지향 설계, 도메인 주도 설계, 리팩토링 등등 결국 목적은 하나다. 변경하기 쉬울 것. 변경하기 쉽게 만들기 위한 방법들이다.

그렇다면 변경하기 쉬운 설계란 과연 어떤 설계를 말하는 걸까? 한 번에 하나의 클래스만 변경할 수 있는 객체다.

변경사항이 있을 때 변경해야 하는 클래스가 5개만 넘어가도 변경이 어렵다. 객체지향 관점에서 생각해 보면 예를 들어 내가 달리기를 할 수 있게 되었다고 해서 가족들이 변경이 될 필요가 없다.

절차지향과 객체지향

프로세스와 데이터를 별도의 모듈에 위치시키는 방식을 절차적 프로그래밍이라 한다. 데이터를 사용하는 프로세스가 데이터를 소유하도록 동일한 모듈 내부에 위치하도록 프로그래밍하는 방식을 객체지향 프로그래밍이라 한다.

두 방식의 근본적인 차이는 책임의 이동이다. 객체 스스로가 자율적인 존재가 되므로 자신의 문제는 스스로 처리하게 된다. 따라서 이해 가능한 코드가 되고, 객체 내부의 변경이 외부에 영향이 없기 때문에 변경이 쉬워지는 것이다.

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

문득💡 모든 객체가 자율적이어야하나?

실세계에서 무생물은 인간이라는 컨트롤러가 필요하지만 소프트웨어 세계의 객체지향 설계 관점에서는 소프트웨어를 구성하는 모든 객체들이 자율적으로 행동하는 설계가 훌륭한 객체지향 설계이다.

설계란 코드를 배치하는 것이다.

앞에서 이야기한 것들로 종합해 정리해보자면, 우리가 진정 원하는 것은 변경에 유연하게 대응할 수 있는 코드이다. 변경이 가능한 코드는 이해하기 쉬운 코드여야 하고, 이해하기 쉬운 코드는 예상하는 방식대로 객체가 행동하는 코드다.

객체지향 패러다임으로의 전환을 위해 프로그래밍하는 동안 집중해야하는 두 가지는 무엇인가?

  1. 어떤 객체들이 필요한지 고민해야한다.
    • 어떤 객체들이 어떤 상태와 행동을 가지는지 결정해야 클래스의 윤곽을 잡을 수 있다. 객체를 중심에 두는 접근 방법이 설계를 단순하고 깔끔하게 만든다.
  2. 객체를 기능을 구현하기 위해 협력하는 공동체의 일원으로 봐야 한다.
    • 객체를 협력하는 공동체의 일원으로 바라보는 것은 설계를 유연하고 확장 가능하게 한다.

훌륭한 협력이 훌륭한 객체를 만들고, 훌륭한 객체가 훌륭한 클래스를 만든다.

훌륭한 클래스를 설계하기 위한 핵심?

어떤 부분을 외부에 공개하고 어떤 부분을 감출지를 결정하는 것이다. 외부에서는 객체의 속성에 접근할 수 없도록 막고 적절한 public 메서드를 통해서만 내부 상태를 변경할 수 있게 해야 한다.

클래스의 내부와 외부를 구분해야 한다. 객체의 명확성이 객체의 자율성을 보장하기 때문이다. 구현의 자유를 제공한다.

구현의 자유는 외부에서는 구현의 세부적인 내용을 모르기때문에 자유가 생긴다. 외부에 미치는 영향을 걱정하지 않아도 된다. 객체의 상태 는 숨기고 행동만 외부에 공개해야 한다.

메소드와 메시지? 다형성?

객체가 다른 객체와 상호 작용할 수 있는 유일한 방법은 메시지를 전송(request) 하는 것뿐이다. 메시지를 수신한 객체는 스스로 결정에 따라 메시지를 처리할 방법을 결정하는데 수신할 메시지를 처리하는 자신만의 방법이 메소드이다.

객체는 메시지를 전송할 뿐이기 때문에 메소드의 존재를 모른다. 메시지를 전송하면 메시지를 수신한 객체가 메시지를 처리할 방법(메소드)을 자율적으로 결정한다.

메시지와 메소드의 구분에서 다형성의 개념이 출발한다. 다형성은 동일한 메시지를 수신했을 때 객체의 타입에 따라 다르게 응답할 수 있는 능력을 말한다.

역할, 책임, 협력

협력이란 애플리케이션의 기능을 구현하기 위해 수행하는 상호작용이다.

책임은 객체가 협력에 참여하기 위해 수행하는 로직이다.

역할은 객체들이 협력 안에서 수행하는 책임들이 모여 객체가 수행하는 역할을 구성한다.

쉽게 풀어보다면 협력이란 객체들이 서로 메시지를 주고받는 것이고, 책임은 일을 하기 위해 하는 일, 역할은 수행되는 일이라고 할 수 있을 거 같다.

책임을 할당할 때는 메시지가 객체를 결정해야 하고, 행동이 상태를 결정해야 한다.

역할을 구현하는 가장 일반적인 방법은 추상 클래스와 인터페이스를 사용하는 것이다.

추상 클래스와 인터페이스 중 구현하는 방법을 선택하는 기준은 무엇일까?

추상 클래스책임의 일부를 구현해 놓은 것이고, 인터페이스는 구현 없이 책임의 집합만을 나열해 놓은 것이다.

역할을 수행하는 모든 객체들이 공유하는 상태와 행동의 기본 구현이 존재한다면 추상 클래스를 선택하고, 공통의 구현이 필요없고 책임의 목록만 정의되기만 하면 되면 인터페이스로 구현한다.


오브젝트 1-3장 스터디 후기

오브젝트 1~3장까지 읽고 스터디를 진행했다. 질문과 답하기를 통해 내가 읽은 것이 그저 읽은 것이 아니라 학습을 했는지, 머릿속에 있는 것을 설명을 해봄으로 인출 연습을 했다. 오브젝트 스터디가 객체지향 설계에 대해 알아가는 것도 중요하지만 면접 대비가 되었으면 좋겠다는 생각을 했다.

객체지향 설계의 실습을 준비했다. 클래스 다이어그램의 초기 설계를 객체지향 설계로 바꾸는 실습을 해보았다. 실제로 해보니 책으로 읽고 생각하는 것보다 어려웠다.

다음에는 실습을 좀 더 준비해서 코드 관점에서도 다이어그램 관점에서도 모두 생각해 볼 수 있게 준비해야겠다.

질문

사실 Screening이 Movie 안에 calculateMovieFee 메서드가 존재하고 있는지조차 알지 못한다. p49

위의 문장이 이해가 안간다는 질문이 들어왔다. 같이 이야기해보기로 했다. Screening 코드를 보면

private Money calculateFee(int audienceCount) {
        return movie.calculateMovieFee(this).times(audienceCount);
    }

이 코드를 보면 Screeningmovie.calculateMovieFee(this).times(audienceCount)return하고 있다. ScreeningMovie 안에 calculateMovieFee 메서드를 호출하고 있는데 존재하고 있는지조차 알지 못한다는게 말이되느냐는 의견이었다.

이 부분을 메시지와 메소드 설명을 다시 생각해서 본다면 객체가 다른 객체와 상호 작용할 수 있는 유일한 방법은 메시지를 전송(request) 하는 것뿐이고 메시지를 수신한 객체는 스스로 결정에 따라 메시지를 처리할 방법을 결정하는데 수신할 메시지를 처리하는 자신만의 방법이 메소드라고 한다. 객체는 메시지를 전송할 뿐이기 때문에 메소드의 존재를 모른다. 메시지를 전송하면 메시지를 수신한 객체가 메시지를 처리할 방법(메소드)을 자율적으로 결정하게 되는거다.

그렇다면 Screening은 Movie에게 메시지(calculateMovieFee(screening))를 보냈고 Movie가 메소드를 자율적으로 결정했다고 볼 수 있다.

예로 중국집에 짜장면 1개 라는 메시지를 보내면 주문한 사람은 거기서 끝이다. 이 메시지를 처리할 방법은 몰라도 된다. 아니 모른다. 짜장면을 어떻게 만드는지는 중국집만 알게 된다.

results matching ""

    No results matching ""