LostCatBox

READ-ME Writing

Word count: 879Reading time: 5 min
2022/12/25 Share

read.me 작성법

Created Time: November 23, 2022 1:39 PM
Last Edited Time: November 25, 2022 4:11 PM

Description

프로젝트에 대한 간단한 설명을 기술한다. 어떠한 일을 수행하기 위한 프로젝트인지, 어떠한 서비스를 위한 것인지를 작성하면 된다. 너무 길게 작성하기 보단 간결하고 명료하게 작성하는 것이 좋다. 프로젝트의 가치를 전달하는 것도 좋다.

Environment

실행환경에 대해 작성하면 된다. OS나 컴파일러 혹은 Hardware와 관련된 환경을 작성하면 된다. Multicore 환경에서 돌아가는 프로그램이라면 CPU나 RAM 같은 것들을 작성해도 좋다.

Prerequisite

작성한 코드를 실행하기 전에 설치해야할 pakage나 의존성이 걸리는 문제들을 설명하면 된다.

Files

이 항목은 내가 추가한 것이다. 중요한 코드 파일들 몇 개를 대상으로 해당 파일이 어떠한 역할을 하는 파일인지를 간단히 설명해주면 전반적인 맥락을 파악하기에 좋을 것 같아 추가하였다.

Usage

작성한 코드를 어떻게 실행해야 하는지에 대한 가이드라인이다. Usage Example을 함께 작성하면 좋다.

이 외에도 라이센스, contributing 같은 것들도 있지만 처음부터 readme를 복잡하게 작성하기 보단 프로젝트의 규모가 커지면서 디테일하게 추가하며 다듬는 것이 좋다.

마치! 알고리즘 문제 풀때 주어지는것처럼 스펙 정의하면된다.

  • 내가 작성한 예시
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# READ.md

# 개발 환경

- java 11
- spring 2.7.5
- jpa 2.7.5
- jdbc 2.7.5
- web 2.7.5
- gradle 7.5.1
- h2 2.1.214

# 실행 방법

- 실행 전 build.gradle 파일 내부 dependenies에 대해 설치 필요
- 프로그램 실행
src.main.java….homework.`HomeworkApplication` 실행
- 테스트 코드 실행
src.test.java….homework.service.* 각각의 Test파일 실행

# 프로젝트 구조

## 워크플로우

![스크린샷 2022-11-22 오전 1.40.10.png](homework_workflow.png)

## 간단한 설명

- `OrderController` : 각 Service들을 호출하는역할 및 주문 프로그램의 시작과 끝 책임
- `OrderScanner` : 사용자의 주문을 입력받고, 해당 내용 validation에 대한 책임
- `ProductService` : 주문 프로그램에서 jpa repository를 통한 h2 DB와의 올바른 데이터 반환 책임
- `OrderService` : 주문서 작성에 대한 책임

# 프로젝트 구현

## 목표

SOLID 원칙에 따라 합당한 구조 설계

추후의 주문 프로그램에 개선 및 확장이 일어날 경우 해당 책임과 역할을 가진 코드만 수정 가능하도록 설계 노력 (OOP, SRP)

목적에 맞는 올바른 동작을 확인하는 세부적인 테스트 코드 작성

## 올바른 스펙 정의

### 주문에 대한 입력값 정의

해당 주문 프로그램에서는 클라이언트에게 상품번호, 주문수량 입력 받게된다.

이때 상품번호, 주문수량에 대한 스펙을 명확히 다음과 같이 정의하여, 목적에 맞게 올바른 동작을 확인하는 테스트 코드를 작성하였다.

- 상품 번호 : 6자리의 숫자로 구성
- 주문 수량 : 숫자로 구성

### DTO, Entity에 대한 스펙 정의

- `Order`: 주문 하나마다 객체화, DTO역할 (productId, productCount로 구성)
- `ProductDTO`: `Product Entity`에 대한 DTO역할 (id, name, price, stock로 구성)
- `Product Entity`: 데이터 베이스와의 통신 기준 (id, name, price, stock로 구성)

## 주요 동작 방식

