NextStep TDD, Clean Code with Java ์๋ฃ ํ๊ธฐ
์๋ก
4.3~6.1 ์ฝ 8.5์ฃผ๊ฐ NextStep์์ ์งํํ๋ TDD, Clean Code With Java 16๊ธฐ ๊ณผ์ ์ ์ฐธ๊ฐํ๋ค. ์ฐธ๊ฐํ๊ฒ ๋ ๊ณ๊ธฐ๋ ๋ง์๋ฐ, ์ ๋ฆฌํด ๋ณด๋ฉด ๋ค์์ผ๋ก ์์ฝํ ์ ์๋ค.
- ์ค์ ์นดxx, 11xx๋ฑ์ ๊ธฐ์ ์์ ๋ฅ์คํธ์คํญ์ ๊ต์ก ๊ณผ์ ์ ํตํด ์ ์ ์จ๋ณด๋ฉ์ ์งํํ๊ณ ์๊ณ , ์ฐํ ์ฝ๋ ์ฐํ ์บ ์ ์ผ๋ถ ๊ณผ์ ์ด๋๋ ๋น์ทํด ๊ฒ์ฆ๋ ๊ฐ์ ํ๋ฆฌํฐ๋ผ๊ณ ์๊ฐํ๋ค.
- ์ดํํฐ๋ธ ์๋ฐ, ํด๋ฆฐ์ฝ๋, TDD์ ๊ฐ์ด ์ฑ ์ ํตํด ํผ์ ์ด๋ก ๋ง ์ตํ๋ ์ง์๋ค์ ์ค์ต์ ํตํด ํ์ฉ์ ํด ๋ณผ ์ ์๋ค.
- ๋ด๊ฐ ์๋ ์ฃผ๋ณ์ ๋ฐ์ด๋ ์ฌ๋๋ค์ ๊ณตํต์ ์ผ๋ก ๋ฅ์คํธ์คํญ์ ๊ฐ์๋ฅผ ํ๋ ์ด์์ ์๋ฃํ๋ค.
๊ณผ์ ์์ฒด๋ ์ฝ ๋ ๋ฌ๊ฐ ์งํ๋๋ฉฐ ํฌ๊ฒ๋ 4๊ฐ, ์ธ๋ถ์ ์ผ๋ก๋ 17๊ฐ์ ์๋ฐ ๋ฏธ์
์ ์ํํด์ผ ํ๋ค. ๋ฏธ์
์ ์ํํ๋ฉด PR์ ์ฌ๋ฆฌ๊ณ , ๋ฉํ ๋ค์ ๋ฆฌ๋ทฐ๋ฅผ ํตํด merge๊ฐ ๋๋ ์์ผ๋ก ์งํ์ด ๋๋๋ฐ, 80๋ง ์์ด๋ผ๋ ์์ง ์์ ๊ธ์ก์ ๊ณผ์ ์์๋ ๋ถ๊ตฌํ๊ณ ์ ๊ณผ์ ์ ์๋ฃํ๋ ์๋ฃ์จ์ ์ ์ฒด ์ธ์์ 10~20%๊ฐ ์ฑ ๋์ง ์๋๋ค๊ณ ํ๋ค. ์ค์ ๋ก ์ด๋ฒ ๊ธฐ์์์๋ 120~130๋ช
์ ๋๊ฐ ์ฐธ๊ฐํ์ง๋ง, 6/1์ผ๊น์ง ์ ๊ณผ์ ์ ์๋ฃํ ์ธ์์ 10๋ช
๋จ์ง์ด์๋ ๊ฒ ๊ฐ๋ค.
๋ฏธ์
๋ด๊ฐ ์งํํ ๋ชจ๋ ๋ฏธ์ ์ PR๊ณผ ์งํํ๋ฉด์ ๋ด๊ฐ ๋ฐฐ์ ๋ ์ ์ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์๋์ฐจ ๊ฒฝ์ฃผ - ๋จ์ํ ์คํธ
- PR ๋ฆฌ๋ทฐ
ํจํค์ง๋ณ๋ก ์ฑ ์์ ๋ถ๋ฆฌํ๊ณ , JUnit์ ์ฌ์ฉ๋ฒ์ ์ตํ์ ๋จ์ํ ์คํธ๋ฅผ ํ๋ ๋ฒ์ ๋ํด ์ตํ๋ค. ํนํ๋ ์ด๋ฒ ๋จ๊ณ์ ์์น์ด ์์๋๋ฐ, ์๋์ ๊ฐ์ ๊ท์น์ ํตํด์ ๋ฉ์๋๋ฅผ ๋ถ๋ฆฌํด ๋ฉ์๋๊ฐ ํ ๊ฐ์ง ์์ ๋ง ๋ด๋นํ๋๋ก ๊ตฌํํ๋ ์ฐ์ต์ ํ๋ ๊ฒ์ด ๊ฐ์ ๋ชฉํ์๋ค.
- ํ ๋ฉ์๋์ ์ค์ง ํ ๋จ๊ณ์ ๋ค์ฌ ์ฐ๊ธฐ๋ง ํ๋ค.
- else ์์ฝ์ด๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค.
- ๋ฉ์๋์ ๋ผ์ธ ์๊ฐ 15๋ผ์ธ์ ๋์ด๊ฐ์ง ์์์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์๋์ฐจ ๊ฒฝ์ฃผ ๋ฏธ์ ์ ํตํด ๋ฉ์๋ ๋ถ๋ฆฌ๋ฟ๋ง ์๋๋ผ ์ผ๊ธ์ปฌ๋ ์ ๊ณผ ์ ๋ตํจํด์ ํ์ฉ์ ๋ํด์ ์ตํ ์ ์์๋ค.
๋ก๋ - TDD
- PR ๋ฆฌ๋ทฐ
๋ก๋๋ฏธ์ ์ 2,3,4๋จ๊ณ๋ ์ด์ ์ ์๋์ฐจ ๊ฒฝ์ฃผ์ ๋น์ทํ๋ค๋ ๋๋์ด ๋ค์๊ณ , ์๋ก์ด ๊ฑธ ์ตํ๊ธฐ๋ณด๋ค๋ ์ด์ ๋จ๊ณ์์ ํ์ตํ ๋ฉ์๋ ๋ถ๋ฆฌ์ ์ผ๊ธ์ปฌ๋ ์ , ์ ๋ตํจํด, ๋จ์ํ ์คํธ์ ๋ํ ์ดํด๋ฅผ ํ๋ฒ ๋ ์ค์ต์ ํด๋ด์ผ๋ก์จ ์ ๊ฐ๋ฌด๋ฆฌ์ํค๋ ๊ฑธ ๋ชฉํ๋ก ํ๋ค.
๋ก๋ ๋ฏธ์ ์์ ๊ฐ์ฅ ๊ธฐ์ต์ ๋จ๋ ๋ฏธ์ ์ "1๋จ๊ณ - ๋ฌธ์์ด ๊ณ์ฐ๊ธฐ"๋ค. ์๊ตฌ์ฌํญ์ ๋จ์ํ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ฌธ์์ด ๊ฐ์ ๋ฐ๋ผ ์ฌ์น ์ฐ์ฐ์ ์ํํ ์ ์๋ ๊ณ์ฐ๊ธฐ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ธ๋ฐ, ์ด๊ฒ ๋ค์ฌ ์ฐ๊ธฐ๋ฅผ ํ ๋ฒ๋ง ํด์ผ ํ๊ณ , else๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๋๋ค๋ ์กฐ๊ฑด ๋๋ฌธ์(๋น์ฐํ switch๋ ์๋๊ณ , ๊ทธ๋ ๋ค๊ณ if ๋ก์น ๋ ์๋๋ค.) ์กฐ๊ธ ์๋ก์ด ์ ๊ทผ์ ํตํด ๊ตฌํํด์ผ ํ๋ค.
package domain;
import java.util.Arrays;
import java.util.function.BiFunction;
public enum Operator {
PLUS("+", (num1, num2) -> Integer.valueOf(num1 + num2)),
MINUS("-", (num1, num2) -> Integer.valueOf(num1 - num2)),
MULTIPLY("*", (num1, num2) -> Integer.valueOf(num1 * num2)),
DIVIDE("/", (num1, num2) -> Integer.valueOf(num1 / num2));
private final String operator;
private final BiFunction<Integer, Integer, Integer> calculator;
Operator(String symbol, BiFunction<Integer, Integer, Integer> calculator) {
this.operator = symbol;
this.calculator = calculator;
}
public String getOperator() {
return operator;
}
public static Integer calculator(String operator, Integer num1, Integer num2) {
return getOperator(operator).calculator.apply(num1, num2);
}
private static Operator getOperator(String operator) {
return Arrays.stream(values())
.filter(o -> o.operator.equals(operator))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("์ฌ์น ์ฐ์ฐ ๊ธฐํธ๋ง ๊ฐ๋ฅํฉ๋๋ค."));
}
}
์ด๊ฑด ์ฌ์น์ฐ์ฐ์ ๊ตฌํํ ๋ด ์ฝ๋์ด๊ณ , Enum๊ณผ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ํตํด ๊ตฌํํ๋ค. BiFunction์ ์ฌ๋ด์์๋ ์์ฃผ ๋ณด์ด๋ ์ฝ๋๋ค์ด๋ผ ์ต์ํ๋๋ฐ, Enum์ ์ค์ค๋ก๋ ์ด๋ ๊ฒ๊น์ง ํ์ฉํ ์ ์์ ์ค์ ๋ชฐ๋๋ค. ๊ตฌํํ๋ฉด์๋ ๋๋๊ณ , ์์ผ๋ก๋ ๊พธ์คํ ํ์ฉํ ์ ์์ ์ ๋๋ก ๊ณ์ํด์ ํ์ตํด์ผ ํ ๊ฒ ๊ฐ๋ค.
์ฌ๋ค๋ฆฌํ๊ธฐ - FP, OOP
- PR ๋ฆฌ๋ทฐ
์ฌ๋ค๋ฆฌํ๊ธฐ์ ๋ฏธ์ ์ ํตํด์๋ ํฌ๊ฒ ์๋์ ์ธ ๊ฐ์ง๋ฅผ ํ์ต์ ํ๋ ๊ฒ์ด ๋ชฉํ์๋ค.
- ํฌ๊ฒ ์คํธ๋ฆผ, ๋๋ค๋ฅผ ํตํด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ ๊ฒฝํ
- In -> Out, Out -> In ๋ฐฉ์์ผ๋ก ๋๋ฉ์ธ ๊ฐ์ฒด๋ฅผ ์ค๊ณํ๋ ๊ฒฝํ
- ์ฑ ์์ฃผ๋์ค๊ณ ๊ธฐ๋ฐ์ผ๋ก ์ธํฐํ์ด์ค๋ฅผ ํ์ฉํด ํ๋ก๊ทธ๋๋ฐ์ ํ๋ ์ฐ์ต
๊ทธ๋ฆฌ๊ณ ์ด๋ฒ ๋ฏธ์ ์ ์ถ๊ฐ๋ก ์ง์ผ์ผ ํ ๊ฐ์ฒด์งํฅ ์ํ ์ฒด์กฐ ์์น์ ๋ค์๊ณผ ๊ฐ์๋ค.
- ๋๋ฏธํฐ ๋ฒ์น์ ์งํจ๋ค.
- ๋ชจ๋ ์ํฐํฐ๋ฅผ ์๊ฒ ์ ์งํ๋ค.
- 3๊ฐ ์ด์์ ์ธ์คํด์ค ๋ณ์๋ฅผ ๊ฐ์ง ํด๋์ค๋ฅผ ์ฐ์ง ์๋๋ค.
- ๊ฒํฐ/์ธํฐ/ํ๋กํผํฐ๋ฅผ ์ฐ์ง ์๋๋ค.
๋๋ ์ด ์ค์์ ์ธ ๋ฒ์งธ "3๊ฐ ์ด์์ ์ธ์คํด์ค ๋ณ์๋ฅผ ๊ฐ์ง ํด๋์ค๋ฅผ ์ฐ์ง ์๋๋ค." ์ด๊ฒ ๊ต์ฅํ ์ด๋ ค์ ๋ค. 3๊ฐ ์ด์์ด๋ ๋ง์ ๋ ๊ฐ๊น์ง๋ง ์จ์ผ ํ๋ค๋ ๋ง์ด์๊ณ , ๋ฏธ์ ์ ์งํํ๋ค ๋ณด๋ฉด ๋ฑ ์ธ ๊ฐ๊น์ง๋ง ์ฐ๋ฉด ์์ฝ๊ฒ ๊ตฌํํ ์ ์์ ๊ฒ ๊ฐ์๋ฐ ๋ ๊ฐ๊น์ง๋ง ์จ์ผ ํ๋ค๋ ์กฐ๊ฑด ๋๋ฌธ์ ๊ต์ฅํ ๊ตฌํํ๊ธฐ ๊น๋ค๋ก์ด ๋ถ๋ถ์ด ์์๋ค.
public class LadderResults {
private final Map<Participant, LadderResult> ladderResults;
public LadderResults(Map<Participant, LadderResult> ladderResults) {
this.ladderResults = ladderResults;
}
public LadderResult getResultForParticipant(Participant participant) {
return Optional.ofNullable(ladderResults.get(participant))
.orElseThrow(() -> new IllegalArgumentException(participant.getName() + " ์ฐธ๊ฐ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค."));
}
public Map<Participant, LadderResult> getAllResults() {
return ladderResults;
}
}
๋น์ฅ์ ์ฝ๋๋ง ๋ด์๋ ๋ด๊ฐ ๋งํ ๋ด์ฉ์ด ์ดํด๊ฐ ์ ๊ฐ๊ฒ ์ง๋ง, ์ต๋ํ ํด๋์ค๋ฅผ ๋ถ๋ฆฌ์ํค๊ณ , ์ผ๊ธ์ปฌ๋ ์
์ผ๋ก ๋ฌถ๊ณ , ๊ทธ๊ฑธ ๋ Map์ผ๋ก ๋ฌถ๋ ๋ฐฉ๋ฒ์ ํตํด ํด๊ฒฐํ๋ค.
์๊ฐ์ ์ฒญ - ๋ ๊ฑฐ์ ์ฝ๋ ๋ฆฌํฉํฐ๋ง
- PR ๋ฆฌ๋ทฐ
์๊ฐ์ ์ฒญ ๋ฏธ์ ์ ์ด๋ฒ 16๊ธฐ์ ์๋กญ๊ฒ ์ถ๊ฐ๋ ๋ฏธ์ ์ด์๋ค. ์ฒ์๋ถํฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ค์ ํ์ ์์ ๋ง์ฃผ์น ๋ฒํ ๋ ๊ฑฐ์ ์ฝ๋๊ฐ ์ฃผ์ด์ก๊ณ , ์ด๋ฅผ ์ง๊ธ๊น์ง ํ์ตํ TDD, OOP, ํด๋ฆฐ์ฝ๋ ๊ธฐ๋ฐ์ผ๋ก ์ ์ง์ ์ผ๋ก ๋ฆฌํฉํฐ๋ง ํ๋ ๊ฒ์ด ๋ฏธ์ ์ ๋ชฉํ์๋ค.
์ฒซ ๋ฏธ์ ์ด๋ค ๋ณด๋, ์ฐธ๊ณ ํ ๋ ํผ๋ ์์๊ณ ๊ทธ๋ ๋ค ๋ณด๋ ๋์ด๋๊ฐ ๊ธ๊ฒฉํ๊ฒ ๋์๋ค๊ณ ์๊ฐํ๋ค. ํนํ๋ ๋ฏธ์ ์ ์ฝ๋๋ jdbcTemplate์๊ธฐ ๋๋ฌธ์ JPA๊ธฐ๋ฐ์ ๋๋ฉ์ธ ์ค๊ณ์ ๋น์ฆ๋์ค ๋ก์ง์ ์์ฑํด ์ค๋๋ฐ ์ต์ํ๋ ๋๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์๋ ์ฝ๋์ ์ ๋ต์ ์๋ค์ง๋ง ์ด๊ฒ ๊ณผ์ฐ ์ฌ๋ฐ๋ฅธ ๋ฐฉ์์ผ๊น?๋ผ๋ ์๋ฌธ์ ์ด ๊ณ์ ๋ค์๋ค. ๊ทธ๋ฆฌ๊ณ ์ค์ ๋ก๋ ๊ฐ์ฅ ๋ง์ ๋ฆฌ๋ทฐ ํํ์ด ์ค๊ฐ๋ ๋ฏธ์ ์ด์๋ค.
๋ง์ง๋ง ๋ฏธ์
์ ํตํด์ ๊ทธ๋์ ์ตํ๋ TDD, OOP, ํด๋ฆฐ์ฝ๋๋ฅผ ํตํด ๋ ๊ฑฐ์ ์ฝ๋๋ฅผ ์คํธ๋ญ๊ธ๋ฌ ํจํด์ผ๋ก ๋ฆฌํฉํฐ๋ง ํ๋ ๋ฐฉ๋ฒ์ ํ์ตํ ์ ์์๋ค.
์ ๋ฆฌ
ํ์ฌ ์ ๋ฌด์ ํ์ฌ ์งํํ๊ณ ์๋ ๋์๋ฆฌ์ธ ๋ํ๋ง๊น์ง ๊ฐ์ด ๋ณํํด์ผ ํ๊ธฐ์ ๋ฏธ์ ๊ธฐ๊ฐ์ธ ๋ ๋ฌ ๋์ ๋งค์ฐ ๋ฐ์๊ฒ ์ด์๋ ๊ฒ ๊ฐ๋ค. ๋ฉํ ๋ค๋ ํ์ง์์ด๊ธฐ์ ํ๋ฃจ์ ํ ๋ฒ PR ๋ฆฌ๋ทฐ๋ฅผ ์งํํด ์ฃผ์๊ณ , ๊ทธ๋ ๊ธฐ์ ํ๋์ PR์ 2~3๋ฒ์ ๋ฆฌ๋ทฐ๊ฐ ์ค๊ฐ๋ค๊ณ ๊ฐ์ ํ๋ฉด ์ฌ์ค์ ๊ฑฐ์ ์ฌ๋ ๋ ์์ด PR์ ์ฌ๋ฆฌ๊ณ , ์์ ํ๊ณ ์ฌ PR ํ๊ณ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์งํํด์ผ ์๋ฃํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ฌํํผ ๋ญ ๋ฐค์ ์ ์ค์ฌ ๋ ๋ฌ ๋์ ๋งค์ผ 6์๊ฐ ๋ฏธ๋ง์ผ๋ก ์ ์ ์๋ฉฐ ์ฌ์์ ์ฐจ ๊ณผ์ ์ ์๋ฃํ๋ค.
TDD, Clean Code with Java ๊ณผ์ ์ ํตํด ๋์ ์ฝ๋ฉ ์คํ์ผ์ด ์ด์ ๊ณผ๋ ํ์ฐํ๊ฒ ๋ฌ๋ผ์ก๊ณ , ๋งค์ฐ ๊ฐ์ ๋์๋ค๊ณ ์๊ฐํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐฐ์ด ์ ์ ํ ๋๋ก ์ฝ๋์์ฑ๊ณผ ๋ค๋ฅธ ์ฌ๋์ ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ๋์ฑ๋ ์์ ๊ฐ ์๊ฒ ํ ์ ์๊ฒ ๋์๋ค๊ณ ์๊ฐํ๋ค. ํน์๋ ๋๊ตฐ๊ฐ ๋์๊ฒ ์ด ๊ฐ์๊ฐ ์ด๋ป๋๊ณ ๋ฌผ์ด๋ณธ๋ค๋ฉด 1~3๋ ์ฐจ์ ๊ฐ๋ฐ์๋ผ๋ฉด ํ ๋ฒ์ฏค์ ๊ผญ ์๊ฐํด ๋ณด๋ผ๊ณ ๊ถํ๊ณ ์ถ๋ค.