Post

객체의 협력과 역할 그리고 책임

객체의 협력과 역할 그리고 책임

최대한 객체지향적으로 개발을 하려고 하다보니 객체지향에 대해 전혀 모르고 있었다는 것을 깨달았다. 자바언어도 공부하고 싶던 찰나에 객체지향에 대해 자세히 알고싶었다. ( 답답했음.. )

image

객체지향의 사실과 오해 ( 조영호 저 )

항간에 객체지향에 대해 공부하는 데 좋기로 매우 유명한 책을 e-book으로 구매했다. 아침과 저녁 이동시간에 짬짬이 보고있다. 학부시절 배웠던 객체에 대해 생각해보면 객체는 클래스가 틀이고 어쩌고 뭐 항상 이런 식으로 배웠던 것 같다. 이 책의 첫 장을 보기 전까지는 객체는 그저 클래스안에 정의된 어떤 Thing… 이라고만 추상적으로 알고있었다.
저자는 객체를 협력과 역할과 책임 관점에서 바라보고 책을 집필했다. 매우 신박했고 부끄럽지만 처음 접한 관점이었다. 이제서야 객체가 뭔지 어렴풋이 알 것 같다.

객체는 협력한다

객체지향 프로그래밍을 실제 우리가 사는 세계와 비슷하다고 하는 경우가 많다. 비슷하기는 하나 꼭 맞는 말은 아니라고 한다.
비슷한 경우를 들어 얘기를 해본다. 객체는 어떤 기능 혹은 일(목표)의 달성을 위해 서로 협력한다. 책에서는 카페에서 커피를 주문하는 하나의 프로세스를 예로 든다.
저자의 예시를 인용하자면 ( 꼭 직접 읽어보자 ) 카페에는 손님, 캐셔, 바리스타가 있다. 손님은 캐셔에게 커피를 주문한다. 캐셔는 받은 주문내역을 바리스타에게 넘겨주고 바리스타는 커피를 만든 뒤, 캐셔에게 커피를 주면 캐셔가 바리스타에게 커피를 받아 손님에게 커피를 제공한다. 이런 프로세스에서 손님, 캐셔, 바리스타는 각각 객체이고 세 명이 협력해야 이 프로세스가 완료된다. 손님이 커피를 주문하지 않으면, 캐셔가 받은 주문을 바리스타에게 전달해주지 않으면, 바리스타가 커피를 만들지 않으면 이 프로세스는 제대로 동작하지 않을 것이다.

객체의 역할과 구현, 책임

앞서 말한 예시는 너무 저자의 예시를 배껴온 것이므로 나만의 예시를 생각해보겠다.
지금 간단하게 떠오르는 게 학교의 프로세스다.
학교에는 선생님 역할과 학생 역할이 존재한다. 역할이라는 것은 그 선생님 역할에 누가오든 학생을 가르치기만 하면 되는 것이고 학생 역할에 누가 됐든 수업을 들으면 되는 것이다. 선생님이 바뀐다고 학생이 수업을 듣는 것 자체에 영향을 주지 않는다. 물론 강의 실력의 편차로 인해 약간 못 가르칠 수도 있지만 어쨌든 가르친다는 것이 중요한 것이다. (SOLID 원칙 중 리스코프 치환원칙)
즉, 선생님이라는 역할은 학생을 가르쳐야하는 책임이 있고, 학생이라는 역할은 수업을 들어야하는 책임이 있다. 그리고 독사 선생님이 학기 중에 퇴직하시고 나무늘보 선생님이 오셨다한들 선생님이라는 역할_과 *학생을 가르쳐야하는 책임_은 변하지 않는다. 학생 역시 마찬가지이다.
이 상황에서 선생님 역할과 학생 역할은 인터페이스이고 각각의 역할에 배정된 실제 인물들은 객체 이며 역할의 구현체라고도 한다. 그리고 선생님이 가르치지 않으면 수업을 들을 수도 없으므로 이 객체들은 서로 협력한다.
아.. 김영한님의 스프링 수업에서는 로미오와 줄리엣 공연을 로미오 _역할_과 줄리엣 *역할
, 각각에 해당하는 실제 배우들을 객체, 연기를 해야하는 _책임_으로 예시를 드셨다. 애초에 역할이라는 단어가 사용되는 예시이다보니 꽤 직관적이어서 개발할 때 이 예시를 생각하면서 하면 좋을 듯 하다 👍.

