-
Notifications
You must be signed in to change notification settings - Fork 8
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
[코드리뷰용] 중간 점검차 브랜치 올려봅니다 #5
base: main
Are you sure you want to change the base?
Changes from 74 commits
62f62ec
54d5388
fa1e021
d65b0a4
a1ead40
6ca34c6
0e05d2e
1e0abc3
1183107
05abd75
696159d
fb19680
70df824
ba44695
2059d6b
b913481
7bdec4c
17c896d
1eb5090
c499133
22b43be
88eaffb
e88d9d0
c5034ae
9227322
b23ca92
d6759da
5a04201
4a8c368
d5ab889
e75be9b
b1446cf
f2a3c44
37738d9
ea6d0b6
0074748
a87cf19
827fc06
150ba15
8271534
3d0f4ec
e3bbedc
9bd7864
a5d6170
45ef8c7
d75fe5b
4f5953f
0b4bb15
25dd38a
447e15f
f989513
3cb8d29
dc1b6c5
a33676e
f08a892
5cf777f
9386758
8d352fb
27f8b99
abe24f1
8685e02
e5d9f07
d95692e
9d1fec4
54daf24
fbda804
6effba9
2bfa4d2
242c1ec
11ae6ed
950825a
97c1554
b04188d
0c3e4ed
bab1d06
f91e001
e11deaa
4d5c438
bc9a72f
d706211
d2a4fa0
1fd46c7
6780cfa
85da7f1
3d5f98d
dba61ce
c86d800
68c6d35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# 서비스 파악 및 구현 계획 | ||
> **지하철 역과 노선을 관리하는 지하철 노선도 기능을 구현한 코드** | ||
|
||
### 사전등록정보 | ||
- 교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의 숲역, 매봉역 | ||
- 하행 - 상행 | ||
- 2호선: 교대역 - 강남역 - 역삼역 | ||
- 3호선: 교대역 - 남부터미널역 - 양재역 - 매봉역 | ||
- 신분당선: 강남역 - 양재역 - 양재시민의숲역 | ||
|
||
# Controller | ||
- 사용자 입력과 Service 코드 매칭 | ||
- 유효한 입력인지 확인 ```(Exception 1)``` | ||
|
||
# Service | ||
### Managerable | ||
- 공통 기능 추출 후 추상화 | ||
- 역 관련 기능/지하철 노선 등록/노선 구간 추가 기능 service 코드가 확장 | ||
- 등록/삭제/조회/(메인화면으로)돌아가기 | ||
```aidl | ||
public abstract class Managerable{} | ||
``` | ||
> interface 로 초기 기획하다가 추상 클래스로 변경함. | ||
> **되돌아가기**을 공통적으로 갖고 있으며 기능 수행 후 **출력하는 내용**이 거의 비슷하니 확장하는 방향으로 변경. | ||
> 맞는 선택인지 구현하면서 계속 고민해볼 것 | ||
|
||
### StationManagerImpl | ||
> 역 관련 기능 | ||
- 지하철 역 등록 | ||
- 등록 이후 노선에 등록하지 않기 | ||
- 노선에 등록되어 있으면 중복 등록 불가 ```(SubwayConstraintHandler.2)``` | ||
- 지하철 역 삭제 | ||
- 노선에 등록된 역은 삭제할 수 없다. ```(SubwayConstraintHandler.2)``` | ||
- 지하철 역의 목록 조회 | ||
- 지하철 역 가나다순 나열하기 | ||
- 역 이름 앞에 **'[INFO]'** 붙이기 ```(view )``` | ||
- 한줄씩 출력 | ||
|
||
- View 코드에서 출력 포맷 활용하여 구현하고 호출할 때 매개변수로 구문이 다르게 나가도록 | ||
- 출력 포맷 적극 활용할 것 | ||
|
||
### LineManagerImpl | ||
> 지하철 노선 등록 | ||
- 노선 등록 | ||
1. 노선 이름 입력 | ||
2. 상행 종점 이름 입력 | ||
3. 하행 종점 이름 입력 | ||
4. **'[INFO] 지하철 노선이 등록되었습니다.'** ```(view)``` | ||
- 지하철 노선 삭제 | ||
- 지하철 노선 목록 조회 | ||
- **'[INFO] n 호선/신분당선'** 나열 ```(view)``` | ||
|
||
### SectionManagerImpl | ||
> 노선에 구간 추가 | ||
- 구간 등록 | ||
1. 등록한 노선 입력 ```(SubwayConstraintHandler.2 : true-continue, false - retry)``` | ||
2. 등록할 역 이름 입력 | ||
3. 노선에서 차지할 순서 입력 | ||
4. **'[INFO] 지하철 구간이 등록되었습니다.'** ```(view)``` | ||
|
||
### MapServcie | ||
> 지하철 노선에 등록된 역 조회 | ||
- 노선의 상행 종점부터 하행 종점까지 연결된 순으로 역 목록 조회 | ||
|
||
|
||
|
||
# config | ||
> 1. 에러나 제약 사항 체크 | ||
> 2. 상수값 모음 | ||
|
||
위반 시 **[ERROR]** 를 반드시 앞에 붙인다. | ||
|
||
### SubwayException | ||
Controller 에서 주로 사용되는 예외 | ||
1. 제공되는 서비스 외 문자 입력 및 선택 시 발생 | ||
|
||
### SubwayConstraintHandler | ||
Service 에서 주로 사용되는 예외 | ||
1. 지하철 역/노선 이름은 2글자 이상인지 확인 | ||
- 아니면 다시 입력 받도록 | ||
2. 노선에 등록되어있는지 확인(수정 및 업데이트 시) | ||
- 있으면 true 없으면 false | ||
3. 노선에 등록되어있는지 확인(조회 시) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# TODO | ||
|
||
## controller | ||
### Maincontroller | ||
각각의 controller 를 실행하는 객체 | ||
사용자의 입력에 맞게 올바른 controller 배치 | ||
- [ ] 1을 입력하면 StationController와 연결된다. | ||
- [ ] 2을 입력하면 LineController와 연결된다. | ||
- [ ] 3을 입력하면 SectionController와 연결된다. | ||
- [ ] 4를 입력하면 지하철 노선을 출력하는 컨트롤러와 연결된다. | ||
- [ ] Q 를 입력하기 전까지 사용자의 입력을 받아 서비스를 제공한다. | ||
|
||
### LineController | ||
지하철 노선과 관련한 기능을 관장하는 객체 | ||
- [ ] 1을 입력하면 노선을 등록한다. | ||
- [ ] 2를 입력하면 노선을 삭제한다 | ||
- [ ] 3을 입력하면 노선 목록을 조회한다. | ||
- [ ] B 를 입력하면 메인 화면으로 되돌아간다. | ||
|
||
#### - 주의사항 | ||
- [ ] 이미 등록된 이름의 노선은 추가할 수 없다. | ||
- [ ] 노선 이름은 2글자 이상이어야 한다. | ||
- [ ] 등록 시 상행 종점, 하행 종점을 입력받는다. | ||
- [ ] 노선에 등록된 역 이름을 나열할 수 있다. | ||
- [ ] 하나의 역은 여러개의 노선에 추가될 수 있다. | ||
|
||
### SectionController | ||
역과 역 사이 구간을 관리하는 객체 | ||
- [ ] 1을 입력하면 구간을 등록한다. | ||
- [ ] 2를 입력하면 구간을 삭제한다. | ||
- [ ] B 를 입력하면 메인 화면으로 되돌아간다. | ||
|
||
#### - 주의사항 | ||
- [ ] 노선에서 갈래길이 생길 수 없다. | ||
- [ ] 역과 역 사이에 새로운 역이 추가될 수 있다. | ||
- [ ] 노선에 등록된 역을 삭제할 수 있다. | ||
- [ ] 종점을 제거하면 다음 역이 종점이 된다. | ||
- [ ] 노선에 포함된 역이 2개 이하일 때 제거할 수 없다. | ||
|
||
### StationController | ||
지하철 역과 관련한 기능을 관장하는 객체 | ||
- [ ] 1을 입력하면 역을 등록한다. | ||
- [ ] 2를 입력하면 역을 삭제한다 | ||
- [ ] 3을 입력하면 역 목록을 조회한다. | ||
- [ ] B 를 입력하면 메인 화면으로 되돌아간다. | ||
|
||
#### - 주의사항 | ||
- [ ] 이미 등록된 이름의 역은 추가할 수 없다. | ||
- [ ] 역 이름은 2글자 이상이어야 한다. | ||
- [ ] 노선에 등록된 역은 삭제할 수 없다. | ||
|
||
### 지하철 노선에 등록된 역 조회 기능 | ||
- [ ] 상행 종점부터 하행 종점까지 순서대로 나열한다. | ||
|
||
<br/> | ||
<br/> | ||
<br/> | ||
|
||
## Service | ||
### Managerable | ||
각각의 Service 들중 공통적으로 필요한 메서드를 나열 하는 추상클래스 | ||
- [ ] 등록 | ||
- [ ] 삭제 | ||
- [ ] 조회 | ||
- [ ] 되돌아가기 - 메인화면 | ||
|
||
### LineManager | ||
노선 관련한 서비스를 모은 집약체 | ||
- [ ] 노선 등록 | ||
- [ ] 이름으로 노선 객체를 불러올 수 있다. | ||
- [ ] 노선 객체에 상행 종점과 하행 종점을 저장한다. | ||
- [ ] 저장하는 배열의 가장 처음을 상행 종점, 가장 마지막을 하행 종점으로 지정한다. | ||
- [ ] 사용자가 입력한 이름이 노선 목록에 존재하지 않을 경우에만 노선을 생성한다. | ||
- [ ] 사용자가 입력한 이름이 2글자 이상 되지 않는다면 노선을 생성하지 않는다. - 메인화면으로 | ||
- [ ] 노선에 등록된 역은 속한 노선 이름을 저장할 수 있다. | ||
- [ ] 노선 삭제 | ||
- [ ] 노선을 삭제한다고 역이 삭제되지는 않는다. | ||
- [ ] 노선 목록 조회 | ||
|
||
### SectionManager | ||
구간 관련한 서비스를 모은 집약체 | ||
- [ ] 구간 등록 | ||
- [ ] 역을 저장한 1차원 배열에서 올바른 위치에 역을 삽입할 수 있다. | ||
- [ ] 존재하지 않는 역을 생성하여 구간을 만들 수 없다. | ||
- [ ] 구간 삭제 | ||
- [ ] 역을 저장한 1차원 배열에서 해당하는 역을 삭제할 수 있다. | ||
- [ ] 노선에 포함된 역이 2개 이상일 때 삭제할 수 없다. - 메인 화면으로 | ||
- [ ] 종점을 제거하면 다음 역이 종점이 된다. | ||
- [ ] 되돌아가기 - 메인화면 | ||
|
||
### StationManager | ||
역과 관련한 서비스를 모은 집약체 | ||
- [ ] 역 등록 | ||
- [ ] 2글자 이상일 때 등록이 가능하다. | ||
- [ ] 이미 존재하는 이름으로 등록은 불가능하다. - 메인화면 | ||
- [ ] 구간 등록을 하지 않은 역은 어떤 노선과도 연결되지 않는다. | ||
- [ ] 역 삭제 | ||
- [ ] 노선에 등록되어 있는 역은 삭제할 수 없다. | ||
- [ ] 역 조회 | ||
- [ ] 되돌아가기 - 메인화면 | ||
|
||
<br/> | ||
<br/> | ||
<br/> | ||
|
||
## View | ||
- [ ] 매개변수를 활용하여 코드의 재사용성을 극대화한다. | ||
### Askview | ||
- [ ] \## 00할 00을 입력하세요. | ||
- [ ] \## 원하는 기능을 선택하세요. | ||
|
||
### Responseview | ||
- [ ] \[INFO] 지하철 00이 00되었습니다. | ||
- [ ] \## 00 목록 | ||
- [ ] \[INFO] 00 | ||
- [ ] \## 00 화면 | ||
- [ ] 노선/역/구간 | ||
```aidl | ||
// 노선/역/구간 | ||
1. 00 등록 | ||
2. 00 삭제 | ||
3. 00 조회 | ||
B. 돌아가기 | ||
``` | ||
|
||
```aidl | ||
// main 화면 | ||
1. 역 관리 | ||
2. 노선 관리 | ||
3. 구간 관리 | ||
4. 지하철 노선도 출력 | ||
Q. 종료 | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
package subway; | ||
|
||
import java.util.Scanner; | ||
|
||
import subway.controller.MainController; | ||
public class Application { | ||
public static void main(String[] args) { | ||
final Scanner scanner = new Scanner(System.in); | ||
// TODO: 프로그램 구현 | ||
public static void main(String[] args) throws Exception { | ||
MainController main = new MainController(); | ||
main.headController(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package subway.config.constants.initValues; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public enum Lines { | ||
LINE_2("2호선", Arrays.asList("교대역", "강남역", "역삼역")), | ||
LINE_3("3호선", Arrays.asList("교대역", "남부터미널역", "양재역","매봉역")), | ||
신분당선("신분당선", Arrays.asList("강남역", "양재역", "양재시민의숲역")); | ||
Comment on lines
+7
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요건 노선 사전 등록 정보를 enum으로 빼둔 것일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 처음 구현이 우선일 때는 List 형식으로 데이터를 저장했었습니다! 그러다보니 초기화 부분에 변동 사항이 생기면 조건문을 찾아서 고쳐야 할 것 같았습니다. 새로운 노선이 생기고 역과 노선 관계가 생길 때마다 if 새로운 노선 then ~~ 역를 반복하는 것 처럼요. 그래서 상수 관리할 때 가장 많이 쓰이는게 enum 이니까 이걸 쓰면 되겟다!! 하는 생각으로 시작했습니다! 먼가 지금 생각해보니 해시맵 같은 거로 관리해도 괜찮을 것 같았다는 생각이 드네욯... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 그렇군요! 질문을 드린 것은, �데이터 초기화는 어플리케이션 실행될 때만 한번 동작하고, 이후론 시스템 상에서 재사용될 여지가 없는 값인데 따로 enum으로 만든 분리한 이유가 무엇인지 궁금해서였어요~ enum값 조회 -> 해당 enum에 할당된 리스트를 순회하면서 저장하는 것보다, 데이터를 초기화하는 용도의 클래스를 만들면 좀 더 관리가 편하지 않을까요? 이렇게 하면 데이터 초기화 책임을 분리할 수 있다는 장점도 있어요! 지금은 초기화를 담당하는 객체와, 초기화 데이터를 담당하는 객체가 분리되어 있어 실제 데이터 초기화 과정을 한 눈에 보기 힘드니, 아예 한 곳에 모아두는 거죠. 만약 초기 데이터의 양이 엄청 많아져서 파일 입출력 등으로 대체해야 하는 요구사항이 있다고 가정할게요. 그럼 데이터 초기화 클래스에 파일 읽는 메서드만 새롭게 추가하면 되어요. 이런 식으로, 어떤 새로운 요구사항이 생겼을 때 내가 어디를 건드려야 하는지 << 를 보면서 관련있는 아이들끼리 묶어주면 좀 더 응집도가 올라갈 것 같아요! 또 Arrays.asList를 이용해 만든 리스트는 크기는 고정이지만, 내부 요소를 변경할 순 있다고 알고 있어서 의도하지 않은 값이 세팅되는 이슈도 생길 수 있을 것 같아요. 요건 개인적인 스타일이니까 그냥 이런 의견도 있구나~ 하고 참고만 해주셔요! (파일이나 DB없이 초기 데이터를 직접 넣는 경우가 일반적이지 않기도 하고) |
||
private String name; | ||
private List<String> values; | ||
Lines(String name, List<String> values){ | ||
this.name = name; | ||
this.values=values; | ||
} | ||
|
||
public String getName(){ | ||
return this.name; | ||
} | ||
|
||
public List<String> getValues(){ | ||
return this.values; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package subway.config.constants.initValues; | ||
|
||
public enum StationName { | ||
교대역, 강남역, 역삼역, 남부터미널역, 양재역, 양재시민의숲역, 매봉역; | ||
|
||
private String station; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package subway.config.constants.views; | ||
|
||
public enum Errors { | ||
VALID("잘못된 명령입니다. 입력값을 확인해주세요."), | ||
ADD_STATION("이미 등록된 역 이름입니다."), | ||
ADD_LINE("이미 등록된 노선 이름입니다."), | ||
DEL_STATION("존재하지 않은 역 이름입니다."), | ||
UNEXPECTED("예상치 못한 에러가 발생했습니다."), | ||
DEL_LINE("존재하지 않는 노선 이름입니다."); | ||
|
||
private final String message; | ||
Errors(String message){ | ||
this.message = message; | ||
} | ||
public String getError(){ | ||
return this.message; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package subway.config.constants.views; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
public enum Indexes { | ||
MAIN("메인", Arrays.asList("역 관리", "노선 관리", "구간 관리", "지하철 노선도 출력")), | ||
METHOD("기능", Arrays.asList("등록", "삭제", "조회")); | ||
|
||
private String role; | ||
private List<String> values; | ||
|
||
Indexes(String role, List<String> values) { | ||
this.role = role; | ||
this.values = values; | ||
} | ||
|
||
public String getRole() { | ||
return this.role; | ||
} | ||
|
||
public String getIndex() { | ||
StringBuilder sb = new StringBuilder(); | ||
for (int i = 0; i < values.size(); i++) { | ||
sb.append(i + 1).append(". "); | ||
sb.append(values.get(i)).append("\n"); | ||
} | ||
sb.append("Q. 종료\n"); | ||
return sb.toString(); | ||
} | ||
|
||
public String getIndex(String target) { | ||
int size = values.size(); | ||
if (target.equals("구간")) { | ||
size = 2; | ||
} | ||
StringBuilder sb = new StringBuilder(); | ||
for (int i = 0; i < size; i++) { | ||
sb.append(i + 1).append(". "); | ||
sb.append(target).append(" "); | ||
sb.append(values.get(i)).append("\n"); | ||
} | ||
sb.append("B. 돌아가기\n"); | ||
return sb.toString(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package subway.config.constants.views; | ||
|
||
public enum Methods { | ||
등록("1"), | ||
삭제("2"), | ||
조회("3"), | ||
출력("4"), | ||
종료("Q"), | ||
돌아가기("B"); | ||
private final String command; | ||
Methods(String command){ | ||
this.command = command; | ||
} | ||
|
||
public String getCommand(){ | ||
return command; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package subway.config.constants.views; | ||
|
||
public enum Prefixes { | ||
SHARP("## "), | ||
INFO("[INFO] "), | ||
ERROR("[ERROR] "); | ||
private final String prefix; | ||
Prefixes(String prefix){ | ||
this.prefix=prefix; | ||
} | ||
public String getPrefix(){ | ||
return this.prefix; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package subway.config.constants.views; | ||
|
||
public enum Questions { | ||
FUNC("원하는 기능을 선택하세요.\n"), | ||
NAME("을 입력하세요.\n"), | ||
SEQUENCE("순서를 입력하세요.\n"); | ||
|
||
private final String question; | ||
static final String SHARP = Prefixes.SHARP.getPrefix(); | ||
|
||
Questions(String question) { | ||
this.question = question; | ||
} | ||
|
||
public String Message(){ | ||
StringBuilder sb = new StringBuilder(); | ||
sb.append(SHARP).append(this.question); | ||
return sb.toString(); | ||
} | ||
|
||
public String Message(String target) { | ||
StringBuilder sb= new StringBuilder(); | ||
sb.append(SHARP); | ||
sb.append(target).append(this.question); | ||
return sb.toString(); | ||
} | ||
|
||
public String Message(String work, String target) { | ||
String message = work + "할 " + target + this.question; | ||
return message; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
만약 Exception이 발생한다면 시스템은 어떻게 되나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사실 원래
System.err.println
으로 문구 출력한 후 처음으로 되돌아가도록 하려고 했습니다!근데 알아보다 보니까 이게 성능상으로 문제가 될 수 있다는 내용을 읽어서 더 고민해보고자 일단 이렇게 처리했습니다.
( https://spongeb0b.tistory.com/92 )
혹시
System.err.println
을 사용하는 것에 대해서 어떻게 생각하시는지 여쭤도 될까요?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
옹
System.err.println
라는게 있다는 걸 지금 알았어요ㅋㅋ요 코멘트를 남긴 이유는, Exception이 발생되었을 때 처리해주는 과정이 없는 것 같아서였어요!
throws는 상위 메서드, 그러니까 호출부에서 이 예외를 처리해줄거야~ 라는 키워드인데, main은 저희가 컨트롤할 수 있는 최상위 메서드이니까요!
제가 알기로는 main에서 throws를 하면 JVM이 예외처리를 해주는데, 요 예외 처리가 단순히 콘솔에 출력만 해주고 마는 것으로 알고 있어요. 요 프로그램은 콘솔 프로그램이니, 이 어플리케이션을 사용하는 사용자의 입장에서 생각하면 갑자기 알 수 없는 에러 메세지가 나오는 상황이 되겠죠?
try-catch를 이용해 적절하게 예외 처리 로직을 추가�하는 것은 어떤지 슬쩍 의견 남겨보아요!