본문 바로가기
객체지향

객체지향(6) - 객체 지도

by 왈레 2022. 3. 17.

이번장에서는 객체지향이 구조와 기능이라는 가지 관점을 어ᄄᅠᇂ게 조화시키는에 관해 설명합니다.

구조는 기능에 비해 변화에 안정적입니다.

따라서 객체지향 패러다임은 객체들의 구조안에 기능을 녹임으로써 변화에 안정적인 소프트웨어를 개발할 있게 합니다.

만약 도메인 모델에 관해 들어본 적이 있다면 이번 장에서 도메인 모델과 객체지향 패러다임 사이의 관계를 이해하게 것입니다.

또한 자주 변경되는 기능이 아니라 안정적인 구조를 기반으로 시스템을 분할하는 객체지향적인 접근법은 역할, 책임, 협력을 기반으로 시스템의 기능을 구현하는 책임-주도설계의 본질을 이해하는 데도 도움이 것입니다.

 

기능을 중심으로 구조를 종속시키는 접근법은 범용적이지 않고 재사용이 불가능하며 변경에 취약한 모델을 낳게 된다. 이와 달리 안정적인 구조를 중심으로 기능을 종속시키는 접근법은 범용적이고 재사용 가능하며 변경에 유연하게 대처할 있다. 사람들에게 직접 길을 묻는 접근접은 기능에 구조를 종속시키는 방법이며 지도는 구조에 기능을 종속시키는 방법이다.

 

전통적인 소프트웨어 개발 방법은 변경이 빈번하게 발생하는 기능에 안정적인 구조를 종속시키는 길을 묻는 방법과 유사하다. 반면에 객체지향 개발 방법은 안정적인 구조에 변경이 빈번하게 발생하는 기능을 종속시키는 지도의 방법과 유사하다. 객체지향은 자주 변경되는 기능이 아니라 안정적인 구조를 기반으로 시스템을 구조화한다.

 

자주 변경되는 기능이 아니라 안정적인 구조를 따라 역할, 책임, 협력을 구성하라!

 

기능 설계 VS 구조 설계

기능 측면의 설계는 제품이 사용자를 위해 무엇을 있는지에 초점을 맞춘다.

구조 측면의 설계는 제품의 형태가 어떠해야 하는지에 초점을 맞춘다.

설계의 가장 도전은 기능과 구조라는 두가지 측면을 함께 녹여 조화를 이루도록 만드는 것이다.

 

소프트웨어 개발 초기단계에서는 사용자가 무엇을 원하는지, 그리고 사용자가 원하는 것을 만족시키기 위해 시스템이 어떤 기능을 제공해야 하는지에 초점을 맞춰야 한다. 훌륭한 기능이 훌륭한 소프트웨어를 만드는 충분조건이라고 한다면 훌륭한 구조는 훌륭한 소프트웨어를 만들기 위한 필요조건이다.

 

성공적인 소프트웨어들이 지닌 공통적인 특징은 훌륭한 기능을 제공하는 동시에 사용자가 원하는 새로운 기능을 빠르고 안정적으로 추가할 있다는 것이다.

 

미래에 대비하는 가장 좋은 방법은 변경을 예측하는 것이 아니라(불가능) 변경을 수용할 있는 선택의 여지를 설계에 마련해 놓는 것이다. 훌륭한 설계자는 미래에 구체적으로 어떤 변경이 발생할 것인지를 예측하지 않는다.

 

가지 재료: 기능과 구조

객체지향 세계를 구축하기 위해서는 사용자에게 제공할 "기능" 기능을 담을 안정적인 "구조"라는 재료가 준비돼 있어야 한다.

 

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

 

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

 

일반적으로 기능을 수집하고 표현하기 위한 기법을 유스케이스 모델링이라고 하고 구조를 수집하고 표현하기 위한 기법을 도메인 모델링이라고 한다. 그리고 가지 모델링 활동의 결과물을 각각 유스케이스 도메인 모델이라고 한다.

 

안정적인 재료: 구조

도메인 모델

사용자가 프로그램을 사용하는 대상 분야를 도메인이라고 한다.

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

도메인 모델은 소프트웨어가 목적하는 영역 내의 개념과 개념 간의 관계, 다양한 규칙이나 제약 등을 주의 깊게 추상화한 것이다.