객체의 자율성

객체는 자율성은 내부와 외부를 명확하게 구분하는 것부터 나온다 ( 조영호 저 )

객체는 외부로부터 간섭을 받지 않아야만 자율성을 가질 수 있다. 위의 학교 예시를 다시 들어보면 선생님 역할에 배정된 객체는 학생을 가르치기만 하면 된다. 그 방법으로 수업을 어떻게 준비했고 어떤 방식으로 진행되는 지 상관이 없다. 수업 방식과 준비는 선생님이 알아서 결정하는 것이고 학생이 이래라 저래라 할 수 없다. 학생은 그냥 선생님 역할(인터페이스)에 누가(객체) 오든간에 수업을 들으면 그만이다.

메시지

객체와 객체는 협력할 때 메시지를 주고 받는다. 요청과 응답이다. 이번엔 다시 카페를 예로 들겠다. 카페에서 고객이 캐셔에게 커피를 달라고 주문(요청)한다. 캐셔는 바리스타에게 주문에 맞는 커피를 만들어달라고 요청한다. 바리스타는 캐셔의 요청에 대한 응답으로 커피를 만들어준다. 캐셔 역시 고객의 주문에 대한 응답으로 커피를 내어준다.

1
2
    고객 --주문(요청)--> 캐셔 --커피만들어줘(요청)--> 바리스타
    <--커피 내어줌(응답)--        <--만들어줌(응답)--

이렇게 총 4개의 메시지가 객체간에 발생했다. 이 때 메시지를 보내는 측을 송신자(sender), 메시지를 받는 측을 (수신자)라고한다.
객체간의 협력은 다양한 의사소통 방법을 가진 사람과는 다르게 객체간의 메시지로만 이루어진다.

SOLID 객체 지향의 좋은 설계 원칙

로버트 마틴이라는 분이 이런 원칙을 발표(?) 했다.

1. SRP ( Single Responsibility Principle ) - 단일 책임 원칙

  • 한 클래스는 하나의 책임만 가져야 한다.
  • 선생님은 학생을 가르치는 책임만 있으면 되지 학생 역할에 박보검을 지정할 수는 없다.

2. OCP ( Open/Closed Principle ) - 개방/폐쇄 원칙

  • “소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.”
  • 이건 좀 어려운데 다른 기능 등의 확장되거나 추가될 때 객체(코드) 그 자체는 변하면 안된다.

3. LSP ( Liskov Substitution Principle ) - 리스코프 치환 원칙

  • “프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.”
  • 카페의 바리스타가 바꼈다고 커피를 만들지 않고 파스타를 만들면 안된다.

4. ISP ( Interface Segregation Principle ) - 인터페이스 분리 원칙

  • “특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.”
  • 인터페이스는 최대한 분리해서 구현하는 것이 좋다.

5. DIP ( Dependency Inversion Principle ) - 의존성 역전 원칙

  • 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙을 따르는 방법 중 하나다.
  • 구체화에 의존하면 OCP역시 치켜지지 않는다. 추상화에 의해 구현된 객체들은 다형성을 가지기 때문에 변하기 쉬운데 그럴 때마다 코드를 변경하는 것은 매우 번거롭고 객체 지향을 어긋나게 하는 것이다.
  • 해결하기 위해 의존성 주입 ( Dependency Injection )이 필요하다.
This post is licensed under CC BY 4.0 by the author.