1. `OrderController`가 주문 프로그램의 시작과 끝 사용자 응답 대기
2. 주문 시작시 `productService.checkStock()` 호출하여 현재 DB 제품목록 출력
3. `orderScanner.makeOrders()` 호출
4. `OrderScanner`가 사용자의 주문을 입력받고, 해당 내용 validation(상품 번호, 주문 수량에 대해) 체크 후 Order 객체 생성, 주문 모두를 가진 `orderList` 반환
5. `productService.saveProductList(orderList)` 호출
6. `ProductService` 에서 해당 `orderList` 의 `Order`들에 대해 해당하는 `Product` 찾고, 모든 `Product`에 대해 `update` 성공시(더티체킹) 아무런 반환없음
7. `orderService.makeOrderSheet(orderList)` 호출
8. `OrderService`에서 해당 `orderList` 의 `Order`들에 대해 해당하는 `Product` 찾고, 각 `Product` 의 가격(price)와 해당 `Order`의 수량을 곱한 값을 모두 더해 최종 주문 금액, 지불 금액 출력까지 성공시 아무런 반환없음
9. 1번부터 다시 시작

## 사전 동작

`HomeworkApplication` 클래스의 main 함수 호출 시 다음과 같은 과정 존재

**DatabaseConfig**

- spring 실행후, 초기화 후 `@Order(1)` 첫번째로 `run()` 호출
(`ApplicationRunner` 상속)

**OrderController**

- **DatabaseConfig실행후** `@Order(2)` 이므로 `run()` 호출
(`ApplicationRunner` 상속)

## 주요 함수 스펙 및 동작

개선, 확장 등 변경이 일어났을 시에도 각 함수들이 목적에 맞는 올바른 동작하는지 확인하는 세부적인 테스트 코드 작성완료

### OrderController의 대표적인 함수

각 Service들을 호출하는역할 및 주문 프로그램의 시작과 끝 동작

**run()**

- 성공: o, order, q, quit 입력 시
- 실패: [o, order, q, quit] 외의 입력 시

### OrderScanner의 대표적인 함수

OrderScanner는 사용자의 주문을 입력받고, 해당 내용에서 상품 번호, 주문 수량 값을 validation에 대한 책임을 갖는다.
참고로, 올바른 데이터의 스펙은 다음과 같다.

- 상품 번호 : 000000 ~ 999999 범위 내의 6자리의 숫자
- 주문 수량 : 1 ~ 2147483647 범위 내의 숫자

**isOrderConclude()**

- 성공: 2개의 파라미터 모두 `“ “`, `“ “` 일때
- 실패: 2개의 파라미터 모두 `“ “`, `“ “` 일때 아닐때

**checkValidProductId()**

- 성공: 000000 ~ 999999 범위 내의 숫자로 구성된 String 값
- 실패: null, Blank, 6글자 X, 숫자가 아닌 다른 문자로 구성

**checkValidProductCount()**

- 성공: 1 ~ 2147483647 범위 내의 숫자로 구성된 String 값
- 실패: null, Blank, 숫자가 아닌 문자열 포함된 String ,숫자가 아닌 다른 문자로 구성, 마이너스 숫자, int값 범위 넘어선 숫자, 0

**checkValidOrderList()**

- 성공: 리스트 파라미터가 비어있지 않을 때
- 실패: 리스트 파라미터가 비어있을 때

### ProductService의 대표적인 함수

주문 프로그램에서 jpa repository를 통한 h2 DB와의 올바른 데이터 반환 책임

**findProductById()**

- 성공: `productId` 파라미터에 해당하는 `Product Entity` 존재
- 실패: `productId` 파라미터에 해당하는 `Product Entity` 부재

**findWithIdForUpdate()**

- 성공: `productId` 파라미터에 해당하는 `Product Entity` 존재
- 실패: `productId` 파라미터에 해당하는 `Product Entity` 부재

**saveProductList()**

이중 주문 완료 처리시 싱글 쓰레드 환경과 멀티 쓰레드 환경에 대해 동일한 order는 동일한 결과값을 나타내야한다. SoldOutException의 횟수를 카운트하여 테스트를 검증하였다.

- 성공: 한 트랜잭션으로 `orderList` 파라미터의 모든 `Order` 재고 부족없이 모두 stock update 처리 성공
- 실패: `orderList` 파라미터의 모든 `Order` 중 하나라도 재고부족 시 `SoldOutException` 및 현재 트랜잭션 실패 처리(롤백)

### OrderService의 대표적인 테스트 코드

주문서 작성에 대한 책임

**getTotalPrice()**

- 성공: `orderList` 파라미터의 모든 `Order` 의 가격*주문수량을 취합
- 실패: `orderList` 파라미터의 모든 `Order` 중 가격*주문수량이 OverFlow가 일어남

**checkValidMultiple()**

- 성공: 음수가 아닌 숫자 둘을 곱한 후 OverFlow가 일어나지않는 값
- 실패: params 중 하나 음수값, params 모두 음수값, params 곱한후 OverFlow가 일어나는 값
CATALOG
  1. 1. read.me 작성법