Computer기본지식/객체지향의 사실과 오해

객체지향의 사실과 오해 - Chapter5,Chapter6

HOONY_612 2021. 7. 22. 11:25
반응형

 

 

이번 챕터들이 이 책의 진짜 핵심인 것 같다. 읽으면서 앞에서 배웠던 개념을 총 집합시켜 놓은 것 같은 느낌이 들었다.

그래서 5,6챕터들을 읽기 위해선 앞의 내용들을 정확히 이해해야만 읽을 수 있다.

그럼 한 번 정리해보겠다.

Chapter5. 책임과 메세지

 

책임이란? 요청을 처리하기 위해 객체가 수행하는 행동

자율성의 판단기준은 문맥에 따라 변할 수 있다.

자율적인 객체란? 어떻게(how)가 아니라 무엇(what)을 설명하는 것.

 

*메세지와 메서드

 

1. 메세지

"수신자(모자장수) + 메시지 이름(증언하라) + 인자(언제,어디서)"로 구성

"메세지는 협력하기위한 유일한 의사소통수단"

 

2. 메서드

메시지를 받고 처리를 위해 내부적으로 선택하는 방법.

 

3. 다형성(대체 가능성)

서로 다른 유형의 객체가 동일한 메세지에 대해 서로 다르게 반응하는 것.

메세지 송신자 입장에선 수신부 객체가 서로 다른 방식으로 메세지를 처리해도 동일한 책임을 가진 객체로 봄.

송신자는 오직 메세지만을 중심으로 수신자를 지정한다.

 

클래스는 동적인 객체들의 특성과 행위를 텍스트로 표현하는 추상화 도구.

객체는 속성과 행위를 가진 것. 클래스는 객체를 담는 틀일 뿐.

 

*데이터 주도 설계 : 데이터를 중심으로 설계하는 기법. 이렇게 될 경우 밖으로 데이터가 드러나 자율성 저해.

*책임 주도 설계 : 책임 완수를 위해 협력하는 객체를 이용해 시스템을 설계하는 기법.

*What/Who 사이클 : 어떤 행위를 수행할 것인지를 결정한 후에 누가 그 행위를 수행할 것인지 결정.

*묻지말고 시켜라 : 메세지를 먼저 결정하고 메세지를 수신 할 후보를 선택.

 

* 인터페이스

 

특징

사용법만 알면 내부 구조나 동작 방식을 몰라도 쉽게 대상을 조작하거나 의사전달 가능.

인터페이스 자체가 아닌 내부 구성이나 동작방식만 변경하는 것은 사용자에게 영향을 안 미침.

대상이 변경되더도 동일한 인터페이스를 제공하면 아무 문제없이 상호작용 가능.

 

인터페이스와 구현의 분리

객체관점에서 생각하는 방법

-좀 더 추상적인 인터페이스 : 추상적이면 자율성이 높아짐.

-최소 인터페이스 : 메세지를 따르면 불필요한 인터페이스가 제거된다.

-인터페이스와 구현(implementation)의 차이 : 객체의 내.외부를 분리하라는 것.

 

캡슐화에 대해서는 Chapter6에서 더 자세히 설명되어있다.

 

책임의 자율화에 따른 전체적인 협력의 설계 품질결정 이유

1. 자율적인 책임은 협력을 단순하게 만든다.

2. 자율적인 책임은 모자 장수의 외부와 내부를 명확하게 분리한다.

3. 책임이 자율적일 경우 책임 수행 방법을 변경해도 외부에 영향을 미치지 않는다.

4. 자율적인 책임은 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.

5. 객체가 수행하는 책임들이 자율적일수록 객체의 역할을 이해하기 쉬워진다.

 

 

Chapter6.  객체 지도

 

"유일하게 변하지 않는 것은 모든 것이 변한다는 사실뿐이다"

 

*길 찾기

지나가는 사람에게 물어보기(기능적인 해결책)

지도에 표시된 길을 따라가는 법(구조적인 해결책)

 

--> 지도는 구체적인 기능이 아니라 구조를 제공한다. 지도는 재사용가능하다.(범용적)

 

어떤 사람이 주문을 한다. 클릭 2번 시 물건 구입이 되는 기능을 개발해줘요~

A개발자는 "클릭 2번하다"라는 추상화하여 코딩을 시작하고 

B개발자는 "클릭 2번시 물건 구입하다"하여 추상화하지 않고 코딩을 시작했다.

 

 

 

위의 예시에서는 A개발자는 재활용이 가능한 인터페이스를 가지고 있다. 그러나 기능에 맞춘 B개발자는 재활용을 하지 못하고 구현체 B를 다시 구현해야했다.

 

"지도은유의 핵심은 기능이 아닌 구조로 모델링을 하였을 때 범용적이고 이해가 쉬우며 변경에 안정적"

 

기능 측면 : 제품이 사용자를 위해 무엇을 할 수 있는지에 초점

구조 측면 : 제품의 형태가 어떠해야 하는지에 초점

 

 

"우리는 도메인 모델링을 하고 거기에서 유스케이스 모델링을 한다."

 

유스케이스 모델링 : 기능을 수집하고 표현하기 위한 기법

도메인 모델링 : 구조를 수집하고 표현하기 위한 기법 

 

도메인 모델

