Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6장 객체 지도 #203

Closed
Tracked by #40
fkdl0048 opened this issue Jan 10, 2024 · 0 comments
Closed
Tracked by #40

6장 객체 지도 #203

fkdl0048 opened this issue Jan 10, 2024 · 0 comments

Comments

@fkdl0048
Copy link
Owner

fkdl0048 commented Jan 10, 2024

6장 객체 지도

유일하게 변하지 않는 것은 모든 것이 변한다는 사실뿐이다.
:헤라클레이토스

여행 중 길을 찾을 때 사람에게 직접 물어보는 방법과 지도를 이용해 길을 찾는 방법으로 나눈다면 각각의 방법에 따라 과정과 난이도는 확연하게 차이가 난다.

다른 사람에게 길을 물어보는 것은 '기능적이고 해결책 지향적인 접근법'이다.

길을 가르쳐 주는 사람이 해당 목적지까지의 경로를 단계별로 상세히 설명한다.

이러한 방법은 일반적이지도 않고, 재사용 가능하지도 않다.

이에 비해 지도는 실세계의 지형을 기반으로 만들어진 추상화된 모델이다.

지도를 이용해 길을 찾는 방법은 길을 묻는 방법보다 쉽고 간단하다. (시작점과 목적지를 이음)

지도는 길을 찾는 데 필요한 주변 지형을 추상적으로 표현하고 있기 때문에 실세계의 환경과 지식을 통해 밀접하게 연관지어 이해할 수 있게 해준다.

정리하자면 지도를 이용한 방법은 '구조적이고 문제 지향적인 접근법'이다.

지도는 길을 찾는 데 필요한 구체적인 기능이 아니라 길을 찾을 수 있는 '구조'를 제공한다.

길을 묻는 방법은 해결책 지향적이기 때문에 현재 위치와 목적지의 요구만 만족시킬 수 있는 반면, 지도는 현재뿐 아니라 다양한 목적을 위해 재사용이 가능하다. (더 범용적)

지도를 제작한 사람들도 지도를 이용할 사람들이 구체적으로 어떤 목적으로 지도를 이용할지 모른다.

지도가 범용적인 이유는 지도를 사용하려는 사람들이 원하는 '기능'에 비해 지도에 표시된 '구조'가 더 안정적이기 때문이다.

수명또한 더 길다.

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

사람들의 요구사항은 계속 변하기 때문에 모델이 제공해야 하는 기능 역시 이에 따라 지속적으로 변할 수밖에 없다.

따라서 기능을 중심으로 구조를 종속시키는 접근법은 범용적이지 않고 재사용이 불가능하며 변경에 취약한 모델을 낳게 된다.

이와 달리 안정적인 구조를 중심으로 기능을 종속시키는 접근법은 범용적이고 재사용 가능하며 변경에 유연하게 대처할 수 있는 모델을 만든다.

사람에게 묻는 것은 기능에 구조를 종속시키는 것이며 지도는 구조에 기능을 종속시키는 것이다.

전통적인 개발 방법은 전자에 가깝고, 객체지향 개발 방법은 후자에 가깝다.

객체지향은 자주 변경되는 기능이 아니라 안정적인 구조를 기반으로 시스템을 구조화한다.

자율적인 객체들로 시스템을 분할하는 객체지향이 강력한 이유는 사람들이 실세계의 현상을 인지하고 이해하는 관점을 그대로 소프트웨어에 투영할 수 있기 때문이다.

이번 장은 기능이 아닌 구조를 바탕으로 시스템을 분할하는 객체지향의 또 다른 측면에 관해 설명한다.

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

기능 설계 대 구조 설계

모든 소프트웨어 제품에는 두 가지 측면이 존재한다.

하나는 '기능'측면의 설계이고, 다른 하나는 '구조'측면의 설계이다.

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

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

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

소프트웨어가 사용자에게 가치 있는 이유는 사용자가 필요로 하는 기능을 제공하기 때문이다.

