DevLog ๐ถ
[์ฐํ ์ฝ 5๊ธฐ] ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ํ๊ณ ๋ณธ๋ฌธ
[์ฐํ ์ฝ 5๊ธฐ] ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ํ๊ณ
dolmeng2 2023. 2. 22. 10:39์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์์ ์ ๋ฒ ์ฃผ์ ๋๋ฌ์ง๋ง... ์๋ก์ด ๋ฏธ์ ์ ์ ์ํ๋๋ผ ์ด์ ์์ผ ํ๊ณ ๋ฅผ ์์ฑํ๋ค... ๐ฅน
์คํ์ด๋ ์งํํ ์ฒซ ํ์ดํ๋ก๊ทธ๋๋ฐ์ด๋ค.
ํ๋์ ๋ ธํธ๋ถ์ผ๋ก ๊ฐ์ด ์ฝ๋ฉํ๋ ๊ฑด ์ฒ์ ํด๋ณด๋ ๊ฒฝํ์ด๋ผ ์๋ฌ๋๋ค.
์ง๊ธ ์์ ๋๋ผ๋ ๊ฑฐ์ง๋ง, ํผ์ ์ฝ๋ฉํ ๋๋ณด๋ค ์๊ฐ์ ๋ ๊ฑธ๋ ค๋ ํ์ด์๊ฒ ๋ถ๋๋ฝ์ง ์์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด์ ๋ ์ข์ ๋ฐฉํฅ์ผ๋ก ์ค๊ณํ๊ธฐ ์ํด์ ์์์ ์ผ๋ก ๋ ธ๋ ฅํ๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค.
ํ๊ณ ๋ฅผ ์ด๋ป๊ฒ ์์ฑํ ๊น ๊ณ ๋ฏผํ๋๋ฐ, ์ฝ๋๋ ๋จ๊ณ๋ณ๋ก branch๊ฐ ๋๋์ด์ ธ ์๊ณ , ๊ธฐ๋ฅ ๋ชฉ๋ก๋ ๋ ์์ธํ๊ฒ ์์ฑ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ฝ๋์ ๋ํ ์ค๋ช ๋ณด๋ค๋ ์ด๋ค ์์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋์ง ์ ๋ ๊ฒ ๋ ์ข์ ๊ฒ ๊ฐ์์ ๊ทธ๋ ๊ฒ ์ ์ด๋ณด๋ ค๊ณ ํ๋ค :D
โ๏ธ ์์ฑํ ์ฝ๋
โ๏ธ 1์ฐจ PR
โ๏ธ 2์ฐจ PR
โ๏ธ ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ
- ์ฃผ์ด์ง ํ์ ๋์ n๋์ ์๋์ฐจ๋ ์ ์ง ๋๋ ๋ฉ์ถ ์ ์๋ค.
- ๊ฐ ์๋์ฐจ์ ์ด๋ฆ์ ๋ถ์ฌํ ์ ์๋ค. ์ ์งํ๋ ์๋์ฐจ๋ฅผ ์ถ๋ ฅํ ๋ ์๋์ฐจ ์ด๋ฆ์ ๊ฐ์ด ์ถ๋ ฅํ๋ค.
- ์๋์ฐจ ์ด๋ฆ์ ์ผํ(,)๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ตฌ๋ถํ๋ฉฐ ์ด๋ฆ์ 5์ ์ดํ๋ง ๊ฐ๋ฅํ๋ค.
- ์ฌ์ฉ์๋ ๋ช ๋ฒ์ ์ด๋์ ํ ๊ฒ์ธ์ง๋ฅผ ์
๋ ฅํ ์ ์์ด์ผ ํ๋ค.
- ์ ์งํ๋ ์กฐ๊ฑด์ 0์์ 9 ์ฌ์ด์์ random ๊ฐ์ ๊ตฌํ ํ random ๊ฐ์ด 4 ์ด์์ผ ๊ฒฝ์ฐ ์ ์งํ๊ณ , 3 ์ดํ์ ๊ฐ์ด๋ฉด ๋ฉ์ถ๋ค.
- ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์์ ์๋ฃํ ํ ๋๊ฐ ์ฐ์นํ๋์ง๋ฅผ ์๋ ค์ค๋ค. ์ฐ์น์๋ ํ ๋ช
์ด์์ผ ์ ์๋ค.
โ๏ธ 1์ฐจ ํ์ด ํ๋ก๊ทธ๋๋ฐ
๋น์์๋ TDD๊ฐ ๊ทธ๋ฅ ํ ์คํธ ์ฝ๋๋ง ์์ฑํ๋ฉด ๋๋ ๊ฑด ์ค ์๊ณ ๊ธฐ๋ฅ ๊ตฌํ๋ถํฐ ๋ค ํ๊ณ ๋์ ํ ์คํธ ์ฝ๋๋ฅผ ๋ค๋ฆ๊ฒ ์์ฑํ์๋ค.
๊ทธ๋์ ์ปค๋ฐ ๋ด์ญ์ ๋ณด๋ฉด ์ด๋ ๋ค. ๋๊ฐ ๋ด๋ ๊ธฐ๋ฅ ๋จผ์ ๊ตฌํํ๊ณ ํ ์คํธ ๊ตฌํํ ์ฌ๋... ๐ฅน
๊ทธ๋๋ ๋น์ ์์ฑํ ์ผ๊ธฐ๋ฅผ ๋ณด๋ฉด ์ต๋ํ ์ด๋ฐ ๋ด์ฉ์ ๊ตฌํํ๋ค.
1. ๋๋ฉ์ธ์์ getter ์ฌ์ฉํ์ง ์๊ธฐ
2. DTO๋ฅผ ํตํ ๋ฐ์ดํฐ ์ ๋ฌ
3. Stream์ ํ์ฉํ์ฌ filter๋ฅผ ํตํด ์กฐ๊ฑด ๊ฒ์ฆ
4. private ๋ฉ์๋ ํ ์คํธ -> ๋ฆฌํ๋์ ์ฌ์ฉํ๊ธฐ (...)
5. ์๋์ฐจ ์ด๋ฆ์ ๋ํ equals, hashcode ์ค๋ฒ๋ผ์ด๋ฉ์ ํตํด ์๋์ฐจ ๊ฐ์ฒด ๊ด๋ฆฌํ๊ธฐ
์ง๊ธ ์์ ์๊ฐํด๋ณด๋ฉด ์ ๋ง ๋ถ๋๋ฝ๋ค. ๋๋ฉ์ธ์์ Getter๋ฅผ ๋ฌด์์ ์ง์ํ๊ณ , DTO ๋ฌด์์ ์ฌ์ฉํ๊ณ , ๋ฌด์๋ณด๋ค ํ ์คํธ ์ฝ๋๋ฅผ ๋ฆฌํ๋๊ฒฌ๊น์ง ์ฌ์ฉํ๋ฉด์ ์ฒ๋ฆฌํ๋ ๊ฑด ๋ญ๋น์ด๊ธฐ ๋๋ฌธ์ด๋ค. (๋น์์๋ ์ด๊ฑฐ ๊ตฌํํ๊ณ ์์ฒญ ๋ฟ๋ฏํ๋ค. ์๋ ๋ถ๋๋ฌ์ด ๊ฐ์ ์ด ์ฑ์ฅํ๋ค๋ ์ฆ๊ฑฐ๋ผ๊ณ ํ๋ค...ใ ใ )
โ๏ธ 1์ฐจ PR
์คํ๊ณผ ๊ฐ์ด ํผ๋๋ฐฑ์ ํฉ์ณ์ ์๋ก ์ฝ๋์ ๋ํ ๋ฌธ์ ์ ์ ์ ๋ฆฌํ๊ธฐ๋ก ํ๋ค.
๐ฌ ๋ทฐ์ ์ถ๋ ฅ์ ๋๋ฉ์ธ์์ ๊ด๋ฆฌํ ๊ฒ
public class Car {
private final String name;
private final StringBuilder drivingMark;
private Car(final String name) {
...
}
public static Car of(final String name) {
return new Car(name);
}
public void move() {
drivingMark.append("-");
}
...
}
๋ง์ฝ ๋ทฐ์ ๋ํ ์ถ๋ ฅ ์กฐ๊ฑด์ด ๋ณ๊ฒฝ๋๋ค๋ฉด ๋๋ฉ์ธ๋ ํจ๊ป ๋ณ๊ฒฝ๋๋ค๋ ๋จ์ ์ด ์๋ค. ๋น๊ต์ ๋ณ๊ฒฝ์ด ์ฆ์ ๋ถ๋ถ์ธ ์ถ๋ ฅ ์กฐ๊ฑด์ ๋ํด์ ์ด๋ ๊ฒ ๋๋ฉ์ธ๊ณผ ์ฐ๊ด์ ์ง์ผ๋ฉด ์ ๋๋ค ๐ฅฒ (๋๋ฉ์ธ๋ ํจ๊ป ๋ณํ๊ฒ ๋๋๊น) ๊ทธ๋์ ์ถํ ๋ฆฌํฉํ ๋ง ๋ ์๋์ฐจ๋ position๋ง ๊ฐ์ง๊ณ ์๋๋ก ๋ง๋ค๊ณ , ์ถ๋ ฅ์ ๋ํ ์์ ์ view์์ ์ฒ๋ฆฌํ๋๋ก ๋ณ๊ฒฝํ์๋ค.
๋ํ, toString()์ ํตํด์ ๋น์์๋ ์๋์ฐจ ์ด๋ฆ๊ณผ ์ฃผํ๊ฑฐ๋ฆฌ๋ฅผ ์ถ๋ ฅํ๋ ค๊ณ ํ์ผ๋ (์ฌ์ค ํ๋ฆฌ์ฝ์ค ๋ ๊ทธ๋ ๊ฒ ํด์๋ ๊ฒ ๋ฒ๋ฆ์ด ๋์๋ค.) ์ด ๋ถ๋ถ๋ ๋ฆฌ๋ทฐ์ด๋์ด toString()์ ๋ชฉ์ ์ฑ์ ๋ํด ์๊ฐํด ๋ณด๋ผ๊ณ ํ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ด๋ ธ๋ค.
toString()์ ์ฌ์ ์ํ๋ ๊ฑด ์ข์ง๋ง, ๋ณดํต ํ๋์ ๋ด์ฉ์ด ๋ค ๋์์ผ ํ๋ฉด์, ๋ก๊น ์ฉ๋๋ก ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ์ฒ๋ผ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ์ฉ๋ (= ๋ทฐ์์ ์ฒ๋ฆฌํ ์ผ)๋ก ์ฌ์ฉํ๋ ๊ฑฐ๋ ๋ง๊ฒ ์ฐ์ด์ง ์์ ๊ฒ์ด์๋ค.
๐ฌ ์ญํ ๊ณผ ์ฑ ์์ ๋ถ๋ฆฌ
public class InputUtil {
private final InputView inputView = new InputView();
public <T> T getUserInput(Supplier<T> inputReader) {
try {
return inputReader.get();
} catch (IllegalArgumentException | DuplicateException | ConsoleException e) {
OutputView.printMessage(e.getMessage());
return getUserInput(inputReader);
}
}
public Cars getCarNames() {
OutputView.printMessage(GET_CAR_NAMES_MESSAGE.getValue());
String carNames = inputView.getUserInput();
return Cars.of(carNames);
}
...
}
1์ฐจ ๋๋ InputUtil์ ๋ณ๋๋ก ๋์ด์ ์ฌ์ฉ์์๊ฒ ์ฌ์ ๋ ฅ์ ๋ฐ๋๋ก ํ๋๋ฐ, (์ฌ์ค ์ ํธ ํด๋์ค๋ ์ด๋ ๊ฒ ์ฌ์ฉํ๋ ๊ฒ ์๋๋ค. ๋ณดํต ์ ํธ ํด๋์ค๋ static ๋ฉ์๋๋ ํ๋๋ง ๊ด๋ฆฌํ๋ ํด๋์ค์ธ๋ฐ ๋น์์๋ ์ ๋ชจ๋ฅด๊ณ ์ผ๋ค๐ฅน ) getCarNames๋ฅผ ๋ณด๋ฉด, ๋ทฐ์์ ๋๋ฉ์ธ์ ์์ฑํ๋ ์ญํ ๊น์ง ํ๊ณ ์๋ ๊ฒ์ด์๋ค!
์ฐ์ InputUtil์ ๋ง๋ค์๋ ์ด์ ๋ถํฐ ์๊ฐํ๋ค. ๋๋ InputView๋ฅผ ์ํ ์ง์ ์ ์ผ๋ก InputUtil์ ๋์์๋๋ฐ, ์ด๋ InputView์ OutputView๋ฅผ ์ด๊ณณ ํ๋์์ ์ฐธ์กฐํ๋๋ก ํ๊ณ ์ถ์ด์์๋ค.
๊ทผ๋ฐ ๊ธ๋ก ์ฐ๋๊น ๊ธธ์ด๋ณด์ด์ง๋ง ๊ฒฐ๋ก ์ ๊ทธ๊ฑฐ์๋ค. ์ญํ ๊ณผ ์ฑ ์์ ์ ๋๋ก ๋ถ๋ฆฌํ์ง ๋ชปํ ๊ฒฐ๊ณผ๋ก ๋์จ ํดํ๋... InputView์์ ์ถฉ๋ถํ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ ๋ด์ฉ์ด์๊ณ , ๋จ์ง inputView์์ ์ฝ์์ ๋ํ ์ ๋ ฅ ๋ฉ์๋๋ง ๋๊ณ ์ถ์ด์ ๊ทธ๋ฌ๋ ๊ฒ์ด์๋ค.
ํผ๋๋ฐฑ์ ๋ฃ๊ณ ๋ณด๋ ์คํ๋ ค ์ง์ฐ๋ ๊ฒ ๊น๋ํ ๊ฒ ๊ฐ์์ ๊ณผ๊ฐํ๊ฒ ์ง์ ๊ณ , view์์ ๋๋ฉ์ธ์ ์์ฑํ๋ ๋ก์ง๋ ๋ณ๊ฒฝํ์ฌ ์ปจํธ๋กค๋ฌ์์ ์์ฑํ๋๋ก ์งํํ์๋ค. ์ด ํผ๋๋ฐฑ ๋๋ถ์ ๋๋ฉ์ธ๊ณผ ๋ทฐ๋ฅผ ๋๋ ์ผ ํ๋ ํ์คํ ์ด์ ๋ฅผ ์ ๋๋ก ์๊ฒ ๋ ๊ณ๊ธฐ์๋ค. ๐
๐ฌ ๋ฌด๋ถ๋ณํ DTO ์์ฑ
์ฌ์ค ์น ๊ฐ๋ฐ์ ์ต์ํด์ ธ์๋ ๋๋, DTO๋ฅผ ์์ฑํ๋ ๊ฒ ๋๋ฌด ๋น์ฐํ๊ฒ ๋๊ปด์ก๊ณ ์์ฐ์ค๋ฝ๊ฒ ์ฌ์ฉํ๋ค. ํ์ง๋ง, ์ ์ฌ์ฉํด์ผ ํ๋์ง๋ ํ ๋ฒ๋ ๊ณ ๋ คํ ์ ์์ด ์ฌ์ฉํ๋ ๊ฒ์ด์๋ค ๐ฅน ๊ทธ๋์ ์ DTO๋ฅผ ์ฌ์ฉํ์ จ๋๋ ์ง๋ฌธ์ ๋ํด ์ฝ๊ฒ ๋ต๋ณํ ์ ์์๋ค.
ํ์ฌ Car์์๋ ์ฃผํ ๊ฒฐ๊ณผ์ ๋ํ ๋๋ผ์ด๋น ๋งํฌ(-)๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์, ํด๋น ๋งํฌ์ ๊ธธ์ด๋ง ํ์ํด์ DTO๋ฅผ ํตํด ํฌ์ฅํ์ฌ ์ฌ์ฉํ๋ ค๊ณ ํ์์ต๋๋ค! ๋ฌผ๋ก ๋ด๋ถ์ ์ผ๋ก getter๋ฅผ ์ฌ์ฉํ์ฌ .length()๋ฅผ ํตํด ๊ฐ์ ธ์ฌ ์ ์๋ ๋ถ๋ถ์ด์์ง๋ง, getter๋ ํด๋น ํ๋์ ๊ฐ ์์ฒด๋ฅผ ๋ฆฌํดํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ชฉ์ ์ ๋ถํฉํ์ง ์๋ค๊ณ ํ๋จํ์๊ณ , ๋ณ๋์ ํด๋์ค๋ก ์ ์ธํ๋ฉด ๋ค์ด๋ฐ์ ํตํด ํด๋น ๊ฐ์ด ์ด๋ค ๊ฒ์ ์๋ฏธํ๋์ง ๋ ์ ๋ํ๋ผ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
๋ค๋ง ๋ฆฌํฉํ ๋ง ๊ณผ์ ์์ ํด๋น ํ๋ ๋์ ์ position ๊ฐ์ ๊ฐ์ง ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์์๊ฐ์ ํฌ์ฅํ๊ธฐ ์ํด์ ‘dto’๋ผ๋ ๋ค์ด๋ฐ ๋์ ์ ํด๋น ๊ฐ์ ํฌ์ฅํ๋ ‘CarPosition’ ๋ฑ์ ํด๋์ค๋ก ๋ค์ ๋ฆฌํฉํ ๋ง ํ๊ณ ์ ํฉ๋๋ค.
์ถ๊ฐ์ ์ผ๋ก, ์์๊ฐ ํฌ์ฅ์ ์ํด์ ์ฐจ ์ด๋ฆ ์ญ์ ๋ณ๋๋ก ๋ถ๋ฆฌํ์ฌ ํฌ์ฅํด์ validation์ ํด๋น ํฌ์ฅ ํด๋์ค์์ ์งํํ๋๋ก ํด์ ๋๋ฉ์ธ์ ๋ํ ์ญํ ์ ์ค์ด๋ ๋ฐฉํฅ์ผ๋ก ์ค๊ณํด๋ณด๊ณ ์ ํฉ๋๋ค! (์ถํ ํ๋๊ฐ ์ถ๊ฐ๋๊ณ , ์ ์ฝ ์ฌํญ์ด ์ถ๊ฐ๋๋ฉด Car ๋๋ฉ์ธ ํ๋์์ ๋๋ฌด ๋ง์ ์ญํ ์ ํ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค :D)
๋น์์๋ ์ด๋ ๊ฒ ๋ต๋ณํ์ง๋ง, ์ฌ์ค ๋๋ฉ์ธ์์ DTO๋ฅผ ๋ฐํํ๊ณ ์์๊ธฐ ๋๋ฌธ์ ๋๋ฉ์ธ์ ํ๋๋ฅผ getter๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ ๊ทผํ ์ ์๋ค๋ ์ด์ ๋ก ์ฌ์ฉํ์๋ค. ํ์ง๋ง! ๋๋ฉ์ธ์์ DTO๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ๋ ์ข์ง ์๋ค๋ ์ฌ์ค์... 1์ฐจ ๋ฆฌํฉํ ๋ง ์ดํ์ ์๊ฒ ๋์๋ค. ์ด๊ฑฐ๋ ๋ค์ ์ธ๊ธํ ์์ ! ์๋ฌดํผ, '์์๊ฐ ํฌ์ฅ'์ด๋ผ๋ ๋ช ๋ชฉํ์ ์ด๋๊น์ง๋ '์ DTO๋ฅผ ์ฐ๋ฉด ์ ๋ผ...?' ์ด๋ฌ๊ณ ์์๋ค. ใ ใ
๐ฌ ์ปจํธ๋กค๋ฌ์ ์ธํฐํ์ด์ค
๋น์ ์ปจํธ๋กค๋ฌ์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์๋๋ฐ, ์ฌ์ค ์ปจํธ๋กค๋ฌ๊ฐ ํ๋์ฌ์ ๊ต์ฅํ ๋ฌด์๋ฏธํ๋ค. ใ ใ ๊ทธ๋์ ๋ค์ ๋ฆฌํฉํฐ๋ง ๋ ๊ณผ๊ฐํ๊ฒ ์ญ์ ํ์๋ค. ์ญ์ ํ๋ ๊ฒธ ์ธํฐํ์ด์ค์ ๋ํด์ ๊ณต๋ถ๋ฅผ ํ์๋๋ฐ, ๊ทธ ๋ด์ฉ์ ๋ธ๋ก๊ทธ์ ์ ๋ฆฌํ๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ์ฌ๊ธฐ์ ์ ์ด๋๋ค.
๐ฌ Enum ํ์ฉ, ํ์ง๋ง ์ด๋๊น์ง...?
๊ธฐ์กด์๋ 'DomainConstant'์ด๋ผ๋ enum ํตํด์ ๋๋ฉ์ธ์ ์ ์ฝ์ฌํญ์ ๋ชจ๋ ์ฌ๊ธฐ์ ๊ด๋ฆฌํ๋ค. ํ์ง๋ง, ๋๋ฉ์ธ์ด ์ปค์ง๋ค๋ฉด...? ๊ทธ๋ ๋ค๋ฉด ๊ด๋ฆฌํด์ผ ํ๋ ํ๋๊ฐ ๋งค์ฐ ๋ง์์ง๊ฒ ๋๋ค. ๊ทธ๋์ ๋ค์ ๋ฆฌํฉํฐ๋ง ๋๋ enum ๊ตฌ์กฐ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๊ณ ์ถ์ด์, ๋๋ฉ์ธ๋ณ๋ก constant enum์ ๋ถ๋ฆฌํ์๋ค. (ํ์ง๋ง ์ด ๊ตฌ์กฐ๋ ์ง๊ธ ์์ ๋ณด๋ฉด ์์ฝ๋ค.)
๋น์, ์ enum์ผ๋ก ์์๋ฅผ ๊ด๋ฆฌํ๋์ง์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ์๊ฐํ์๋ค.
์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์๋ฅผ enum์ผ๋ก ๊ด๋ฆฌํ๋ ํธ์ธ๋ฐ, enum์ผ๋ก ๊ด๋ฆฌํ๋ฉด์ ์ข์๋ ์ ์ ๋ค์๊ณผ ๊ฐ์ด ๋ง์๋๋ฆด ์ ์์ ๊ฒ ๊ฐ์์!
1. ์ ์ถ๋ ฅ ๋ฉ์์ง์ ๊ฒฝ์ฐ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ๋ฉ์์ง์ธ ๋งํผ ๋ณํ๊ฐ ์์ฃผ ์ผ์ด๋ ์ ์๋ ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐ์ด ๋ค์ด์! ์ด๋, ํด๋น ๋ฉ์์ง๋ฅผ ๋ค์ํ ๊ณณ์์ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ ๋ชจ๋ ๊ณณ์ ์ฝ๋๋ฅผ ๋ฐ๊ฟ์ค์ผ ํ๋๋ฐ enum์ผ๋ก ๊ด๋ฆฌํด์ฃผ๋ฉด ํ ๊ณณ์์ ๊ด๋ฆฌํ ์ ์์ด์ ๊ด๋ฆฌ ์ฐจ์์์ ์ฉ์ดํ๋ค๋ ์๊ฐ์ด ๋ค์ด์.
2. ๋๋ฉ์ธ ์ ์ฝ ์ฌํญ์ ๊ฒฝ์ฐ, ์ด๋ฒ ๊ณผ์ ์์๋ ๋๋ถ๋ถ ์ซ์๊ฐ์ ๊ฐ์ง๊ณ ์๋๋ฐ (ํํ ‘๋งค์ง ๋๋ฒ’๋ผ๊ณ ํ์ฃ !) ํด๋น ์ซ์๊ฐ์ ๋ํด์ ๊ทธ๋๋ก ์ฝ๋์ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ฝ๋๋ฅผ ์ฝ๋ ์ ์ฅ์์ ํด๋น ๋๋ฒ๊ฐ ๋ฌด์จ ์๋ฏธ๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ ๋์ ์์๋ณด๊ธฐ๊ฐ ํ๋ค ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ด์. ๊ทธ๋์ enum์ ํตํด ํด๋น ์ซ์์ ๋ํด์ ๋ณ๋์ ๋ช ์นญ์ผ๋ก ๊ด๋ฆฌํ๊ณ , ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ๊ฒฝ์ด ์ฉ์ดํ ์ ์๋๋ก ํ ๊ณณ์์ ๊ด๋ฆฌํ๋ ค๊ณ ์ฌ์ฉํ๋ ๊ฒ ๊ฐ์์!
๋ค๋ง, ํ์ฌ๋ ๋๋ฉ์ธ ์ ์ฝ์ฌํญ ์์ฒด๋ฅผ ํ๋์ ‘DomainConstant’์์ ๊ด๋ฆฌํ๋ค ๋ณด๋๊น, ์ถํ ํ์ฅ์ฑ์ ๊ณ ๋ คํด๋ดค์ ๋ ๋๋ฉ์ธ์ ํฌ๊ธฐ๊ฐ ์ปค์ง๊ฒ ๋๋ค๋ฉด ๋ด๋ถ์ ๋ค์ด๊ฐ์ผ ํ๋ ๊ฐ์ด ๋ง์์ ธ์ ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ ๊ฒ ๊ฐ์์. ๊ทธ๋์ ์ด๋ฒ ๋ฆฌํฉํ ๋ง ๋ ์ ์ฝ์ฌํญ๋ค์ ๊ฐ ๋๋ฉ์ธ์ ๋ง๊ฒ ํ ๋ฒ ๋ ๋ถ๋ฆฌ ์์ ์ ์งํํด๋ณด๋ ค๊ณ ํฉ๋๋ค!
๋ํ, ๋๋ฉ์ธ ๋ด์์ ์์๋ฅผ static final๋ก ๊ด๋ฆฌํ๋ค๋ฉด ๋ด๋ถ์ ์ผ๋ก ์กฐ๊ธ ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ ์ฅ์์๋ ๋ ๊ท์ฐฎ์(?) ์๋ ์์ ๊ฒ ๊ฐ๊ณ , ๋จ์ํ ์์๊ฐ ์๋๋ผ enum ์ญ์ ๋ณ๋์ ํ์ (์ด๋ผ๊ณ ํํํด๋ ๋ ์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง)์ด๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ ์ก์๋จน์ ๊ฒ ๊ฐ์์…!
ํ์ง๋ง, ์ง๊ธ ์์ ์๊ฐํด๋ณด๋ฉด static final๋ก ๊ด๋ฆฌํ๋ ๊ฒ ๋ ์ข์ ๊ฒ ๊ฐ๋ค. ใ ใ
๐ฌ ํ ์คํธ ์ฝ๋
@ParameterizedTest
@ValueSource(ints = {4, 9})
@DisplayName("๋๋ค๊ฐ์ด 4 ์ด์์ด๋ฉด ์๋์ฐจ๊ฐ ์ ์งํ๋ค.")
void givenFourMoreNumber_thenCarMove(int randomNumber) throws Exception {
// given
Cars cars = TestProvider.createTestCars();
Car car = TestProvider.createTestCar("pobi");
// when
Method method = cars.getClass().getDeclaredMethod("checkNumberAndMove", Car.class, int.class);
method.setAccessible(true);
method.invoke(cars, car, randomNumber);
// then
assertThat(car)
.isEqualTo(TestProvider.createTestMoveCar(car));
}
์๋ง ๋ง์ด๋ค ๊ณ ๋ฏผ์ ํ๋ ๋ถ๋ถ์ผ ๊ฒ์ด๋ค. ํ ์คํธํ๊ธฐ ์ด๋ ค์ด ๋ถ๋ถ (=๋๋ค์ผ๋ก ๊ฐ์ ์์ฑํ๋ ๋ถ๋ถ)์ ๋ํด์ ์ด๋ค ์์ผ๋ก ํ ์คํธ๋ฅผ ํ ๊ฒ์ธ์ง ๋ถ๋ฆฌ๋ฅผ ํด์ผ ํ๋ ์ํฉ์ด๋ค. ๊ธฐ์กด์๋ ํ ์คํธ ํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ๋ฆฌํ๋์ ์ผ๋ก ์์ ๊ฐ์ ๋ฃ์ด์คฌ๋ค. ํ์ง๋ง, ์ด๋ฐ ํ ์คํธ ๋ฐฉ์์ ์ง๋์น๊ฒ ๋ณต์กํ๋ค๋ ์๊ฐ์ด ์๋ฌด๋๋ ๊ฐ๋ฐ์ ์ ์ฅ์์ ๋ค ์๋ฐ์ ์๊ณ , ๋ฌด์๋ณด๋ค '์๋์ฐจ์ ์์ง์'์ ํ ์คํธํ๊ธฐ ์ํด์, Cars๊น์ง ์์ฑํ๋ ๊ฑด ์ญํ ๊ณผ ์ฑ ์์ ๋ถ๋ฆฌ๊ฐ ์ ๋๋ก ์ด๋ฃจ์ด์ง์ง ์์ ๊ฒ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
๊ทธ๋์ ๋ฆฌํฉํฐ๋ง ๋ ๊ฐ์ฅ ์ ๊ฒฝ์ฐ๋ฉด์ ์์ ํ ๋ถ๋ถ์ด๋ค. ํ ์คํธํ๊ธฐ ์ด๋ ค์ด ๋ถ๋ถ์ ์ธ๋ถ๋ก ๋นผ๊ธฐ ์ํด ์ธํฐํ์ด์ค์ ๋ํ Mock ํด๋์ค๋ฅผ ์์ฑํ์ฌ ์งํํ์๋ค.
โ๏ธ 1์ฐจ ๋ฆฌํฉํฐ๋ง
1์ฐจ ๋ฆฌํฉํฐ๋ง ๋๋ ๊ฑฐ์ ๊ฐ์์๋ฏ์ด ์์ฒญ ๋ง์ด ์์ ํ๋ค. ํฌ๊ฒ ๋ฝ์๋ณด์๋ฉด, ๋ค์๊ณผ ๊ฐ์ ํญ๋ชฉ์ ์์ ํ๋ค.
- private method์ ํ ์คํธ๋ ์ต๋ํ public์ ํตํด ์งํํ๋๋ก ๋ง๋ค๊ธฐ
- ๊ฐ ๊ฐ์ฒด์ ๋ํ ์ญํ ์ ํ์คํ๊ฒ ํ๊ธฐ (ex. ๋ทฐ์์ Cars, Race ๊ฐ์ ๋๋ฉ์ธ์ ์์ฑํ์ง ์๋๋ก ๋ง๋ค๊ธฐ)
- Wrapper ํด๋์ค ํ์ฉํ๊ธฐ (๊ฐ ํ๋์ ๋ํ ๊ฒ์ฆ๋ wrapper์์ ์งํํ๊ธฐ)
- ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋ ์ด์ฉํ๊ธฐ
- ํ๋ฉด ์ถ๋ ฅ์ view์์ ์งํํ๋๋ก ์งํํ๊ธฐ
- ๋ฉ์๋์ ์์ ๋ณ๊ฒฝํ๊ธฐ
์ฐ์ ๊ฐ์ฅ ๊ฐ๋ฒผ์ด ๋ฉ์๋์ ์์์ ๊ฒฝ์ฐ, ๋ค์๊ณผ ๊ฐ์ ์์๋ฅผ ์งํค๋ ค๊ณ ํ๋ค.
ํด๋์ค > ์ ์ ๋ณ์ (public-protected-private) > ์ธ์คํด์ค ๋ณ์ > ์์ฑ์ > ์ ์ ๋ฉ์๋ > ๋ฉ์๋ > ์คํ ๋ค๋ ๋ฉ์๋ (toString, equals, hashcode...) > getter / setter ๋ฉ์๋.
์ด๋, public์ด๋ private ๋ฉ์๋ ์ฌ์ด์ ์์๋ฅผ ๊ณ ๋ฏผํ์๋๋ฐ public์ ๋จผ์ ์ ์ธํ๋ ๋ฐฉํฅ์ผ๋ก ์งํํ๋ค. private๋ฅผ public ์ฌ์ด์ ์ ์ธํ๋ ๊ฒ์ ์ ํธํ๋ ๋ถ๋ค๋ ๊ณ์๊ฒ ์ง๋ง, public์ ๋จผ์ ๋ฌ์ผ ํด๋น ๊ฐ์ฒด๊ฐ ํ๋ ์ผ์ ๋ช ํํ๊ฒ ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ (=public์ผ๋ก ์ ์ธ๋ ๋ฉ์๋๋ง ๋ฐ๋ก ํ์ธํ๋ฉด ๋๋๊น) ๋๋ public์ ๋จผ์ ์์ฑํ๋ ๋ฐฉํฅ์ผ๋ก ์งํํ๋ค.
๐ฌ ํ ์คํธ ์ฝ๋ ์ฝ๊ฒ ๋ง๋ค๊ธฐ
public class Cars {
private final List<Car> cars;
private final NumberGenerator numberGenerator;
private Cars(final String carNames, final NumberGenerator numberGenerator) {
this.cars = createCars(carNames);
this.numberGenerator = numberGenerator;
validateDuplicateCarName();
}
}
ํ ์คํธํ๊ธฐ ์ด๋ ค์ด ๋ถ๋ถ์ ๋๋๊ธฐ ์ํด์, ๊ธฐ์กด์๋ NumberGenerator๋ฅผ ํ๋์์ ๋ฐ๋ก ์ฃผ์ ํ์์ง๋ง, ์์กด ๊ด๊ณ๋ฅผ ์ฃผ์ ํ๋ ํ์์ผ๋ก ๋ณ๊ฒฝํ์๋ค. (์ธํฐํ์ด์ค ์ฃผ์ ) ์ด ๋๋ถ์ ์ค์ ํ๋ก๊ทธ๋จ์์๋ RaceNumberGenerator๋ฅผ ํตํด ๋๋ค๊ฐ์ ๊ฐ์ ธ์ค๋๋ก ํ๊ณ , ํ ์คํธ ์ฝ๋์์๋ MockNumberGenerator๋ฅผ ์ฃผ์ ๋ฐ์์ ์ํ๋ ๊ฐ๋ง ๊ณ์ํด์ ๋ฆฌํด๋ฐ์ ์ ์๋๋ก ์งํํ์๋ค.
public class MockNumberGenerator implements NumberGenerator {
private int randomNumber = 0;
private final boolean isIncrease;
public MockNumberGenerator(final boolean isIncrease) {
this.isIncrease = isIncrease;
}
@Override
public int generate() {
if (isIncrease) {
return randomNumber = randomNumber * 2 + 1;
}
return randomNumber;
}
}
@Test
@DisplayName("์ฐ์นํ ์๋์ฐจ๋ฅผ ๋ฝ๋๋ค.")
void givenCarInfo_thenPickWinner() {
// given
MockNumberGenerator numberGenerator = TestProvider.createMockNumberGenerator(true);
Cars testCars = TestProvider.createTestCars(testCarNames, numberGenerator);
// when
testCars.race();
List<String> winners = testCars.pickWinners();
// then
assertThat(winners.size())
.isEqualTo(1);
assertThat(winners)
.isEqualTo(List.of("honux"));
}
๋๋ถ์ ์ฐ์นํ ์๋์ฐจ๋ฅผ ๋ฝ๋ ๋ก์ง์์ 1, 3, 5... ์ด๋ฐ ์์ผ๋ก ๊ฐ์ ๋ฐํ๋ฐ๋๋ก ํ์ฌ ์๋์ฐจ 3๊ฐ๊ฐ ๋ค์ด์์ ๋ ๋ง์ง๋ง ์๋์ฐจ๋ง ์ฃผํ์ ํ๊ฒ ๋์ด์ (4 ์ด์์ด ์ฃผํ ์กฐ๊ฑด) ์ฐ์นํ ์๋์ฐจ๋ฅผ ๋ฝ๊ธฐ๊ฐ ์ฌ์์ก๋ค.
// Car.java
public void move(final int power) {
if (power >= CAR_FORWARD_NUMBER.getValue()) {
position.addPosition();
}
}
๋ํ, ๊ธฐ์กด์๋ ์๋์ฐจ๋ฅผ ์ด๋์ํค๋ ๋ก์ง์ ์ธ๋ถ์์ ํ๋จํด์, ์๋์ฐจ์์๋ move()๋ง ์งํํ๋๋ก ๋ง๋ค์์๋๋ฐ, ์๋์ฐจ์๊ฒ ๋๋ค๊ฐ (=power)์ ์ฃผ๊ณ ์ง์ ์์ง์์ ํ๋จํ๋๋ก ํด์, ๋งค๊ฐ๋ณ์๋ฅผ ํตํด ์๋์ฐจ์๊ฒ ๋๋ค๊ฐ์ ์ฃผ์ ์ํฌ ์ ์์๊ธฐ ๋๋ฌธ์ ์๋์ฐจ์ ๋ํ ํ ์คํธ ์ฝ๋ ์ญ์ ์ฝ๊ฒ ์์ฑํ ์ ์์๋ค.
๐ฌ Wrapper ํด๋์ค ํ์ฉํ๊ธฐ
Wrapper ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด์, ๋๋ฉ์ธ์ ๋ชจ๋ ํ๋๋ง๋ค Wrapper๊ฐ ์์ด์ผ ํ๋์ง์ ๋ํ ์๋ฌธ์ด ์์๋ค. ์ง๊ธ์ ๋ฏธ์ ์ด๊ธฐ ๋๋ฌธ์ ์ด์ ๊ฐ์ด ๋ค ๊ฐ์ธ๋ ์์ผ๋ก ์งํํ์ง๋ง, ์ถํ์๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์๋ ๊ฒฝ์ฐ์๋ ๊ฐ์ธ์ง ์๊ณ , ๊ฒ์ฆ ๋ก์ง ๊ฐ์, ๋ณ๋์ ๋ก์ง์ด ํ์ํ๋ค๋ฉด ๊ฐ์ธ์ ์ฒ๋ฆฌํ๋ ๊ฒ ์ข๋ค๊ณ ๋๊ผ๋ค.
๐ฌ ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋ ์์ฑํ๊ธฐ
private Car(final String name) {
this.name = CarName.of(name);
this.position = CarPosition.of();
}
์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋์ ๋ค์ด๋ฐ์ ๋ํด์ ๊ณ ๋ฏผํ๊ฒ ๋ ๊ณ๊ธฐ์๋ค. ์ง๊ธ๊น์ง ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์ด ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ๊ณ ํด์ ์งํํ์๋ค. ๊ทธ๋์ ๋๋ถ๋ถ of๋ก ์งํํ์๋๋ฐ, ์ด๋ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ ๊ฐ๋ค์ ๋ํด ๊ฒ์ฆํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ - ํน์ ์ง๊ณ ๋ฉ์๋์์ ์ฃผ๋ก ์ฌ์ฉํ๋ค๊ณ ํ๋ค. (ex. List.of) ๊ทธ๋์ create๋ฅผ ์ฌ์ฉํ์ฌ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ํ๋ด๋๋ก ๋ณ๊ฒฝํ์๋ค. ๐
๐ฌ ๋๋ฉ์ธ์์ DTO๋ฅผ ์์ฑํ๊ฒ ๋๋ค๋ฉด...?
public List<CarRaceDto> initStatus() {
return cars.stream()
.map(Car::getCarRaceResult)
.collect(Collectors.toList());
}
์์ ์ฝ๋๋ Cars์์ ์ด๊ธฐ ์๋์ฐจ์ ์ํ๋ฅผ ์ถ๋ ฅํด์ฃผ๋ ์ฝ๋์ด๋ค. ๊ทธ๋ฌ๋, ๋๋ฉ์ธ ๋ด๋ถ์์ DTO๋ฅผ ์์ฑํ๊ณ ์๋ค๋ ์ ์ด๋ค.
๋๋ฉ์ธ ๋ด๋ถ์์ Dto๋ฅผ ์์ฑํ๊ฒ ๋๋ค๋ฉด, Dto์ ์์ฑ์๊ฐ ๋ณํ๊ฒ ๋์์ ๋ ๋๋ฉ์ธ ์ฝ๋ ์ญ์ ํจ๊ป ๋ณ๊ฒฝ๋๋ค๋ ๋จ์ ์ด ์กด์ฌํด์. Dto์ ๊ฒฝ์ฐ ๋๋ฉ์ธ์ ๋นํด ๋ณ๊ฒฝ์ด ์ฆ์ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์, ๋๋ฉ์ธ ๋ก์ง ์ญ์ ํจ๊ป ๋ณ๊ฒฝ๋๋ค๋ ์ ์ด ์ข์ง ์๋ค๊ณ ์๊ฐ์ด ๋ค์ด์. ๋ํ, DTO๋ ์ด๋ฆ ๊ทธ๋๋ก Data Transfer Object๋ก์, ๊ณ์ธต ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ฃผ๋ ์ญํ ์ ํ๋ ๊ฐ์ฒด์ธ๋ฐ ๋๋ฉ์ธ์ด DTO๋ฅผ ์์กดํ๊ฒ ๋๋ ๊ฑด ์ด์ํ๋ค๊ณ ์๊ฐ์ด ๋ค์ด์.
์ฅ์ ์ด๋ผ๊ณ ํ๋ค๋ฉด, ์ธ๋ถ์์ getter๋ฅผ ํตํด ๊ฐ์ ์ ๊ทผํ์ง ์๊ณ ๋ด๋ถ์ ํ๋๊ฐ์ ํตํด์ ๋ฐ๋ก DTO๋ฅผ ์์ฑํ ์ ์๋ค๋ ์ฅ์ ์ด ์์ ๊ฒ ๊ฐ์์. (getter๋ฅผ ์ง์ํ๋ค๋ ๊ด์ ํ์์...! ์ด ๋ถ๋ถ์ ์๊ฐํด๋ด์ผ ๋ ๋ฌธ์ ๊ฐ์์. ์ง๊ธ๊น์ง ๋๋ฌด getter๋ฅผ ๋ฌด์์ ์ผ๋ก ์ ์ฐ๋ ค๊ณ ํ๋ ๊ฒ ๊ฐ์์์. ใ ใ )
ํ์ง๋ง ์ ์์ ๊ฒฝ์ฐ๊ฐ ๋ฆฌํฉํ ๋ง์ด ๋ ํ์ํ ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐ์ด ๋ค์ด์. ๋ณ๋์ ์๋น์ค ๊ณ์ธต์ ๋ง๋ค์ด์ DTO๋ฅผ ๋ฐํํ๋๋ก ํ๊ณ , ์ด ๊ฒฐ๊ณผ๋ฅผ ์ปจํธ๋กค๋ฌ์์ ์ฌ์ฉํ๋๋ก ํ๋ ๊ฒ ๋ ์ข์ ๊ตฌ์กฐ๊ฐ ์๋๊น… ๋ผ๋ ์๊ฐ์ด ๋ค์์ด์. ๋ฆฌํฉํ ๋ง ํ๋ฉด์ ํ ๋ฒ ์์ ํด๋ณด๊ฒ ์ต๋๋ค! ๐
๊ทธ๋์ 2์ฐจ ๋ฆฌํฉํ ๋ง ์, ์๋น์ค ๊ณ์ธต์ ํ์ฉํ์ฌ DTO๋ฅผ ๋ฐํํ๋๋ก ์์ฑํ์๋ค. (ํ์ง๋ง, ์ง๊ธ ์์ ์๊ฐํด๋ณด๋ฉด ๊ทธ๋ฅ getter๋ก ๋๋ฉ์ธ ๊ฐ์ฒด ์์ฒด๋ฅผ ๋๊ฒจ์ฃผ๊ณ ๋ทฐ์์ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๊ฒ ๋ ๊น๋ํ์ ๊ฒ ๊ฐ๋ค. ใ ใ ์ง๊ธ ์ํ๋ก๋ ๋๋ฌด ํค๋นํ ๋ก์ง์ด๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.)
๐ฌ Getter๋ฅผ ์ง์ํ๋ ์ด์
๋น์ ๊ตฌํํ ๋ ๋๋ฉ์ธ์ getter๋ฅผ ๊ต์ฅํ ์ง์ํ๋ ค๊ณ ํ์๋ค. ์ฒ์์๋ ๋ณ์ด์ ์์ด 'getter๋ฅผ ์ง์ํด์ผ ๋ผ!'๋ผ๋ ๋ง ํ ๋ง๋๋ง ๋ฃ๊ณ , ๋ฆฌ๋ทฐ์ด๋๊ป ์ง๋ฌธ์ ๋ฃ๊ณ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๋ก ์ ๋ด๋ ธ์๋ค.
๊ฐ์ฒด๋ฅผ ๋ ๊ฐ์ฒด์ค๋ฝ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํด์๋, ๊ฐ์ฒด์๊ฒ ๊ฐ์ ๋ฐ์์ค๋ ๊ฒ์ด ์๋ ๊ฐ์ฒด์๊ฒ ์ง์ ์ง๋ฌธ์ ๋์ง๋ ํํ๋ก ์ด๋ฃจ์ด์ ธ์ผ ๋๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ด์์. ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ ๊ฐ์ฒด ์ค์ค๋ก ํ๋จํ๊ณ , ์ธ๋ถ์ ๋ํด์ ์ต๋ํ ์ํฅ์ ๋ ๋ฐ๋๋ก ํ๊ณ ์ถ์ด์ getter / setter๋ฅผ ์ง์ํ๋ ค๊ณ ํ๋ ํธ์ด์์.
ํ์ง๋ง, ์๊ฐํด ๋ณด๋๊น ๋ฌด์์ ์ผ๋ก getter๋ฅผ ์ง์ํ๋ ๊ฒ๋ ๋ณ๋ก ์ข์ ์ค๊ณ๋ผ๋ ์๊ฐ์ด ๋ค์ง ์์์ด์. ํนํ ์ด์ ์ฒ๋ผ getter๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ์ํด์ ๋๋ฉ์ธ ๋จ์์ DTO๋ฅผ ๋ฆฌํดํ๋ ๋ฑ์ ํ์๋ ์คํ๋ ค ๊ฐ์ฒด ๊ฐ์ ๊ฒฐํฉ๋๋ฅผ ์ฆ๊ฐ์ํค๋ ํ์๋ผ๊ณ ์๊ฐ์ด ๋ค์์ด์...! ๊ทธ๋์ ์ ๋ง์ ์์ ๊ธฐ์ค์ ์ธ์ ๋๋ฐ, ์ถ๋ ฅ์ ์ํด ํ์ํ๊ฑฐ๋ DTO ๋ณํ ๋ฑ์์๋ getter์ ์ฌ์ฉ์ด ํ์์ ์ด๋ผ๊ณ ์๊ฐ์ด ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฒฝ์ฐ์๋ ์ฌ์ฉํ๋ ๊ฒ ๋ ๋ซ๋ค๊ณ ์๊ฐ์ด ๋ค์ด์!
๊ทธ๋์ ์ด๋ฒ ๋ฆฌํฉํ ๋ง ๋๋ cars์ ๋ํ getter๋ฅผ ์ฌ์ฉํ๋ฉด์ DTO ์์ฑ์ ๋๋ฉ์ธ์์ ์ฒ๋ฆฌํ์ง ์๋๋ก ๋ณ๊ฒฝํ์์ด์. ๋ํ, unmodifableList๋ฅผ ํตํด์ ์ธ๋ถ์์ ๋ณ๊ฒฝํ์ง ์๋๋ก ์งํํ์ต๋๋ค! ๐ ์ด๋ฐ ์์ผ๋ก getter๋ฅผ ์ฌ์ฉํ๋ ๊ฑด ๊ด์ฐฎ์๊น์?
1์ฐจ ๋ฏธ์ ์ ์์ ํ ๋๋ธ ์ง๊ธ์, DTO๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๊ณ ์์ง๋ง ๋น์์ ๋ด๋ฆด ์ ์๋ ์ต์ ์ ๊ฒฐ๋ก ์ด์๋ ๊ฒ ๊ฐ๋ค.
โ๏ธ 2์ฐจ ๋ฆฌํฉํฐ๋ง
2์ฐจ ๋ฆฌํฉํฐ๋ง์์๋ ๊ธฐ๊ฐ์ด ๊ทธ๋ ๊ฒ ๊ธธ์ง ์์์ด์, ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์๋ค.
- ๋๋ฉ์ธ์์ DTO๋ฅผ ์ฐธ์กฐํ์ง ์๋๋ก ๊ฐ์ ํ๊ธฐ.
- Cars / Race์ ๋ํ Service Layer ์ถ๊ฐํ๊ธฐ. (์ปจํธ๋กค๋ฌ์์ ๋๋ฉ์ธ ๋์ ์๋น์ค๋ฅผ ์ฐธ์กฐํ๋๋ก ๋ณ๊ฒฝํ๊ธฐ)
- ํ๋์ ๋ฉ์๋๋ ํ๋์ ์ผ๋ง ํ๋๋ก ๋ถ๋ฆฌํ๊ธฐ, ๋ณ์๋ช ๋ฆฌํฉํ ๋ง ํ๊ธฐ.
- ์๋น์ค์ ๋ํ ํ ์คํธ ์ถ๊ฐ ๋ฐ ๋๋ฉ์ธ์ ๋ชจ๋ public ๋ฉ์๋์ ๋ํ ๋จ์ ํ ์คํธ ์งํํ๊ธฐ.
- ์๋์ฐจ์ ๋ํ Comparable ์ธํฐํ์ด์ค ๊ตฌํ์ ํตํด position ๊ตฌํ๋ ๋ก์ง ๊ฐ์ ํ๊ธฐ. (getter ์ฌ์ฉ X)
DTO ๋ณํ์ ์ํด์ Service ๋ ์ด์ด๋ฅผ ์ถ๊ฐํ์๋ค๋ ๊ฒ์ด ๊ฐ์ฅ ํฌ๊ฒ ๋ฐ๋ ์ ์ด๋ค. ๊ทธ๋ฆฌ๊ณ , ๋น์ ๋ฆฌ๋ทฐ์ด๋๊ป ๋ฐ์๋ ํผ๋๋ฐฑ ์ค์์ "๋ถ์ ํ ๋ค์ด๋ฐ์ ์ฌ์ฉํ์ง ์๊ธฐ" ์ ๋ํด์ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ์์๋๋ฐ, ์ด ๋ถ๋ถ๋ ์์ํ๊ฒ ์์ ํ๋ ์ ์ด ๊ธฐ์ต์ ๋จ๋๋ค. ๊ทธ๋ฆฌ๊ณ , ์ฌ์ ํ ํ ๊ฐ์ง ๋ฉ์๋๋ ํ๋์ ํ์๋ฅผ ํ๋๋ก ๋ง๋๋ ๊ฒ ์ ์ง์ผ์ง์ง ์์์, ๋ฆฌํฉํ ๋ง ๋ ์ต๋ํ ๊ฐ์ ํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ค.
๐ฌ for๋ฌธ๊ณผ for-each, stream
// Cars.java
cars.forEach(car -> {
int power = numberGenerator.generate();
car.move(power);
});
๋ํ, ํ์ด๋ ์งํํ๋ฉด์ for๋ฌธ ๋์ ์ .forEach()๋ฅผ ์ฌ์ฉํ์๋๋ฐ, ์ด ๋ถ๋ถ์ ๋ํด ์ ํํ ์ธ์งํ์ง ๋ชปํ๊ณ ์ฌ์ฉํ๋ ๊ฒ ๊ฐ์์ ๋ฐ๋ก ๊ณต๋ถ๋ฅผ ์งํํ๋ค.
๋ด๋ถ์์ iterator๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค๋ ์ ๊ณผ, for-each๊ฐ ์ผ๋ฐ for์ ๋นํด์ ๋๋ฆฌ๋ค๋ ๊ฒ์ ์ฒ์ ์์๋ค ๐ซข ๋ํ, Collections.forEach ์ญ์ iterator๋ฅผ ์ฌ์ฉํ๋ฉฐ ๋ฐ๋ณตํ๊ธฐ ๋๋ฌธ์, enhanced for๋ฌธ๊ณผ ๋์ผํ๊ณ , ์ฑ๋ฅ์์ผ๋ก ๋์ผํ๋ค๊ณ ํ๋ค! (Stream์ด๋ผ์ ๋ ๋๋ฆด ์ค ์์๋๋ฐ ์๋์๋ค...) ์ด๋ ๊ฒ ๋ ๋ฐฐ์ธ ์ ์์๋ค.
โ๏ธ 3์ฐจ ๋ฆฌํฉํฐ๋ง
์ฌ์ค 3์ฐจ ๋ฆฌํฉํฐ๋ง์ ๋ง์ด ์งํํ์ง ๋ชปํ๋ค. ์ฐ๊ทน๋ ๊ฒน์น๊ณ , ๋ค์ ๋ ์ ์๋ก์ด ๋ฏธ์ ์ ์งํํด์ผ ๋ผ์ ํฌ๊ฒ ๋ฐ๊พธ์ง๋ ๋ชปํ๋ค.
๐ฌ ์ฐ์น์ ์ ์ถ ๋ก์ง์ ๋ํ์ฌ
public List<String> pickWinners() {
Car maxPositionCar = getMaxPositionCar();
return cars.stream()
.filter(maxPositionCar::isSamePosition)
.map(Car::getName)
.collect(Collectors.toUnmodifiableList());
}
๊ธฐ์กด์๋ Cars์์ ์ฐ์น์๋ฅผ ๋ฝ๋ ๋ก์ง์ ๋์์๋ค. ์ด์ ๋ ์ผ๊ธ์ปฌ๋ ์ ์ธ Cars์์ ์ด๋ฏธ ์๋์ฐจ์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์, ๊ฐ์ฒด์๊ฒ ์ง๋ฌธํ๊ธฐ ์ํด์ ์๋์ฐจ ๋ด์์ ์งํํ๊ณ ์ ํ์๋ค. (getter๋ฅผ ํตํด ๋ฐ์์์ ์ฒ๋ฆฌํ์ง ์์ผ๋ ค๊ณ ํ์๋ค.) ๋ค๋ง, ๋ฆฌ๋ทฐ์ด๋๊ป์๋ '์ฐ์น์ ์ ์ถ์ ๋ํ ์ฑ ์'์ ๊ฒฝ์ฃผ๋ฅผ ๊ด๋ฆฌํ๋ Race์์ ์ด๋ฃจ์ด์ง๋ ๊ฒ ๋ ๋ง์ง ์๋๊ณ ๋ง์ํด ์ฃผ์ ์, WinnerCar๋ผ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๊ด๋ฆฌํ๊ณ ์ ํ๋ค.
public class WinnerCar {
private final Cars carInfo;
private WinnerCar(final Cars carInfo) {
this.carInfo = carInfo;
}
public static WinnerCar create(Cars carInfo) {
return new WinnerCar(carInfo);
}
public List<String> getName() {
Car maxPositionCar = carInfo.getMaxPositionCar();
return getWinnerNames(maxPositionCar);
}
private List<String> getWinnerNames(Car maxPositionCar) {
return carInfo.getCars()
.stream()
.filter(maxPositionCar::isSamePosition)
.map(Car::getName)
.collect(Collectors.toUnmodifiableList());
}
}
๋ค๋ง, ๋ด๋ถ์ ์ผ๋ก Cars์ ์ ๋ณด๋ฅผ ๋ฐ์์์ ์ํํ๊ธฐ ๋๋ฌธ์ WinnerCar๊ฐ ํน๋ณํ ํ์ํ๋ค๋ ์๊ฐ์ด ๋ค์ง ์์์, ์ต์ข ์ ์ผ๋ก ๋ดค์ ๋๋ ๊ทธ๋ ๊ฒ ์ข์ ๋ฆฌํฉํ ๋ง์ด ์๋์๋ค๊ณ ์๊ฐ์ด ๋ ๋ค. (์๋ฌด๋๋ ์๊ฐ์ด ์ด๋ฐํด์ ๋ ์ ๊ฒฝ์ ๋ชป ์ด ๊ฒ ๊ฐ๋ค ใ ใ ) ์ง๊ธ ์งํํ๋ค๋ฉด, maxPosition์ ๋ํ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๊ฑฐ๋, ํน์ ์ฐ์น์์ ๋ํด ๋ฐ๋ก ์ ์ฅํ๋ ํ๋๋ฅผ ๋์ด์ ์กฐ๊ธ ๋ ๊ฐ์ฒด๊ฐ ์ฑ ์์ ๊ฐ์ง๋๋ก ์งํํ์ ๊ฒ ๊ฐ๋ค. ์ด ๋ถ๋ถ์ ์์ฝ๋ค.
์๋ฌดํผ, ์ด๋ ๊ฒ ํ๊ณ ์์ฑ์ด ๋๋ฌ๋ค! ๐ฅฒ
๋ณธ ํ๊ณ ์ ๋ด๊ธด ๊ฒ๋ณด๋ค ์ฌ์ค ๋ ๋ง์ ๊ฒ๋ค์ ํ๋ ๊ฒ ๊ฐ์ง๋ง, ๊ทธ๋ฐ ๊ฑด PR์์ ์ถฉ๋ถํ ๋๋ฌ๋๋ ์ ๋ณด์ธ ๊ฒ ๊ฐ์์ ์กฐ๊ธ ๋ ๋ด ๊ฐ์ ๊ณผ ๋ฐฐ์ด ์ ๋ค์ ์์ฃผ๋ก ์์ฑํ์๋ค. ์์ผ๋ก ๋ฏธ์ ํ๋ฉด์ ํ๊ณ ๋ ๊พธ์คํ ์์ฑํด๋ณด๊ณ ์ ํ๋ค ๐ช ํ์ดํ ...!
'์ฐ์ํํ ํฌ์ฝ์ค > ๋ ๋ฒจ 1' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์ฐํ ์ฝ 5๊ธฐ] ๋ ๋ฒจ 1 ๋ ๋ฒจ ์ธํฐ๋ทฐ ์ ๋ฆฌ ๋ฐ ๊ฐ์ ํ๊ณ (4) | 2023.04.06 |
---|---|
[์ฐํ ์ฝ 5๊ธฐ] ์ฒด์ค ๊ฒ์ ๊ตฌํ ๋ฏธ์ ํ๊ณ (0) | 2023.04.05 |
[์ฐํ ์ฝ 5๊ธฐ] ๋ธ๋์ญ ๊ตฌํ ๋ฏธ์ ํ๊ณ (0) | 2023.04.04 |
[์ฐํ ์ฝ 5๊ธฐ] ์ฌ๋ค๋ฆฌ ํ๊ธฐ ๊ฒ์ ๋ฏธ์ ํ๊ณ (0) | 2023.04.03 |
[์ฐํ ์ฝ 5๊ธฐ] 1์ฃผ์ฐจ ํ๊ณ ๋ก - ์ฐ๊ทน, ์๋์ฐจ ๊ฒฝ์ฃผ ๊ฒ์ ๊ตฌํํ๊ธฐ (2) | 2023.02.13 |