도메인 모델은 소프트웨어 개발과 관련된 이해관계자들이 도메인에 대해 생각하는 관점이다.

ex)

  1. 은행 업무에 종사하는 사람들은 은행 도메인을 고객과 계좌 사이의 돈의 흐름으로 이해한다.
  2. 중고 자동차 판매상은 구매되는 자동차와 판매되는 자동차의 교환으로 자동차 도메인을 바라본다.
  3. 게임 플레이어들은 게임 도메인을 캐릭터와 몬스터, 그리고 몬스터가 떨구는 아이템 간의 관계로 파악한다.
  4. 프로그래밍에 종사하는 사람들은 프로그래밍 도메인을 입력과 출력의 함수들로 파악한다. 소프트웨어의 도메인이 무엇이건 상관없이 그곳에는 항상 도메인에 관련된 사람들이 도메인을 바라보는 모델이 존재한다.

 

도메인 모델은 이해관계자들이 바라보는 멘탈 모델이다.

도메인 모델이란 사용자들이 도메인을 바라보는 관점이다.

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

사람들은 세상에 존재하는 현상을 이해하고 현상에 반응하기 위해 자신의 마음 속에 멘탈 모델을 구축한다

소트프웨어 사용자들 역시 도메인에 존재하는 현상을 이해하고 현상에 반응하기 위해 도메인과 관련된 멘탈 모델을 현성한다.

 

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

 

노먼은 멘탈 모델을 사용자 모델, 디자인 모델, 시스템 이미지의 가지로 구분한다.

 

디자인 모델(디자이너) --> 시스템(시스템 이미지) <--사용자 모델(사용자)

 

사용자 모델은 사용자가 제품에 대해 가지고 있는 개념들의 모습이다.

디자인 모델은 설계자가 마음 속에 갖고 있는 시스템에 대한 개념화다.

시스템 이미지는 최종 제품이다.

 

사용자의 모델과 디자인 모델이 동일하다면 이상적이겠지만 사용자와 설계자는 직접적으로 상호작용 없으며 단지 최종 제품인 시스템 자체를 통해서만 의사소통할 있다. 따라서 설계자는 디자인 모델을 기반으로 만든 시스템의 이미지가 사용자 모델을 정확하게 반영하도록 노력해야한다.

 

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

도메인 모델의 가지(디자인 모델, 시스템, 사용자 모델) 측면을 모두 모델링 있는 유사한 모델링 패러다임을 사용할수록 소프트웨어 개발이 쉬워질 것이다. 객체지향은 이런 요구사항을 가장 범용적으로 만족시킬 있는 거의 유일한 모델링이다. 객체지향을 사용하면 사용자들이 이해하고 있는 도메인의 구조와최대한 유사하게 코드를 구조화할 있다.

 

객체지향은 사람들이 만지고 느끼고 있는 실체를 시스템안의 객체로 재창조할 있게 해준다.

동적인 객체가 가진 복잡성을 극복하기 위해 정적인 타입을 이용해 세상을 단순화할 있으며 클래스라는 도구를 이용해 타입을 코드안으로 옮길 있다.

 

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

 

표현적 차이

복습

다시 한번 강조하지만 소프트웨어 객체는 현실이 객체에 대한 추상화과 아니다. 소프트웨어 객체는 현실객체를 은유를 기반으로 재창조한것이다. 따라서 소프트웨어 객체는 현실 객체가 갖지 못한 특성을 가질 수도 있고 현실 객체가 하지못하는 행동을 있다.

 

비록 소프트웨어가 객체가 현실 객체를 왜곡한다고 하더라도 소프트웨어 객체는 현실 객체의 특성을 토대로 구축된다. 이처럼 소프트웨어 객체와 현실 객체사이의 의미적 거리를 가리켜 표현적 차이 또는 의미적 차이라고 한다. 핵심은 은유를 통해 현실 객체와 소프트웨어 객체 사이의 차이를 최대한 줄이는 것이다.

 

안타깝게도 가상의 세계를 창조하는 작업에서 현실 객체를 은유하라는 목소리는 공허한 메아리일 수밖에 없다. 왜냐하면 대부분의 소프트웨어 도메인은 현실에 존재하지 않는 가상의 세계를 대상으로 하기 때문이다. 인터넷은 지금까지 현실 세계에서는 존재하지도, 가능하지도 않았던 새로운 유형의 서비스를 창조해왔다.

 

