우당탕탕 우리네 개발생활

[oop] 6장. 객체 지도 본문

tech

[oop] 6장. 객체 지도

미스터카멜레온 2024. 5. 12. 18:45
이 글은 조영호님의 <객체지향의 사실과 오해> 책을 통해 공부한 내용을 정리하기 위해 작성하였습니다. 제 개인적인 각색과 의견이 첨가되어 있어 실제 책의 내용과는 차이가 있을 수 있습니다.

 

여행 중에 다른 마을로 이동해야 하는데 길을 모른다고 가정해 보자. 이 경우 사람들은 다음의 두 가지 방법 중 하나를 이용해 길을 찾는다.

  1. 지나가는 사람에게 마을까지 가는 길을 직접 물어 보기
    1. 기능적이고 해결책 지향적인 접근법이다.
  2. 지도에 표시된 길을 따라 가기
    1. 실세계의 지형을 기반으로 만들어진 추상화된 모델이다.
    2. 구조적이고 문제 지향적인 접근법이다.

지도 은유의 핵심은 기능이 아니라 구조를 기반으로 모델을 구축하는 편이 좀 더 범용적이고 이해하기 쉬우며 변경에 안정적이라는 것이다.

사람들에게 직접 길을 묻는 접근법은 기능에 구조를 종속시키는 방법이며 지도는 구조에 기능을 종속시키는 방법이다.

기능 설계 대 구조 설계

훌륭한 기능이 훌륭한 소프트웨어를 만드는 충분조건이라고 한다면 훌륭한 구조는 훌륭한 소프트웨어를 만들기 위한 필요조건이다. 성공적인 소프트웨어들이 지닌 공통적인 특징은 훌륭한 기능을 제공하는 동시에 사용자가 원하는 새로운 기능을 빠르고 안정적으로 추가할 수 있다는 것이다. 비록 최종 사용자들이 소프트웨어의 내부 구조를 볼 수는 없지만 깔끔하고 단순하며 유지보수하기 쉬운 설계는 사용자의 변하는 요구사항을 반영할 수 있도록 쉽게 확장 가능한 소프트웨어를 창조할 수 있는 기반이 된다.

 

미래에 대비하는 가장 좋은 방법은 변경을 예측하는 것이 아니라 변경을 수용할 수 있는 선택의 여지를 설계에 마련해 놓는 것이다. 훌륭한 설계자는 미래에 구체적으로 어떤 변경이 발생할 것인지를 예측하지 않는다. 단지 언젠가는 변경이 발생할 것이며 아직까지는 그것이 무엇인지 모른다는 사실을 겸허하게 받아들인다. 좋은 설계는 나중에라도 변경할 수 있는 여지를 남겨 놓는 설계다. 설계를 하는 목적은 나중에 설계하는 것을 허용하는 것이며, 설계의 일차적인 목표는 변경에 소요되는 비용을 낮추는 것이다.

두 가지 재료: 기능과 구조

객체지향 개발에 관한 과거의 다양한 경험과 연구로부터 사람들은 기능과 구조를 표현하기 위해 일관되게 적용할 수 있는 두 가지 기법을 발견했다.

  • 구조는 사용자나 이해관계자들이 도메인(domain)에 관해 생각하는 개념과 개념들 간의 관계로 표현한다.
  • 기능은 사용자의 목표를 만족시키기 위해 책임을 수행하는 시스템의 행위로 표현한다

안정적인 재료: 구조

도메인 모델

도메인 모델이란 사용자가 프로그램을 사용하는 대상 영역에 관한 지식을 선택적으로 단순화하고 의식적으로 구조화한 형태다.

멘탈 모델이란 사람들이 자기 자신, 다른 사람, 환경, 자신이 상호작용하는 사물들에 대해 갖는 모형이다.

도널드 노먼(Donald Norman)은 제품을 설계할 때 제품에 관한 모든 것이 사용자들이 제품에 대해 가지고 있는 멘탈 모델과 정확하게 일치해야 한다고 주장한다. 사용자들은 자신의 멘탈 모델과 유사항 방식으로 제품이 반응하고 움직일 것이라고 기대하기 때문에 훌륭한 디자인이란 사용자가 예상하는 방식에 따라 정확하게 반응하는 제품을 만드는 것이다.

도메인의 모습을 담을 수 있는 객체지향

객체지향을 이용하면 도메인에 대한 사용자 모델, 디자인 모델, 시스템 이미지 모두가 유사한 모습을 유지하도록 만드는 것이 가능하다. 객체지향의 이러한 특징을 연결완전성 또는 표현적 차이라고 한다.

표현적 차이

소프트웨어 객체는 현식 객체를 모방한 것이 아니라 은유를 기반으로 재창조한 것이다. 이처럼 소프트웨어 객체와 현실 객체 사이의 의미적 거리를 가리켜 표현적 차이 또는 의미적 차이라고 한다.

소프트웨어 객체는 그 대상이 현실적인지, 현실적이지 않은지에 상관없이 도메인 모델을 통해 표현되는 도메인 객체들을 은유해야 한다.

불안정한 재료: 기능

유스케이스