이런 관점에서 소프트웨어를 개발하는 일차적인 이유는 사용자에게 훌륭한 기능을 제공하기 위해서다.

개발 초기에는 사용자의 요구사항(도메인)에 맞게 기능을 개발하는 것이 중요하다.

훌륭한 기능이 훌륭한 소프트웨어를 만드는 충분조건이라고 한다면 훌륭한 구조는 훌륭한 소프트웨어를 만드는 필요조건이다.

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

깔끔하고 단순하며 유지보수하기 쉬운 설계는 사용자의 변하는 요구사항을 반영할 수 있도록 쉽게 확장 가능한 소프트웨어를 창조할 수 있는 기반이 된다.

생각보다 더 깔끔하고 단순한 구조가 중요하다고 요즘은 느낀다. 기술적으로 뛰어난 구조도 있을 수 있지만 프로젝트 규모에 맞는 깔끔하고 단순한 구조..

만약 유지보수가 없었다면, 요구사항의 변동이 없다면 구조는 크게 중요하지 않을 것이다.

하지만 소프트웨어 개발에서 불확실성은 항상 존재하며 이를 해결하기 위해 좋은 구조를 가져가야 함은 모든 개발자가 알고 있을 것이다.

개발자의 삶이 고단하면서 흥미로운 이유는 요구사항이 예측 불가능하게 변경되기 때문이다.

훌륭한 설계자는 사용자가 만족할 수 있는 훌륭한 기능을 제공하는 동시에 예측 불가능한 요구사항 변경에 유연하게 대처할 수 있는 안정적인 구조를 제공하는 능력을 갖춰야 한다.

설계가 어려운 이유는 어제 약속했던 기능을 제공하는 동시에 내일 변경될지도 모르는 요구사항도 수용할 수 있는 코드를 창조해야 하기 때문이다.

요구사항을 만족시킬 수 있는 다양한 설계안들을 저울질하면서 그 결과로 단순하면서도 유연한 설계를 창조하는 것은 공학이라기보다 예술에 가깝다. (기예)

하지만 불확실한 미래의 변경을 예측하고 이를 성급하게 설계에 반영하는 것은 불필요하게 복잡한 설계를 낳을 뿐이다.

우리는 미래를 예측할 수 없다. 단지 대비할 수 있을 뿐이다.

미래에 대비하는 가장 좋은 방법은 변경을 예측하는 것이 아니라 변경을 수용할 수 있는 선택의 여지를 마련해 놓는 것이다.

훌륭한 설계자는 미래에 구체적으로 어떤 변경이 발생할 것인지를 예측하지 않는다.

단지 언젠가는 변경이 발생할 것이며 아직까지는 그것이 무엇인지 모른다는 사실을 겸허하게 받아들인다.

좋은 설계는 나중에라도 변경할 수 있는 여지를 남겨 놓는 설계다.

설계를 하는 목적은 나중에 설계하는 것을 허용하는 것이며, 일차적인 목표는 변경에 소요되는 비용을 낮추는 것이다.

안정적인 구조를 중심으로 설계하는 지도 은유와 반대로 전통적인 기능 분해는 자주 변경되는 기능을 중심으로 설계한 후 구조가 기능에 따르게 한다.

이것이 바로 전통적인 기능 분해 방법이 변경에 취약한 이유다.

객체지향 접근방법은 자주 변경되지 않는 안정적인 객체 구조를 바탕으로 시스템 기능을 객체 간의 책임으로 분배한다.

객체지향은 구조에 집중하고 기능이 객체의 구조를 따르게 만든다.

시스템 기능은 더 작은 책임으로 분할되고 적절한 객체에게 분배되기 때문에 기능이 변경되더라도 객체 간의 구조는 그대로 유지된다.

이것이 객체를 기반으로 책임과 역할을 식별하고 메시지를 기반으로 객체들의 협력 관계를 구축하는 이유다.

