일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- JavaScript
- apollo client
- 프로그래밍
- context api
- VUE
- 디자인패턴
- schema-first
- 개발
- ELECTRON
- 프론트엔드
- 리액트
- Node.js
- code-first
- goorm.io
- 함수형
- VanillaJS
- It
- 코딩
- graphql
- Funtional programming
- react.js
- React
- vue.js
- Front-End
- Programming
- angular
- Ramda.js
- 자바스크립트
- Design Pattern
- ECMAScript6
공부하는 블로그
#7 - 분석: 내가 만든 소프트웨어를 실제 세상으로 (2) 본문
#7 - 분석: 내가 만든 소프트웨어를 실제 세상으로(2)
본 블로깅은 Head first OOAD: 세상을 설계하는 객체지향 방법론 (한빛미디어) 책을 Typescript 문법으로 전환하며 공부하는 글입니다.
글을 읽기 전에, 광고 배너 한번씩만 클릭 부탁드립니다. 블로그 운영에 큰 보탬이 됩니다 :)
코드와 메소드 분석
주 경로
- 주인 강아지가 밖에 나가려고 짖는다.
- 강아지 소리 인식기가 강아지 소리를 "듣는다" -
BarkRecognizer.recognize
,Bark
- 주인 강아지가 짖으면 강아지 소리 인식기가 여는 요청을 강아지 문에 보낸다. -
BarkRecognizer.recognize
,open()
,allowedBarks
- 강아지 문이 열린다. -
DogDoor
,open()
- 주인 강아지가 밖으로 나간다.
- 주인 강아지가 화장실을 이용한다.
- 문이 자동으로 닫힌다 -
DogDoor
,close()
- 주인 강아지가 들여보내달라고 짖는다
- 강아지 소리 인식기가 강아지 소리를 "듣는다" -
BarkRecognizer.recognize
,Bark
- 주인 강아지가 짖으면, 강아지 소리 인식기가 여는 요청을 문에 보낸다. -
BarkRecognizer.recognize
,open()
,allowedBarks
- 강아지 문이 열린다. -
DogDoor
,open()
- 문이 자동으로 닫힌다 -
- 주인 강아지는 안으로 들어온다.
- 문이 자동으로 닫힌다. -
DogDoor
,close()
대체 경로들
2.1. 주인이 강아지가 짖는 것을 듣는다.
3.1. 주인이 리모컨의 버튼을 누른다. - Remote.pressButton()
6.3.1. 주인이 강아지가 짖는 것을 듣는다.
6.4.1. 주인이 리모컨의 버튼을 누른다.- Remote.pressButton()
클래스 다이어그램 구성
클래스 다이어그램은 ERD와 비슷한 것 같다. RDB 구성을 할 때에도 관계도를 그리면서 하는데, 클래스 다이어그램은 말그대로 클래스 간의 관계를 나타내는 것을 말하는 듯 하다.
다이어그램을 나타낼 때 세개의 칸으로 구분짓는데, 맨 위에는 클래스명, 가운데는 속성, 그 아래는 메소드를 표기한다.
클래스간의 관계는 화살표로 나타내는데, 참조, 확장, 상속 등을 표현할 수 있다.
아래 그림에서는 Remote 클래스가 DogDoor 클래스를 향해서 화살표가 그어져 있다. 보통은 연관을 나타내는 속성은 다이어그램에 기입하지 않는다. (Remote에 DogDoor 속성을 써넣지 않았다.)
화살표 옆에 숫자는 연관의 다중도를 말한다. ERD로 말하자면 1:1, 1:N, N:M 등의 관계를 말하는 것이다. 아래 그림에서는 door 속성이 하나의 DogDoor 객체를 저장한다. DogDoor에서 Bark를 향하는 화살표에는 * 이 표시되어 있다. 많이 담을수 있다는 이야기이다.
[그림]
머릿속에 담아놓고 말로 설명하는 것보다는 그림으로 한번에 표현하는 것이 훨씬 쉽다. 나만 알고 코드를 짜는 것은 도움이 되지 않는다. 동료들과 협업할 때도 구조를 잘 작성한 후에 만들면 훨씬 좋다. 왜냐하면 일을 분담 할 수 있기 때문이다. 코드 작성하다가 설계가 잘못된 것을 알고서 되돌리면서 허비하는 시간보다, 다이어그램을 만들며 설계를 한 후에 코드를 작성하는 것이 훨씬 좋다.
어제 나의 경우에도 알림톡 서비스 리팩토링을 하면서 DTO와 메시지 전송 단을 나누어 작업하면서 동료와 업무를 나누어서 작업할 수 있어 좋았다.
물론 클래스 다이어그램만으로는 부족하다. 타입 정보도 부족하고, 메소드를 어떻게 작성해야 하는지도 알 수 없다. 클래스 다이어그램은 전체적인 외형와꾸을 구성한다고 생각하면 될 것이다.
코드 구현
이제 코드 구현을 해보자. 오래 기다렸다.
import { DogDoor } from "./DogDoor";
import { Bark } from "./Bark";
export type BarkRecognizer = InstanceType<typeof BarkRecognizer>;
export const BarkRecognizer = class {
private _door: DogDoor;
constructor(dogDoor: DogDoor) {
this._door = dogDoor;
}
public recognize(bark: Bark): void {
console.log(`BarkRecognizer: Heard a ${bark.sound}`);
this._door.allowedBarks.forEach((allowedBark: Bark) => {
if (allowedBark.equals(bark)) {
this._door.open();
}
});
}
};
import { Bark } from "./Bark";
export type DogDoor = InstanceType<typeof DogDoor>;
export const DogDoor = class {
private _open: boolean;
private _allowedBarks: Bark[];
constructor() {
this._open = false;
this._allowedBarks = [];
}
public open(): void {
console.log("The dog door opens.");
this._open = true;
setTimeout(() => {
this.close();
}, 5000);
}
public close(): void {
console.log("The dog door closes.");
this._open = false;
}
public isOpen(): boolean {
return this._open;
}
get allowedBarks(): Bark[] {
return this._allowedBarks;
}
addAllowedBark(allowedBark: Bark) {
this._allowedBarks.push(allowedBark);
}
}
import { DogDoor } from "./src/DogDoor";
import { Remote } from "./src/Remote";
import { BarkRecognizer } from "./src/BarkRecognizer";
import { Bark } from "./src/Bark";
export class DogDoorSimulator {
public main(): void {
const door: DogDoor = new DogDoor();
door.addAllowedBark(new Bark("rowlf"));
door.addAllowedBark(new Bark("roowlf"));
door.addAllowedBark(new Bark("rawlf"));
door.addAllowedBark(new Bark("roof"));
const recognizer: BarkRecognizer = new BarkRecognizer(door);
const remote: Remote = new Remote(door);
console.log("Fido barks to go outside...");
recognizer.recognize(new Bark("rowlf"));
console.log("\nFido has gone outside...");
setTimeout(() => {
console.log("\nFido's all done...");
console.log("...but he's stuck outside!");
const smallDogBark: Bark = new Bark("yip");
console.log("A small dog starts barking...");
recognizer.recognize(smallDogBark);
setTimeout(() => {
console.log("\nFido starts barking...");
recognizer.recognize(new Bark("roowlf"));
console.log("\nFido's back inside...");
}, 5000)
}, 10000);
}
}
new DogDoorSimulator().main();
동작시켜보면 코드가 매우 잘 도는 것을 알 수 있다. 이렇게해서 소프트웨어 분석에 대해서 알아보았다. 다음 시간에는 좋은 디자인이란 무엇인가에 대해 고민해보도록 하자.
'design patterns' 카테고리의 다른 글
#9 좋은 디자인 = 유연한 소프트웨어 : 변하지 않는 것은 없다 (2) (0) | 2019.04.05 |
---|---|
#8 좋은 디자인 = 유연한 소프트웨어 : 변하지 않는 것은 없다 (0) | 2019.04.01 |
#7 - 분석: 내가 만든 소프트웨어를 실제 세상으로 (0) | 2019.03.28 |
#6 - 요구사항 변경 (0) | 2019.03.26 |
#5 - 요구사항 분석 (0) | 2019.03.23 |