도메인은 사용자가 프로그램을 사용하는 대상 분야(은행, 병원, 게임). -->해결하고자하는 분야대상

모델은 대상을 단순화해서 표현한 것.

따라서 도메인 모델은 사용자가 프로그램을 사용하는 대상 영역에 관한 지식을 단순화하고 구조화한 형태.

도메인 모델은 왜 만들까? 도메인에 대한 지식을 공유하고 소통하기 위한 도구이다.

 

예시가 제일 좋다. 도메인 모델은 멘탈 모델(사용자 + 디자인 + 시스템)이다.

멘탈 모델은 사용자, 디자이너, 시스템이 각각 개인적으로 도메인에 대해서 가진 생각이다.

이상적으로 3개 모두 같으면 좋겠지만 현실적으로는 불가능하다. 그래서 가장 안정적인 사용자 멘탈 모델 중심의 도메인 모델을 설계한다.

위의 다이어그램은 계좌라는 정기예금(도메인)에 대한 도메인 모델이다.(정기예금에 필요한 지식을 단순.구조화)

다른 건 관계를 맺고 있는데 이자는 다중성관계를 맺고있다. 즉 해지여부라는 정보에 따라서 다중성을 가진다.

그리고 순서에 집중하지 말고 관계와 내용에 집중하자.

자 도메인 모델의 주요 목표가 무엇이였을까?

바로 도메인에 대한 지식을 단순화하고 구조화한 형태로 설계되어져야한다. 그리고 누구나 알아 볼 수 있어야한다.

그래서 대중성(사용자 중심설계)이 필요하다고 생각한다. 흔한 절차 지향적인 사고에 휩싸이지 말자.

 

그럼 왜 사용자 모델에 초점을 맞추어서 설계를 해야할까?

바로 사용자들이 누구보다도 도메인의 "본질적인" 측면을 이해하고 있기 때문이다.

 

예를 들어 세탁기를 설계하는데 사용자는 오직 "세탁" 이라는 기능에 초점을 두고 있다. 

디자이너, 시스템은 부수적인 것을 설계할 수 있다. 이러한 본질적인 측면을 가지고 설계를 해야 나중에 쉽게 대처할 수 있다.

 

 

불안정한 재료 : 기능

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

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

-> "공통의 사용자 목표를 통해 강하게 연관된 시나리오의 집합"

 

유스케이스 특성

1. 사용자와 시스템 간의 상호작용을 보여주는 "텍스트"

2. 하나의 시나리오가 아니라 여러시나리오 집합(유스케이스 인스턴스)

3. 피처목록을 연관시켜주는 것.(시나리오를 짠다)

4. 사용자 인터페이스와 관련된 세부 정보를 포함하면 안됨.

5. 내부 설계와 관련된 정보를 포함하면 안됨.(캡슐화)

6. 유스케이스는 객체지향과 상관이 없다. 단지 사용자 목표를 문맥으로 정리하는 기법.

"피처로 시나리오(유스케이스 인스턴스)를 만들고 그 시나리오들의 집합이 유스케이스이다."

 

 

기능(유스케이스)과 구조(도메인 모델)의 통합

 

"유스케이스를 설계하고 목표에 대한 시나리오를 만든다. 그리고 도메인 모델에서 적합한 개념을 찾아 조합한다. 마지막으로 도메인 모델의 요소들에게 속성과 메서드를 부여해 어떤 행동을 해야 할 지 할당해준다."

 

도메인 모델의 속성 -> 클래스 인스턴스 변수

협력 안에서의 책임 -> 클래스 메서드

 

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

package why.spring.object.domain;

public interface interestRate {
    public void createInterest(int when, int amount);
}

위와 같이 인터페이스를 사용하여 안의 로직은 감추면서 "나 이자생성 할 수 있어"라는 인터페이스만 다른 객체들에게 내놓고 있다. 그리고 안의 로직은 다음과 같이 구현했다.

<CompoundInterestRate.java>
public class CompoundInterestRate implements interestRate {
    @Override
    public void createInterest(int when, int amount) {
        //로직 생성
    }
}



<SimpleInterestRate.java>
public class SimpleInterestRate implements interestRate {
    @Override
    public void createInterest(int when, int amount) {
        //로직 생성
    }
}

우리는 Account객체에서 메소드를 이용할 때 이자율을 생성하는 것이 필요하다.

그 때 골라서 사용할 수 있다.

public class Account {
    private int accountNumber;//계좌번호
    private int amount;//예금액

    //interestRate interestRate = new CompoundInterestRate();
    //interestRate interestRate = new SimpleInterestRate();
    /**
    이 부분을 원래는 interestRate interestRate;와 같이 선언할 수 있지만 설명을 위해
    위와 같이 선언
    **/

    public Account(int accountNumber, int amount) {
        this.accountNumber = accountNumber;
        this.amount = amount;
    }
    
      public void calculateInterest(int when) {
		//여기서 위에서 고른 이자율을 사용
    }
}

 

이렇게 Chapter5,6을 살펴봤다.

정말 역대급으로 어려운 장이였다. 그러나 도메인 모델과 유스케이스 모델을 설계를 어떻게 해야 할 지 알았고

실질적인 모델링에 쓸 수 있다. 어려운만큼 얻은게 많은 챕터였다.

반응형