사용자의 목표를 달성하기 위해 사용자와 시스템 간에 이뤄지는 상호작용의 흐름을 텍스트로 정리한 것을 유스케이스라고 한다.

유스케이스의 가치는 사용자들의 목표를 중심으로 시스템의 기능적인 요구사항들을 이야기 형식으로 묶을 수 있다는 점이다.

유스케이스의 특성

  1. 유스케이스는 사용자와 시스템 간의 상호작용을 보여주는 '텍스트'다.
    1. 중요한 것은 유스케이스 안에 포함돼 있는 상호작용의 흐름이다. 다이어그램에 노력을 쏟지 말라.
  2. 유스케이스는 하나의 시나리오가 아니라 여러 시나리오들의 집합이다.
    1. 시나리오(Scenario)는 유스케이스를 통해 시스템을 사용하는 하나의 특정한 이야기 또는 경로다.
  3. 유스케이스는 단순한 피처(feature) 목록과 다르다.
    1. 앞에서 언급한 것처럼 유스케이스의 강점은 유스케이스가 단순히 기능을 나열하는 것이 아니라 이야기를 통해 연관된 기능들을 함께 묶을 수 있다는 점이다.
  4. 유스케이스는 사용자 인터페이스와 관련된 세부 정보를 포함하지 말아야 한다.
    1. 사용자 인터페이스를 배제한 유스케이스 형식을 본질적인 유스케이스(essential use case)라고 한다.
  5. 유스케이스는 내부 설계와 관련된 정보를 포함하지 않는다.
    1. 유스케이스에서 객체 설계로의 전환은 공학적인 규칙과 원칙을 기반으로 한 변환 작업이 아니라 경험과 상식과 의사소통을 기반으로 한 창조 작업이다.

유스케이스는 설계 기법도, 객체지향 기법도 아니다

유스케이스는 시스템이 외부에 제공해야 하는 행위만 포함하기 때문에 유스케이스로부터 시스템의 내부 구조를 유추할 수 있는 방법은 존재하지 않는다.

유스케이스를 기반으로 객체의 구조를 쉽게 추출할 수 있다는 어설픈 설명에 속지 마라. 유스케이스는 객체의 구조나 책임에 대한 어떤 정보도 제공하지 않는다.

재료 합치기: 기능과 구조의 통합

도메인 모델, 유스케이스, 그리고 책임-주도 설계

도메인 모델은 안정적인 구조를 개념화하기 위해, 유스케이스는 불안정한 기능을 서술하기 위해 가장 일반적으로 사용되는 도구다.

유스케이스는 사용자에게 제공할 기능을 시스템의 책임으로 보게 함으로써 객체 간의 안정적인 구조에 책임을 분배할 수 있는 출발점을 제공한다.

중요한 것은 견고한 객체지향 애플리케이션을 개발하기 위해서는 사용자의 관점에서 시스템의 기능을 명시하고, 사용자와 설계자가 공유하는 안정적인 구조를 기반으로 기능을 책임으로 변환하는 체계적인 절차를 따라야 한다는 것이다.

책임 할당의 기본 원칙은 책임을 수행하는 데 필요한 정보를 가진 객체에게 그 책임을 할당하는 것이다.

기능 변경을 흡수하는 안정적인 구조

도메인 모델을 기반으로 객체 구조를 설계하는 이유는 도메인 모델이 안정적이기 때문이다. 도메인 모델이 안정적인 이유는 도메인 모델을 구성하는 요소가 다음과 같은 특징을 띠기 때문이다.

  1. 도메인 모델을 구성하는 개념은 비즈니스가 없어지거나 완전히 개편되지 않는 한 안정적으로 유지된다. 정기예금 도메인에서 정기예금과 계좌, 이자율, 이자란 개념은 정기예금이란 금융상품이 없어지거나 완전히 개편되지 않는 한 안정적으로 유지되는 개념이다.
  2. 도메인 모델을 구성하는 개념 간의 관계는 비즈니스 규칙을 기반으로 하기 때문에 비즈니스 정책이 크게 변경되지 않는 한 안정적으로 유지된다. 정기예금 도메인에서 이자는 정기예금이 만기가 되거나 중도 해지를 하는 경우에 한해서 단 한 번 지급된다. 따라서 계좌와 이자 간의 0..1 관계는 이와 같은 핵심적인 비즈니스 규칙이 변경되지 않는 한 동일하게 유지될 것이다.

도메인 모델의 이같은 특징은 도메인 모델을 중심으로 객체 구조를 설계하고 유스케이스의 기능을 객체의 책임으로 분배하는 기본적인 객체지향 설계 방식의 유연함을 잘 보여 준다. 비즈니스 정책이나 규칙이 크게 변경되지 않는 한 시스템의 기능이 변경되더라도 객체 간의 관계는 일정하게 유지된다.

 

객체지향의 가장 큰 장점은 도메인을 모델링하기 위한 기법과 도메인을 프로그래밍하기 위해 사용하는 기법이 동일하다는 점이다. 따라서 도메인 모델링에서 사용한 객체와 개념을 프로그래밍 설계에서의 객체와 클래스로 매끄럽게 변환할 수 있다. 앞에서 객체지향의 이 같은 특성을 연결완전성이라고 설명했다.