안정적인 객체 구조는 변경을 수용할 수 있는 유일한 소프트웨어를 만들 수 있는 기반을 제공한다.

두 가지 재료: 기능과 구조

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

기능은 사용자가 자신의 목표를 달성하기 위해 사용할 수 있는 시스템의 서비스다.

구조는 시스템의 기능을 구현하기 위한 기반으로, 기능 변경을 수용할 수 있도록 안정적이어야 한다.

이 두 재료를 구하기 위해서는 다양한 경험과 연구를 통해 도출된 두 가지 기법을 사용한다.

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

일반적으로 기능을 수집하고 표현하기 위한 기법을 유스케이스 모델링이라고 하고 구조를 수집하고 표현하기 위한 기법을 도메인 모델링이라고 한다.

쉽게 예상할 수 있는 것처럼 두 가지 모델링 활동의 결과물을 각각 유스케이스와 도메인 모델이라고 한다.

안정적인 재료: 구조

도메인 모델

모든 소프트웨어 사용자는 필요성을 충족시키기 위해 존재한다.

무료한 시간을 달래기 위해 게임 소프트웨어를 사용한다.

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

도메인 모델에서 모델이란 대상을 단순화해서 표현한 것으로 모델은 지식을 선택적으로 단순화하고 의식적으로 구조화한 형태다.

모델은 복잡성의 바다에서 길을 잃지 않고 중요한 문제에 집중할 수 있도록 필요한 지식만 재구성한 것이다.

즉, 대상을 추상화하고 단순화한 것이다. (현재 문제에 집중 가능)

모델은 복잡성을 관리하기 위해 사용하는 기본적인 도구다.

도메인과 모델의 정의를 연결하면 도메인 모델을 쉽게 정의할 수 있다.

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

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

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

게임 플레이어들은 게임 도메인을 캐릭터와 몬스터, 그리고 몬스터가 떨구는 아이템 간의 관계로 파악한다.

도메인 모델은 단순히 다어이그램이 아닌 멘탈 모델을 의미한다.

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

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

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

설계자는 디자인 모델을 기반으로 만든 시스템 이미지가 사용자 모델을 정확하게 반영하도록 노력해야 한다.

도메인 모델은 도메인에 대한 사용자 모델, 디자인 모델, 시스템 이미지를 포괄하도록 추상화한 소프트웨어 모델이다.

따라서 도메인 모델은 소프트웨어에 대한 멘탈 모델이다.

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

최종 제품은 사용자의 관점을 반영해야 한다.
:도널드 노먼

이것은 소프트웨어 개발에도 동일하게 적용할 수 있다. 최종 코드는 사용자가 도메인을 바라보는 관점을 반영해야 한다.

이것은 곧 애플리케이션이 도메인 모델을 기반으로 설계되어야 한다는 것을 의미한다.

도메인 모델이란 사용자들이 도메인을 바라보는 관점이며, 설계자가 시스템의 구조를 바라보는 관점인 동시에 소프트웨어 안에 구현된 코드의 모습 그 자체이기 때문이다.

따라서 도메인 모델의 세 가지 측면을 모두 모델링할 수 있는 유사한 모델링 패러다임을 사용할수록 소프트웨어 개발이 쉬워질 것이다.

객체지향은 이런 요구사항을 가장 범용적으로 만족시킬 수 있는 거의 유일한 모델링 패러다임이다.

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

객체지향 패러다임은 사용자의 관점, 설계자의 관점, 코드의 모습을 모두 유사한 형태로 유지할 수 있게 하는 유용한 사고 도구와 프로그래밍 기법을 제공한다.

결과적으로 객체지향을 이용하면 도메인에 대한 사용자 모델, 디자인 모델, 시스템 이미지 모두가 유사한 모습을 유사한 모습을 유지하도록 만드는 것이 가능하다.

객체지향의 이러한 특성을 연결완전성, 또는 표현적 차이라고 한다.

