[Ch.1] 객체, 설계

신은지·2022년 11월 14일
2


오브젝트 : 코드로 이해하는 객체지향 설계 (조영호 저) 를 읽고 정리합니다.


객체와 설계

소프트웨어 설계와 유지보수에 중점을 두기 위해서, 이론이 아닌 실무(실제 코드)에 집중해야 한다.

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

  1. 실행 중 제대로 동작할 것
  2. 변경을 위해 존재할 것 (변경 용이성)
  3. 코드를 읽는 사람과 의사소통할 수 있을 것 (이해 용이)

단순히 동작하는 것에 만족하면 안되는 이유

프로그램은 오늘 기능을 완성하는 동시에, 내일 쉽게 변경되어야 한다.

왜 변경이 쉬워야할까?

  • 요구사항이 항상 변경되기 때문
    • 유저의 의견으로, 기획자의 요청으로, 리소스의 한계로... 소프트웨어는 타의적으로든 자의적으로든 언제든지 변경될 수 있다.
  • 코드 변경과 버그 변경 가능성은 떼어놓을 수 없다
    • 요구사항의 변경은 코드의 변경을, 코드의 변경은 버그 발생 가능성을 높인다.
    • 변경이 어려울 수록 기구현된 코드를 많이 고쳐야하고, 당연히 그만큼 기존 모듈 또는 신규 모듈에서 버그가 발생할 가능성이 높아진다.

변경이 쉬운 코드란?

  • 변경이 쉬운 코드 = 변경에 유연하게 대응할 수 있는 코드 = 이해하기 쉬운 코드
    • 이해하기 쉬워야 보고 고치기 쉬우니까!
    • 이해하기 쉬운 코드 = 우리 예상에서 크게 벗어나지 않는 코드
      • 척보고 무슨 기능인지 딱 연상이 되어야 이해하기 쉽지, 가나다라 하다가 갑자기 efg 나오면 갑자기? 싶어진다. 그런 맥락이다.
  • 근데 코드 (객체)들이 하나만 있나?
    • 기능을 구현하기 위해 여러 객체들이 필요하고, 기능을 수정하기 위해 여러 객체들을 관리해야 한다.
  • 결국 이 객체 하나만 보고 이 객체의 역할이 뭔지 알 수 있어야 예상을 벗어나지 않는 이해하기 쉬운 코드인거고, 변경이 쉬운 코드인 것!

어? 이거 어디서 많이 들어본 소리 아니냐?

~ ✨ 우린 이걸 응집도가 높다고 표현하기로 했어요 ✨ ~

  • 응집도 (cohesion) : 객체 내부 로직이 하나의 목표를 바라보고 있는가?
  • 결합도 (coupling) : 객체가 다른 객체와 얼마나 연관성이 있는가?
    • 대학생때.. 교수님이 커플 보면 보기 싫으니까 커플링을 낮춰야 한다고 설명해주신 적이 있다. 너무 충격적인 드립이라 평생 못 잊을 듯

응집도를 높이고 결합도를 낮춰야 하는 이유

  • 응집도가 낮고 결합도가 높으면 객체 역할을 알아내기 어렵다.
    • 객체 역할을 알기 위해 여러 객체를 참조해야하니까!
  • 또, 객체를 변경하는 것도 어려워진다.
    • 한 객체를 변경하기 위해 관련있는 여러 객체들을 전부 변경해야하니까

~ ✨ 우린 이걸 의존성이 낮다고 표현하기로 했어요 ✨ ~

  • 즉, 객체 사이의 의존성을 낮추고, 변경이 용이한 설계를 만드는게 최종 목표!

의존성은 어떻게 낮추죠?

  • 객체 의존성이 높아지는 이유
    • 내가 할 일을 쟤가 하고 있으니까, 내가 뭘 할 때마다 쟤의 협조가 필요해지는 것.
  • Ex. 밥을 먹는데 반찬을 스스로 집을 수 없고 누군가 떠먹여줘야 하는 상황을 생각해보자.
    • 밥을 국에도 말아먹고 싶고, 반찬 올려서 먹고도 싶고, 이것저것 넣고 볶아도 먹고 싶은데 그때마다 남한테 허락을 받아야 한다면?
    • 오늘은 콩밥말고 쌀밥먹고 싶은데 내게는 선택권이 없다면?

아! 객체가 스스로 처리할 수 있게 자율적인 친구로 만들어주면 되겠구나!

  • 뭔가를 수행할 때, 다른 객체와 엮여서 처리하는게 아니라 객체가 스스로 직접 셀프로 움직이게 해주면 된다.
    • 객체 내부의 세부적인 사항을 스스로 수행하게 만들기 위해, 외부에서 접근할 수 없게 강제하자!

~ ✨ 우린 이걸 캡슐화라고 표현하기로 했어요 ✨ ~

  • 개념적, 물리적으로 객체 내부의 세부적인 사항을 감추고 객체 내부로의 접근을 제한하는 행위
  • 외부 객체는 객체의 인터페이스에만 의존하고, 실제 기능의 구현은 해당 객체만 가능하도록 만들자.
    • 즉, 객체를 인터페이스와 구현으로 나누고 인터페이스만을 공개하는게 중요!
      • 결국 객체는 나와 연관있는 작업만 수행하고, 연관 없는 작업은 다른 객체에게 위임하게 된다.
  • 객체를 모두 사람이라고 생각하자. (= 의인화)
    • 객체가 쌀밥이어도, 떡볶이여도, 얘네는 다 살아있고 스스로의 의지로 움직이는 애들이라고 생각하고 책임을 넘기자.

이제 각 객체들이 스스로를 책임지게 되었습니다! 😮

  • 어느 한 대장 객체가 다른 객체들을 모두 책임지는게 아니라, 모든 객체들에게 책임이 적절히 분배되었고, 각 객체들은 자율적으로 스스로의 책임을 수행한다.
  • 데이터와 데이터를 사용하는 프로세스들이 동일한 객체 안에 위치해서 객체 응집도가 높아진 상태!

그럼 이제 객체들이 완전히 독립적인 건가요?

아니용!

트레이드 오프 (trade-off)

  • 어떤 기능을 설계하는 방법은 한 가지 이상일 수 있다.
  • 객체 자율성을 지키기 위해 전체 설계 관점에서 타 객체와의 결합도가 높아질 수도 있다.

왜 이런 일이 발생한거죠?

  • 한 어플리케이션을 만들기 위해 여러 객체들이 서로 협력해야 하고, 이를 위해 객체 사이에 메시지를 주고받게 된다.
    • 이 메시지를 주고 받기 위해 필요한 최소한의 지식이 의존성을 만들게 된다.
      • 아무리 인터페이스에만 접근하게 설계하게 만들어 의존성을 낮춰도, 결국 타 객체의 인터페이스 < 에는 접근하게 되는 것.
  • 좋은 설계의 목적은 의존성을 없애는게 아니라, 의존성을 낮추는 것이다.
    • 최대한 한 번에 하나의 클래스만 변경할 수 있도록, 최대한 데이터와 프로세스가 동일한 모듈 내부에 위치할 수 있도록!

그럼 객체 지향 설계의 최종 목표는 뭔가요?

협력하는 객체 사이의 의존성을 적절하게 관리하는 설계를 구현하자!

  • 불필요한 의존 관계 없이, 객체들이 적절하게 상호작용하고 적당한 수준의 변경을 구현 가능하게 할 때 유연하게 설계되었다고 평가할 수 있을 것이다.
profile
호그와트 장학생

0개의 댓글