그렇다면 우리가 은유를 통해 투영해야 하는 대상은 무엇인가? 그것은 바로 사용자가 도메인에 대해 생각하는 개념들이다. 소프트웨어 객체를 창조하기 위해 우리가 은유해야하는 대상은 바로 도메인 모델이다.

 

따라서 소프트웨어 객체는 대상이 현실적인지, 현실적이지 않은지에 상관없이 도메인 모델을 통해 표현되는 도메인 객체들을 은유해야한다. 이것이 도메인 모델이 중요한 이유다. 결과적으로 표현적 차이는 줄어들 것이며, 사용자의 멘탈 모델이 그대로 코드에 녹아 스며들게 것이다.

 

표현적 차이가 중요한 이유는 코드의 구조가 도메인의 구조를 반영하기 때문에 도메인을 이해하면 코드를 이해하기 훨씬 수월해진다. 도메인 속의 개념과 관계가 코드 속에 녹아 있기 때문에 도메인이 알려주는 길을 따라가면 코드 속에서 길을 잃지 않을 있다. 결국 도메인 모델은 코드 안에 존재하는 미로를 헤쳐나갈 있는 지도를 제공한다.

 

불안정한 기능을 담는 안정적인 도메인 모델

도메인 모델을 기반으로 코드를 작성하는 번째 이유는 도메인 모델이 제공하는 구조가 상대적으로 안정적이기 때문이다.

 

도메인 모델의 핵심은 사용자가 도메인을 바라보는 관점을 반영해 소프트웨어를 설계하고 구현하는 것이다. 도메인에 대한 사용자의 관점을 반영해야 하는 이유는 사용자들이 누구보다도 도메인의 "본질적인" 측면을 가장 이해하고 있기 때문이다.

 

본질적이라는 것은 변경이 적고 비교적 특성이 오랜 시간 유지된다는 것을 의미한다. 소프트웨어 개발의 가장 적은 변경이며 변경은 항상 발생한다는 사실을 기억하라. 사용자 모델에 포함된 개념과 규칙은 비교적 변경될 확률이 적기 때문에 사용자 모델을 기반으로 설계와 코드를 만들면 변경에 쉽게 대처할 있을 가능성이 커진다. 이것은 도메인 모델이 기능을 담을 있는 안정적인 구조를 제공할 있음을 의미한다.

 

결론적으로 안정적인 구조를 제공하는 도메인 모델을 기반으로 소프트웨어의 구조를 설계하면 변경에 유연하게 대응할 있는 탄력적인 소프트웨어를 만들 있다. 도메인 모델은 여러분이 기능을 구현할 참조할 있는 궁극적인 지도다.

 

불안정한 재료: 기능

유스케이스

기능적 요구사항이란 시스템이 사용자에게 제공해야 기능의 목록을 정리한 것이다.

 

훌륭한 기능적 요구사항을 얻기 위해서는 목표를 가진 사용자와 사용자의 목표를 만족시키기 위해 일련의 절차를 수행하는 시스템 간의 "상호작용"관점에서 시스템을 바라봐야 한다.

 

사용자는 자신의 목표를 달성하기 위해 시스템과의 상호작용을 한다. 사용자가 시스템에게 작업을 요청하면 시스템은 요청을 처리한 사용자에게 원하는 결과를 제공한다. 사용자는 시스템의 응답을 기반으로 다른 작업을 요청하고, 시스템은 요청을 다시 처리한 사용자에게 응답한다. 사용자와 시스템 사이의 상호작용은 사용자의 목표를 만족시키거나 에러 등의 이유로 상호작용을 이상 진행할 없을 때까지 계속된다.

 

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

 

일차 액터(Primary actor) 시스템의 서비스 하나를 요청하는 이해 관계자로, 하나의 목표를 가지고 유스케이스를 시작하는 액터를 의미한다. 일반적으로 시스템과 연동하는 외부 시스템 역시 일차 액터 범주에 포함시킨다.

 