표현력 차이

다시 한 번 강조하지만 소프트웨어 객체는 현실 객체에 대한 추상화가 아니다.

소프트웨어 객체와 현실 객체사이의 관계를 가장 효과적으로 표현할 수 있는 단어는 은유다.

앞 장에서 여러번 나왔지만, 소프트웨어 객체는 현실 객체를 모방한 것이 아니라 은유를 기반으로 재창조한 것이다.

따라서 소프트웨어 객체는 현실 객체가 갖지 못한 특성을 가질 수도 있고 현실 객체가 하지 못하는 행동을 할 수도 있다.

비록 소프트웨어 객체가 현실 객체를 왜곡한다고 하더라도 소프트웨어 객체는 현실 객체의 특성을 토대로 구축된다.

이처럼 소프트웨어 객체와 현실 객체 사이의 의미적 거리를 가리켜 표현적 차이 또는 의미적 차이라고 한다.

핵심은 은유를 통해 현실 객체와 소프트웨어 객체 사이의 차이를 최대한 줄이는 것이다.

안타깝게도 대부분의 소프트웨어 도메인은 현실에 존재하지 않는 가상의 세계를 대상으로 한다.

게임 도메인은 현실에는 존재하지 않는 강력한 마법과 괴물들의 천국이다.

우리가 은유를 통해 투영해야 하는 대상은 바로 사용자가 도메인에 대해 생각하는 개념들이다.

즉, 소프트웨어 객체를 창조하기 위해 우리가 은유해야 하는 대상은 바로 도메인 모델이다.

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

도메인 모델을 기반으로 설계하고 구현하는 것은 사용자가 도메인을 바라보는 관점을 그대로 코드에 반영할 수 있어야 한다.

결과적으로 표현적 차이는 줄어들 것이며, 사용자의 멘탈 모델이 그대로 코드에 녹아 스며들게 될 것이다.

표현적 차이가 중요한 이유는 소프트웨어를 이해하고 수정하기 쉽게 만들어주기 때문이다.

코드의 구조 자체가 도메인의 구조를 반영하기 때문에 도메인을 이해하면 코드를 이해하기가 훨씬 수월해진다.

결국 도메인 모델은 코드 안에 존재하는 미로를 헤쳐나갈 수 있는 지도를 제공한다.

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

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

도메인 모델의 핵심은 사용자가 도메인을 바라보는 관점을 반영하여 소프트웨어를 설계하고 구현하는 것이다.

사용자 관점을 반영해야 하는 이유는 사용자들이 누구보다 도메인의 '본질적인' 측면을 가장 잘 이해하고 있기 때문이다.

본질적이라는 것은 변경이 적고 비교적 그 특성이 오랜 시간 유지된다는 것을 의미한다.

소프트웨어 개발의 가장 큰 적은 변경이며 변경은 항상 발생한다는 사실을 기억하라.

사용자 모델에 포함된 개념과 규칙은 비교적 변경될 확률이 적기 때문에 사용자 모델을 기반으로 설계와 코드를 만들면 변경에 쉽게 대처할 수 있을 가능성이 커진다.

이것은 도메인 모델이 기능을 담을 수 있는 안정적인 구조를 제공할 수 있음을 의미한다.

도메인 모델은 소프트웨어 구조의 기반을 이룬다.

그리고 안정적인 구조를 기반으로 자주 변경되는 기능을 배치함으로써 기능의 변경에 대해 안정적인 소프트웨어를 구현할 수 있다.

결론적으로 안정적인 구조를 제공하는 도메인 모델을 기반으로 소프트웨어의 구조를 설계하면 변경에 유연하게 대응할 수 있는 탄력적인 소프트웨어를 만들 수 있다.

비록 도메인 모댈이 도메인과 관련된 중요한 개념과 관계를 보여준다고 해도 실제로 사용자에게 중요한 것은 도메인 모델이 아니라 소프트웨어의 기능이다.

