CheerUp_Cheers

개체 모델링1 본문

인프런/개체지향 프로그래밍 및 설계 (Java)

개체 모델링1

meorimori 2020. 11. 26. 17:07

#클래스 다이어그램

어떤 시스템에 있는 클래스들을 보여주는 다이어그램

 -> 클래스 안의 상태,동작,접근제어자

 -> 클래스 간의 관계

시스템의 정적인 구조를 보여주기 적합.

UML(여러가지 다이어그램)의 일부

 

#UML

시스템의 디자인을 시각화하기 위해 만든 표준

- 구조을 보여주는 UML 7개(클래스..)

- 동작을 보여주는 UML 7개(시퀀스..)

 -> 요즘은 이런 문서화 줄어듬

 -> 자사의 기술을 개발이 많아져서.

 


 

#모델링할 문제

- 화분에 예쁜 꽃

- 일정량의 물이 있으면 평생 삼

- 물을 뿌릴때 사용하는 도구는 분무기

- 하루라도 물 못받으면 사망

- 사망 후에는 뿌려도 안살아남.

 

1단계 분무기

1) 클래스명 : WaterSpray

2) 상태 : 현재 남아 있는 물의양

  - 초기 값 : 0

  - int remainingwaterInMl

3) 생성자

4) getter, setter(이건 좀..)

 

# 물을 추가할때 어떻게 채우나?

정답은 없어

 방법 1) 200ml까지 채워야지? (setter를 활용한 것)

 방법 2) 물을 100ml 추가해야지? [addWater(int)라는 메소드를 추가해야함]

방법 2

 


 

2단계 분무기 동작

# 메소드 이름은 어떻게 할까요??

방법 1) 동작에 초점을 맞출 경우

  ex) pull(), press()

방법 2) 용도에 초점을 맞출 경우

  ex) spray() <- 우리의 선택

 

# void srapy() vs int spray() ?

 1)int spray()

 int spray()가 반환하는 값이 뭘 반환하는지 알기 힘듦.

 사람 마다 이해가 다름( 왜 뿌리고 남은 물을 반환해? vs 당연히 해야지)

 -> 명백한게 좋으니 void가 좋음

 -> 두번쨰를 굳이 쓰고싶다면 메서드 명을 바꾸자 sprayAndReturnRemainWater()

 

 

#개체 모델링에서 흔히 저지르는 실수

실세계의 상태와 동작을 모두 클래스에 넣는 거,..

-> 개발하다보면 코드를 여러번 고침

-> 쓸데없는 유지보수 비용의 증가.

 

- 완벽한 코드는 없다.

 1) 처음부터 완벽한 모델링는 불가능

 2) 점진적으로 접근하자

 3) 코드는 필요한 시점에 추가.

  -> TMI ㄴㄴ

 


3단계 분무기 용량 추가

실제 분무기는 최대 용량이 있다!

-> addWater()로 계속하면 넘치잖아~

 

#분무기에 최대 용량을 추가

두가지 방법이 있음

- 모든 분무기의 용량이 같을 경우

 1) 상수를 추가하여 상수보다 증가한 상태가 클 경우 상수로 유지. (MAX = 200)

  -> 멤버변수가 추가 안됨.

 2) 공장에서 찍어 낼때 생성자로 용량을 설정해주기.

  -> 멤버변수가 추가됨(capacity)

 

# 이미 반쯤 차있는 200ml 분무 통에 물을 추가 할떄 어떻게 생각?

생각 1) 100ml 추가하자

생각 2) 가득채우자 <- 여기선 자연스럽데;;

 

# '가득채우자' 동작

capacity라는 멤버변수가 있으니 구현 가능.

fillup()이라는 메소드를 추가하자!


4단계 수도꼭지

분무기에 물넣는게 뭐 그냥 넣는게 말이 되지않지않냐?

-> 수도꼭지 만들어달라

 

1) 생각 1

 수도꼭지(Faucet) 멤버변수랑, 채워라 메소드 있으면 되는거 아니야?

 어차피 WaterSpray의 addWater()를 호출해야함.

 -> 이게 필요한게 맞냐?

 

#정말 Faucet이라는 클래스가 필요한가?

모든과정을 다 구현하지 않을거면 필요한거만 넣자..

 


5단계 화분

클래스 이름은 FlowerPot

Alive의 Setter는 없다.

-> 한번 죽은 꽃 어떻게 살려~

 

#화분의 멤버 변수2: 많이 먹엇니

minDailyWaterInMl : 매일 필요한 최소 물의 양

꽃 마다 다른 양이 필요하니 생성자로 초기화.

getter는 상관없음, setter는 추가 x.

 

- 위의 클래스 문제점

분무를 나눠서하면 바로 죽어버림;;

 ex) 하루에 10ml필요한데 5ml 한번 뿌리는 순간 false

 

#하루가 지났을때 판정을 하자.

새로운 함수를 추가.

 


6단계 : 00적 상호작용

5단계까지는 문제가 있어!

WaterSpray와 FlowerPot간에 상호작용이 없네?

 -> 구조체 사고방식에서 벗어난게 아님

 

- why?

호출자가 직접.. 복잡해

호출자가 이런 일을 직접 해줌.

1)분무기에서 물발사

2) 몇 ml 분사되었는지 확인

3) 그 뒤에 화분에 물을 추가

 -> 데이터 저장소로 쓴거 뿐임

 -> 의존관계 조차 없음.

 

#방법 1: '분무기를 화분에 대고 뿌리자'

-> 뿌려주기만하고, 신경안쓰면됨(메소드 어찌됫든 상관없이 뿌려)

-> 호출자 코드가 간단

-> 캡슐화가 잘됨

 

#방법 2: '분무기를 줄테니 알아서 뿌려'

인자를 WatterSpray로 받음.

화분이 어떻게 뿌릴줄 아는거야..

 

#어떤 방법이 좋을까?

2번이 장점이 많다네요.

FlowerPot.addWriter(int)를 제거가능.

 -> 나름 복잡한 계싼 로직도 클래스안에 숨겨버려~

분무기만 화분에 물을 줄수있따!(제약)

 -> 클래스가 상호작용할수 있는 대상도 제한적으로 함!

 


7단계 : 부품으로 분리해보기

#6단계는 유연성이 떨어짐.

화분에 물을 줄때 컵을 쓰고싶다면..?

 -> 추상클래스를 쓰면되요 ^^(나중에)

 

- 재활용할 수 있는 부분이 없을까?

 재활용성은 유연성.

 

#분쿠기를 두 부품으로 분리해보면

- 머리는 손잡이와 호스

- 몸통

 

#간단히 상태에 따라 분리한 버전

 


8단계 : 다시 사용성 높이기

#미리 규격을 정해두자!

두 열거형을 인자로 받자.

재사용성 해결이 됬고, 규격에 맞추게 함.

 

#몸통가서 호출하고 머리가서 호출하고 불편하잖아?

스프레이안에도 메소드를 두고, 그 메소드들이 호출하게 하자.

스프레이에도 Spray()만들고 머리의 spray()호출
간편해진 코드 왼쪽(기존), 오른쪽(새로움)