유스케이스의 가치 사용자들의 목표를 중심으로 시스템의 기능적인 요구사항들을 이야기 형식으로 묶을 있다는 점이다. 산발적으로 흩어져 있는 기능에 사용자 목표라는 문맥을 제공함으로써 기능이 유기적인관계를 지닌 체계를 이룰 있게 한다. 이것은 요구사항을 기억하고 관리하는 필요한 다양한 정식적 과부하를 줄인다.

 

사용자 목표가 유스케이스의 핵심이다. 유스케이스는 공통의 사용자 목표를 통해 강하게 연관된 시나리오의 집합이다.

 

정기예금 이자 계산 유스케이스 with 앨리스터 코오번의 템플릿기반

( 유스케이스는 중도 해지 지급받을 있는 이자액을 알고자 하는 사용자의 목표를 충족시키기 위한 연관된 시나리오의 집합을 표현해야 한다.)

 

유스케이스명 : 중도 해지 이자액을 계산한다.

 

일차 액터 : 예금주

 

주요 성공 시나리오 :

  1. 예금주가 정기예금 계좌를 선택한다.
  2. 시스템은 정기예금 계좌 정보를 보여준다.
  3. 예금주가 금일 기준으로 해지할 경우 지급받을 있는 이자 계산을 요청한다.
  4. 시스템은 중도 해지 지급받을 있는 이자를 계산한 결과를 사용자에게 제공한다.

 

확장 :

3a. 사용자는 해지 일자를 다른 일자로 입력할 있다.

 

유스케이스의 특성

  • 첫째, 유스케이스의 사용자와 시스템 간의 상호작용을 보여주는 "텍스트". 유스케이스는 다이어그램이 아니다. 중요한 것은 유스케이스 안에 포함돼 있는 상호작용의 흐름이다. 유스케이스의 핵심은 사용자와 시스템 간의 상호작용을 일련의 이야기 흐름으로 표현하는 것이다.

 

  • 둘째, 유스케이스는 하나의 시나리오가 아니라 여러 시나리오들의 집합이다. 시나리오를 유스케이스 인스턴스라고도 한다.

 

  • 셋째, 유스케이스는 단순한 피처(feature) 목록과 다르다. 피처는 시스템이 수행해야 하는 기능의 목록을 단순하게 나열한 것이다. 피처의 단점은 위의 예제 피처를(중도해지시 이자, 만기시 이자) 서로 연관이 없는 독립적인 기능으로 보이게끔 만든다는 점이다. 피처를 유스케이스로 묶고 사용자와의 상호작용 흐름 속에서 피처를 포함하는 이야기를 제공함으로써 시스템의 기능에 대해 의사소통할 있는 문맥을 얻을 있다. 유스케이스의 강점은 유스케이스가 단순히 기능을 나열하는 것이 아니라 이야기를 통해 연관된 기능들을 함께 묶을 있다는 점이다.

 

  • 넷째, 유스케이스는 사용자 인터페이스와 관련된 세부 정보를 포함하지 말아야 한다.

유스케이스는 자주 변경되는 사용자 인터페이스 요소는 배제하고 사용자 관점에서 시스템의 행위에 초점을 맞춘다. 이처럼 사용자 인터페이스를 배제한 유스케이스 형식을 본질적인 유스케이스라고 한다.

 

  • 다섯째, 유스케이스는 내부 설계와 관련된 정보를 포함하지 않는다.

 

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

 

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

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

불안정한 기능을 안정적인 구조 안에 담음으로써 변경에 대한 파급효과를 최소하하는 것은 훌륭한 객체지향 설계자가 갖춰야 기본적인 설계 능력이다.

 

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

 

변경에 유연한 소프트웨어를 만들기 위해서는 유스케이스에 정리된 시스템의 기능을 도메인 모델을 기반으로 객체들의 책임으로 분배해야 한다.

 

객체지향 패러다임은 모든 것이 객체라는 사상에서 출발한다. 따라서 유스케이스에 명시된 기능을 구현하는 프로그래머는 시스템을 사용자로부터 전송된 메시지를 수행하기 위해 책임을 수행하는 거대한 자율적인 객체로 본다.

 

앞에서 살펴본 책임-주도 설계는 지점부터 적용된다. 지금까지는 시스템이 사용자에게 제공할 기능이 있다는 가정하에 객체들 간의 협력을 설계했지만 사실 협력의 출발을 장식하는 번째는 시스템의 기능을 시스템의 책임으로 바꾼 얻어진것이다.

 