소프트웨어의 존재 이유는 사용자가 원하는 목표를 달성할 수 있는 다양한 기능을 제공하는 것이다.

따라서 사용자에게 제공할 기능을 기술한 정보가 필요하다.

불안정한 재료: 기능

유스케이스

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

우리는 사용자들이 시스템을 통해 달성하고자 하는 '목표'가 존재하기 때문에 기능을 제공한다.

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

사용자는 자신의 목표를 달성하기 위해 시스템과의 상호작용을 시작한다.

사용자가 작업을 요청하면 시스템은 요청을 처리한 후 사용자에게 원하는 결과를 제공한다.

사용자는 시스템의 응답을 기반으로 또 다른 작업을 요청하고, 시스템은 요청을 다시 처리한 후 사용자에게 응답한다.

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

  • 앨리스 코오번의 유스케이스
    • 유스케이스는 시스템의 이해관계자들 간의 계약을 행위 중심으로 파악한다.
    • 유스케이스는 이해관계자들 중에서 일차 액터라 불리는 행위자의 요청에 대한 시스템의 응답으로서, 다양한 조건하에 있는 시스템의 행위를 서술한다.
    • 일차 액터는 어떤 목표를 달성하기 위해 시스템과의 상호작용을 시작한다.
    • 시스템의 모든 이해관계자들의 요구에 응답하고 이해관계자를 보호해야 한다.
    • 특별한 요청과 관계되는 조건에 따라 서로 다른 일련의 행위 혹은 시나리오가 전개될 수 있다.
    • 유스케이스는 이렇게 서로 다른 시나리오를 묶어 준다.

일차 액터란 시스템의 서비스 중 하나를 요청하는 이해관계자로, 하나의 목표를 가지고 유스케이스를 시작하는 액터를 의미한다.

졸라맨..

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

산발적으로 흩어져 있는 기능에 사용자 목표라는 문맥을 제공함으로써 각 기능이 유기적인 관계를 지닌 체계를 이룰 수 있게 한다.

유스케이스의 특성

첫째, 유스케이스는 사용자와 시스템 간의 상호작용을 보여주는 '텍스트'다.

유스케이스 다이어그램이 아니다.

중요한 것은 유스케이스 안에 포함돼 있는 상호작용의 흐름이다.

다이어그램에 노력을 쏟지 말라. 중요한 것은 유스케이스에 담겨 있는 이야기다.

둘째, 유스케이스는 하나의 시나리오가 아니라 여러 시나리오들의 집합이다. (협력의 모습)

셋째, 유스케이스는 단순한 피처 목록과 다르다.

피처는 시스템이 수행해야 하는 기능의 목록을 단순하게 나열한 것이다.

단순 기능의 목록을 나열하기 때문에 두 피처를 서로 연관이 없는 독립적인 기능으로 보이게끔 만든다는 점이다.

두 피처를 유스케이스로 묶고 사용자와의 흐름 속에서 두 피처를 포함하는 이야기를 제공함으로써 시스템의 기능에 대해 의사소통할 수 있는 문맥을 얻을 수 있다.

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

유스케이스는 자주 변경되는 사용자 인터페이스 요소는 배제하고 사용자 관점에서 시스템의 행위에 초점을 맞춘다.

이처럼 사용자 인터페이스를 배제한 유스케이스 형식을 본질적인 유스케이스라고 한다.

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

유스케이스의 목적은 연관된 시스템의 기능을 이야기 형식으로 모으는 것이지 내부 설계를 설명하는 것이 아니다.

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

유스케이슥 단지 사용자가 바라보는 시스템의 외부 관점만을 표현한다는 점에 주목하라.

유스케이스는 시스템의 내부 구조나 실행 메커니즘에 관한 어떤 정보도 제공하지 않는다.

단지 사용자가 시스템을 통해 무엇을 얻을 수 있고 어떻게 상호작용할 수 있느냐에 관한 정보만 기술된다.

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

사실 유스케이스는 객체지향과도 상관이 없다. (다른 패러다임에도 동일하게 적용)

또한, 어떠한 객체의 구조나 책임에 대한 정보도 제공하지 않는다.

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

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

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

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

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

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

시스템은 사용자와 만나는 경계에서 사용자의 목표를 만족시키기 위해 사용자와의 협력에 참여하는 커다른 객체이다.

사용자에게 시스템이 수행하기로 약속한 기능은 결국 시스템의 책임으로 볼 수 있다.

사용자의 관점에서 시스템은 자신이 전송한 메시지에 응답하는 데 필요한 책임을 수행하는 일종의 객체다.

시스템이라는 객체 안에는 더 작은 규모의 객체가 포함될 수 있다. (구성, 합셩)

이제 시스템이 수행해야 하는 커다른 규모의 책임은 시스템 안에 살아가는 더 작은 크기의 객체들의 협력을 통해 구현될 수 있다.

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

_

시스템에 할당된 커다란 책임은 이제 시스템 안의 작은 규모의 객체들이 수행해야 하는 더 작은 규모의 책임으로 세분화한다.

이때 객체를 선택하기 위해 도메인 모델을 참고한다.

도메인 모델에 포함된 개념을 은유하는 소프트웨어 객체를 선택해야 한다.

이것은 소프트웨어와 코드 사이의 표현적 차이를 줄이는 첫걸음이다.

협력을 완성하는 데 필요한 메시지를 식별하면서 객체들에게 책임을 할당해 나간다.

마지막으로 협력에 참여하는 객체를 구현하기 위해 클래스를 추가하고 속성과 함께 메서드를 구현하면 시스템의 기능이 완성된 것이다.

이제 코드는 불안정한 기능을 수용할 수 있는 안정적인 구조에 기반한다.

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

메세지를 먼저 정의하여 객체의 책임과 역할을 분명히 하고 이후에 메서드와 속성을 구현하는 순서가 아닌가?

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

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

책임-주도 설계 방법은 시스템의 기능을 역할과 책임을 수행하는 객체들의 협력 관계로 바라보게 함으로써 두 가지 기본 재료인 유스케이스와 도메인 모델이 반드시 필요한 것은 아니고 유스케이스와 도메인 모델이 책임-주도 설계에서만 사용되는 것은 아니다.

실세계의 기능을 객체지향적으로 보기 좋은 면은 있지만 반드시 필요하거나 사용해야 하는 것도 아니다.

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

도메인 모델에 명시된 개념들을 스스로 상태와 행위를 관리하는 자율적인 객체로 간주한다는 사실에 주목하라.

실세계에서는 수동적인 존재라고 하더라도 소프트웨어 객체로 구현될 때는 스스로 판단하고 행동하는 자율적인 존재로 변한다.

각 객체는 자신의 책임을 완수하는 데 필요한 정보나 서비스가 필요한 경우 이를 제공할 수 있는 다른 객체에게 책임을 요청한다. (협력 관계)

객체의 이름은 도메인 모델에 포함된 개념으로부터 차용하고, 책임은 도메인 모델에 정의한 개념의 정의에 부합하도록 할당한다.

  • 이자를 계산하는 책임을 가진 객체는 이자율이 될 것이며, 이자는 이자율에 의해 생성될 것이다.
  • 책임 할당의 기본 원칙은 책임을 수행하는 데 필요한 정보를 가진 객체에게 그 책임을 할당하는 것이기 때문이다.
  • 결국 이것은 관련된 상태와 행동을 함께 캡슐화하는 자율적인 객체를 낳는다.

유스케이스에서 출발해 객체들의 협력으로 이어지는 일련의 흐름은 객체 안에 다른 객체를 포함하는 재귀적 함성이라는 객체지향의 기본 개념을 잘 보여준다.