시스템의 할당된 커다란 책임은 이제 시스템 안의 작은 규모의 객체들이 수행하는 작은 규모의 책임으로 세분화된다. 그렇다면 어ᄄᅠᆫ 객체를 선택할 것인가? 시점에 도메인 모델이 무대에 등장한다.  우리는 도메인 모델에 포함된 개념을 은유하는 소프트웨어 객체를 선택해야 한다. 이것은 소프트웨어와 코드 사이의 표현적 차이를 줄이는 첫걸음이다.

 

협력을 완성하는 필요한 메시지를 식별하면서 객체들에게 책임을 할당해 나간다. 마지막으로 협력에 참여하는 객체를 구현하기 위해 클래스를 추가하고 속성과 함께 메서드를 구현하면 시스템의 기능이 완성된 것이다.

 

객체지향 설계 간단요약

요구사항들을 식별하고 도메인 모델을 생성한 , 소프트웨어 클래스에서 메서드를 추가하고, 요구사항을 충족시키기 위해 객체들 간의 메시지를 전송하라.

 

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

 

도메인 모델은 기능을 수용하기 위해 은유할 있는 안정적인 구조를 제공한다.

 

책임-주도 설계는 유스케이스로부터 번째 메시지와 사용자가 달성하려는 목표를, 도메인 모델로부터 기능을 수용할 있는 안정적인 구조를 제공받아 실제로 동작하는 객체들의 협력 공동체를 창조한다.

 

책임-주도 설계 방법은 시스템의 기능을 역할과 책임을 수행하는 객체들의 협력 관계로 바라보게 함으로써 가지 기본 재료인 유스케이스와 도메인 모델을 통합한다. 물론 책임-주도 설계를 위해 유스케이스와 도메인 모델이 반드시 필요한 것은 아니고 유스케이스와 도메인 모델이 책임-주도 설계에만 사용되는 것도 아니다. 여기서 중요한 것은 견고한 객체지향 애플리케이션을 개발하기 위해서는 사용자의 관점에서 시스템의 기능을 명시하고, 사용자와 설계자가 공유하는 안정적인 구조를 기반으로 기능을 책임으로 변환하는 체계적인 절차를 따라야 한다는 것이다.

 

이자 계산의 기능의 변경(기존 단리 이자 + 복리이자 추가 feat.Strategy 패턴)

기능이 추가되거나 변경되어도 대부분 핵심적인 클래스 구조가 그대로 유지되는 이유는 도메인을 구성하는 기본적인 개념과 관계를 포함하는 도메인 모델을 기반으로 시스템의 기능을 대응시켰기 때문이다.

안정적인 도메인 모델을 기반으로 시스템의 기능을 구현할 경우 시스템의 기능이 변경되더라도 비즈니스의 핵심 정책이나 규칙이 변경되지 않는 전체적인 구조가 한번에 흔들리지 않는다. 이것이 일반적으로 객체지향이 기능의 변경에 대해 유연하게 대응할 있는 패러다임이라고 일컬어지는 이유다.

 

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

 

객체지향이 강력한 이유는 연결완전성의 역방향 역시 성립한다는 것이다. , 코드의 변경으로부터 도메인 모델의 변경 사항을 유추할 있다. 이것은 객체지향 이전의 대부분 개발 방법이 대응하지 못하고 쉽게 무너졌던 영역이다. 객체지향에서는 도메인 모델과 코드 모두 동일한 모델링 패러다임을 공유하기 때문에 코드의 수정이 모델의 수정이 된다. 이처럼 모델에서 코드로의 매끄러운 흐름을 의미하는 연결완정성 반대로 코드에서 코드에서 모델로의 매끄러운 흐름을 의미하는 것을 가역성이라고 한다.

 

마지막 메시지

안정적인 도메인 모델을 기반으로 시스템의 기능을 구현하라. 도메인 모델과 코드를 밀접하게 연관시키기 위해 노력하라. 그것이 유지보수하기 쉽고 유연한 객체지향 시스템을 만드는 첫걸음이 것이다.

 

※ 출처 - 조영호 : 객체지향의 사실과 오해

댓글