큰 객체는 더 작은 객체로 나눠질수 있고, 크기와 상관없이 모든 객체는 메시지를 전송하거나 수신할 수 있고 메시지에 응답하기 위해 자율적으로 메서드를 선택할 수 있다.

객체에 대한 재귀는 객체지향의 개념을 모든 추상화 수준에서 적용 가능하게 하는 동시에 객체지향 패러다임을 어떤 곳에서도 일관성 있게 적용할 수 있게 한다.

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

도메인 모델이 안정적인 이유는 도메인 모델을 구성하는 요소가 다음과 같은 특징을 띠기 때문이다.

  • 도메인 모델을 구성하는 개념은 비즈니스가 없어지거나 완전히 개편되지 않는 한 안정적으로 유지된다.
  • 도메인 모델을 구성하는 개념 간의 관계는 비즈니스 규칙을 기반으로 하기 때문에 비즈니스 정책이 크게 변경되지 않는 한 안정적으로 유지된다.

도메인 모델의 이같은 특징은 도메인 모델을 중심으로 객체 구조를 설계하고 유스케이스의 기능을 객체의 책임으로 분배하는 기본적인 객치지향 설계 방식의 유연함을 잘 보여준다.

비즈니스 정책이나 규칙이 크게 변경되지 않는 한 시스템의 기능이 변경되더라도 객체 간의 관계는 일정하게 유지된다.

기능적인 요구사항이 변경될 경우 책임과 객체 간의 대응 관계만 수정될 뿐이다.

안정적인 도메인 모델을 기반으로 시스템의 기능을 구현할 경우 시스템의 기능이 변경되더라도 비즈니스의 핵심 정책이나 규칙이 변경되지 않는 한 전체적인 구조가 한 번에 흔들리지 않는다.

이것이 일반적으로 객체지향이 기능의 변경에 대해 좀 더 유연하게 대응할 수 있는 패러다임이라고 일컬어지는 이유다.

객체지향의 가장 큰 장점은 도메인을 모델링하기 위한 기법과 프로그래밍 하기 위해 사용하는 기법이 동일하다는 점이다.

따라서 도메인 모델링에서 사용한 객체와 개념을 프로그래밍 설계에서의 객체와 클래스로 매끄럽게 변환할 수 있다.

이를 연결완전성이라 한다.

이러한 연결완전성은 객체지향에서 역방향도 성립하게 된다. (가역성)

즉, 코드의 변경으로부터 도메인 모델의 변경 사항을 유추할 수 있다.

계속 강조하지만 도메인 모델은 문서나 다이어그램이 아니다.

도메인 모델은 사람들의 머릿속에 들어있는 동유된 멘탈 모델이다.

느낀점

정말 많이 배워가는 챕터라는 생각이 든다.

책에선 설명과 이해를 위해 도메인 모델과 유스케이스를 시각적으로 보여줬지만, 본질은 기능과 구조를 실세계의 은유를 통한 재창조라는 것이다.

각 객체들의 협력을 설계할 때 도메인 모델을 참고하고, 유스케이스를 통해 기능을 책임으로 분배한다.

즉, 설계라는 복잡한 단계를 방법을 통해 단순화하고, 이해하기 쉽게 만들어준다.

논의사항

  • 간단한 예제를 가지고 두 가지 재료로 나눠서 한번 이야기 해보면 좋을 것 같습니다.
    • 작성하신 프로그램에 대해서 간략하게 설명해주시면 좋을 것 같습니다.
@fkdl0048 fkdl0048 self-assigned this Jan 10, 2024
@fkdl0048 fkdl0048 added this to Todo Jan 10, 2024
@fkdl0048 fkdl0048 moved this to Two-Week Plan in Todo Jan 10, 2024
@fkdl0048 fkdl0048 moved this from Two-Week Plan to In Progress in Todo Jan 12, 2024
@github-project-automation github-project-automation bot moved this from In Progress to Done in Todo Jan 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

1 participant