๊ฐ๋ฐ์ ๊ธ์ง๊ธฐ์ ๋น์ทํ๋ค.
๋จผ์ ์๊ฐ์ ๊ธฐ๋กํ ํ ์ฝ๊ธฐ ์ข๊ฒ ๋ค๋ฌ๋ ๊ณผ์ ์ด ์งํ๋๋ค.
ํจ์๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
๋จผ์ ๋ก์ง์ ๋์ดํ๊ฒ ์ถํ์ ๋ฆฌํฉํ ๋ง์ด ์งํ๋๋ค.
์ค๋์ ๊ตฌ์กฐ์ ์ผ๋ก๋ ์ข์ผ๋ฉฐ ์ฝ๊ธฐ ์ข์ ํจ์๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๊ฒ ๋ค.
์๊ฒ ๋ง๋ค๊ธฐ
์ข์ ํจ์ ๊ตฌ์กฐ๋ ๋๊ฐ ์๊ฒ ๊ตฌํํ๋๊ฒ ์ข๋ค.
๊ฐ ํจ์๊ฐ ํ๋์ ์ด์ผ๊ธฐ๋ฅผ ํํํ๋๊ฒ ์ข๋ค.
๋ณดํต ์๋์ ๊ฐ์ ํจ์์ ๊ธธ์ด ์ ๋๊ฐ ์ ํฉํ๋ค๊ณ ํ๋ค.
public static String renderPageWithSetupsAndTeardowns(
PageData pageData, boolean isSuite) throws Exception {
if (isTestPage(pageData))
includeSetupdAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}
๋ฐ๊นฅ์ ๊ฐ์ธ๋ ํจ์๊ฐ ์์์ง์๋ก ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ฌ์์ง๋ค.
ํ ๊ฐ์ง๋ง ํ๊ธฐ
ํจ์๋ ํ ๊ฐ์ง์ ํ๋๋ง ์ ํ๋ฉด ๋๋ค.
SOLID ์์น ์ค '๋จ์ผ ์ฑ ์ ์์น'๊ณผ ๋น์ทํ ๋งฅ๋ฝ์ด๋ค.
ํจ์๊ฐ ํ ๊ฐ์ง๋ง ํ๋์ง ํ๋จํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋,
ํจ์ ๋ด ๋ก์ง ์ค ๋จ์ํ ๋ค๋ฅธ ํํ์ด ์๋ ์๋ฏธ ์๋ ์ด๋ฆ์ผ๋ก ๋ค๋ฅธ ํจ์๋ฅผ ์ถ์ถํ ์ ์์ด์ผ ํ๋ค.
ํจ์๋น ์ถ์ํ ์์ค์ ์์ค์ ํ๋๋ก
ํจ์ ๋ด ๋ชจ๋ ๋ฌธ์ฅ์ ์ถ์ํ ์์ค์ด ๋์ผํด์ผ ํ๋ค.
์๋ฅผ ๋ค์ด ์๋ ์ฝ๋๋ฅผ ๋ณด์.
public void registerUser(String username, String email, String password) {
// ๊ณ ์์ค ์์
: ์ฌ์ฉ์ ๋ฑ๋ก ๋ก์ง
if (isValidEmail(email)) {
// ์ค๊ฐ ์์ค ์์
: ๋น๋ฐ๋ฒํธ ํด์ฑ
String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
// ์ ์์ค ์์
: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ฐ ์ฟผ๋ฆฌ ์คํ
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "user", "pass");
PreparedStatement stmt = conn.prepareStatement("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
stmt.setString(1, username);
stmt.setString(2, email);
stmt.setString(3, hashedPassword);
stmt.executeUpdate();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
throw new InvalidEmailException("Invalid email address");
}
}
private boolean isValidEmail(String email) {
return email.contains("@");
}
isValidEmail()์ ๋์ ์์ค์ผ๋ก ์ถ์ํ ๋์ด์๊ณ ,
Bcrypt.haspw()๋ ์ค๊ฐ ์์ค,
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ฐ ์ฟผ๋ฆฌ ์คํ์ ๋ฎ์ ์์ค์ด๋ค.
์ด๋ ๊ฒ ํจ์ ๋ด์ ๊ฐ ์ฝ๋๋ค์ ์ถ์ํ ์์ค์ด ์ ๊ฐ๊ฐ์ด๋ผ๋ฉด ์ฝ๋๋ฅผ ์ฝ๋ ์ฌ๋์๊ฒ ํผ๋์ ์ค ์ ์๋ค.
public void registerUser(String username, String email, String password)
throws InvalidEmailException, UserRegistrationException {
if (!emailValidator.isValid(email)) {
throw new InvalidEmailException("Invalid email address");
}
try {
String hashedPassword = passwordEncoder.encode(password);
User user = new User(username, email, hashedPassword);
userRepository.save(user);
} catch (Exception e) {
throw new UserRegistrationException("Failed to register user", e);
}
}
์์ ๊ฐ์ด ํจ์ ๋ด์ ์ถ์ํ ์์ค์ ๋๋ฑํ๊ฒ ๋ง์ถ๋๊ฒ ์ฝ๋ ์ฌ๋์๊ฒ ์ข์ ์ฝ๋์ด๋ค.
swtich๋ฌธ
switch๋ฌธ์ ํน์ฑ์ ์๊ฒ ๋ง๋ค๊ธฐ๋, ํ ๊ฐ์ง ์์ ์ ํ๊ฒ ๋ง๋ค๊ธฐ๋ ์ด๋ ต๋ค.
๋ฐ๋ผ์, ๊ฐ switch๋ฌธ์ ์ ์ฐจ์ ํด๋์ค์ ์จ๊ธฐ๊ณ ๋ฐ๋ณตํ์ง ์๋ ๋ฐฉ๋ฒ์ผ๋ก ๋คํ์ฑ(Polymorphism)์ ์ด์ฉํ ์ ์๋ค.
public class AnimalSoundSystem {
public static void main(String[] args) {
String[] animals = {"๊ฐ", "๊ณ ์์ด", "์", "๊ฐ"};
for (String animalType : animals) {
Animal animal = AnimalFactory.createAnimal(animalType);
System.out.println(animalType + "์ ์๋ฆฌ: " + animal.makeSound());
}
}
}
class AnimalFactory {
public static Animal createAnimal(String animalType) {
switch (animalType.toLowerCase()) {
case "๊ฐ":
return new Dog();
case "๊ณ ์์ด":
return new Cat();
case "์":
return new Cow();
default:
throw new IllegalArgumentException("์ ์ ์๋ ๋๋ฌผ ์ข
๋ฅ: " + animalType);
}
}
}
switch๋ฌธ์ ๊ตฌํํ ์ถ์ ํฉํ ๋ฆฌ๋ฅผ ์ด์ฉํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
ํ์ง๋ง switch๋ฌธ์ ๋ถ๊ฐํผํ๊ฒ ์ข์ง ์์ ๊ฒฝ์ฐ๋ก ๋ง๋ค๊ฒ ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ ๊ฒ ๊ฐ๋ค. ๋๋๋ก์ด๋ฉด ์ฐ์ง ์๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค.
์์ ์ ์ธ ์ด๋ฆ์ ์ฌ์ฉ
"์ฝ๋๋ฅผ ์ฝ์ผ๋ฉด์ ์ง์ํ๋ ๊ธฐ๋ฅ์ ๊ฐ ๋ฃจํด์ด ๊ทธ๋๋ก ์ํํ๋ค๋ฉด ๊นจ๋ํ ์ฝ๋๋ผ ๋ถ๋ฌ๋ ๋๊ฒ ๋ค."
ํจ์ ์ด๋ฆ์ด ์๋ฌด๋ฆฌ ๊ธธ๋๋ผ๋ ์ฃผ์ ๋์ ๊ธด ์์ ์ ์ธ ์ด๋ฆ์ ์ฌ์ฉํ๋๊ฒ ํจ์ฌ ์ข๋ค.
์์ ์ ์ธ ์ด๋ฆ์ ์ฌ์ฉํ๋ค๋ฉด ์ค๊ณ๊ฐ ๋๋ ทํด์ง๋ ํจ๊ณผ๋ ์๋ค.
ํจ์ ์ธ์
ํจ์์ ์ด์์ ์ธ ์ธ์์ ๊ฐ์๋ 0๊ฐ(๋ฌดํญ) > 1๊ฐ(๋จํญ) > 2๊ฐ(์ดํญ) > 3๊ฐ(์ผํญ) > 4๊ฐ ์ด์(๋คํญ)
์์ผ๋ก, ์ ์์๋ก ์ข๋ค.
4๊ฐ ์ด์(๋คํญ)์ ์ฌ๋งํ๋ฉด ์ฌ์ฉํ์ง ์๋ ํธ์ด ์ข๋ค. ์ธ์๋ ๊ฐ๋ ์ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ด๋ค.
ํ๋๊ทธ ์ธ์
์ผ๋ฐ์ ์ผ๋ก ํ๋๊ทธ ์ธ์๋ ์ข์ง ์๋ค.
ํนํ bool ๊ฐ์ ๋๊ธฐ๋ ๊ฒ์ bool ๊ฐ์ ๋ฐ๋ผ ํจ์๊ฐ ํ๊ฑฐ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๋ฅผ ์ฒ๋ฆฌํ๋ค๋ ๊ฒ์ ์์ํ๊ธฐ ๋๋ฌธ์ ์ข์ง ์๋ค.
void render(boolean isSuite)
์ ํจ์๋ณด๋จ
void rednerForSuite()
void renderForSingleTest()
์ ํจ์๋ก ๋๋์ด์ ์คํํ๋๊ฒ ๋ ์ข๋ค.
๋จํญ ํจ์
๋จํญ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ํฌ๊ฒ ์ธ ๊ฐ์ง์ด๋ค.
1. ์ธ์์๊ฒ ์ง๋ฌธ์ ๋์ง๋ ๊ฒฝ์ฐ
boolean isUserValid(User user){}
2. ์ธ์๋ฅผ ํตํด ๋ณํํ๋ ๊ฒฝ์ฐ
UserResponseDto userResponseDto = UserResponseDto.from(user);
3.์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
applicationEventPublisher.publishEvent(event);
์ ์ธ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด ๊ฐ๊ธ์ ๋จํญ ํจ์๋ฅผ ํผํ๋๊ฒ ์ข๋ค.
๋ํ ๋ณํ ํจ์์์ ์ถ๋ ฅ ์ธ์๋ฅผ ์ฌ์ฉํ๋ฉด ํผ๋์ ์ผ์ผํจ๋ค.
์ดํญ ํจ์
์ธ์๊ฐ 2๊ฐ์ธ ํจ์๋ 1๊ฐ์ธ ํจ์๋ณด๋ค ์ดํดํ๊ธฐ ์ด๋ ต๋ค.
user.setName("ํ๊ธธ๋");
setName(user, "ํ๊ธธ๋);
์๋๋ณด๋จ ์ ํจ์๊ฐ ์ฝ๊ฒ ์ฝํ๊ณ ๋นจ๋ฆฌ ์ดํด๋๋ค.
๋ฌผ๋ก ์ดํญ ํจ์๊ฐ ๋ ์์ฐ์ค๋ฌ์ด ๊ฒฝ์ฐ๋ ์๋ค.
Point p = new Point(0, 0);
๋ํ, ์ธ์๊ฐ 2๊ฐ ์ด์์ด ๋๋ ์๊ฐ๋ถํฐ ๊ทธ ํจ์๋ฅผ ์ฌ์ฉํ ๋ ์ธ์์ ์์๋ฅผ ์ธ์์ ์ผ๋ก ๊ธฐ์ตํด์ผ ํ๋ค.
์๋์ ๊ทธ ์์๊ฐ ์๋ค.
assertEquals(expected, actual)
expected์ actual์ ๊ฐ์ ํด๋์ค์ด๋ค.
expected ์ actual์ ๋ค์ด๊ฐ ๊ฐ์ ์ค์๋ก ๋ฐ๋๋ก ๋ฃ์๋๋ผ๋ ์ปดํ์ผ ์๋ฌ๋ ์ผ์ด๋์ง ์์ ๊ฒ์ด๋ค.
์ธ์ ๊ฐ์ฒด
์ธ์๊ฐ 2~3๊ฐ๊ฐ ํ์ํ๋ค๋ฉด ํด๋์ค๋ก ์ ๋ฌํ๋ ๊ฒ๋ ๊ณ ๋ คํด ๋ณด์์ผ ํ๋ค.
Circle makeCircle(double x, double y, double radius)
Circle makeCircle(Point center, double radius)
๋ถ์ ํจ๊ณผ๋ฅผ ํผํ๊ธฐ
ํจ์์์๋ ์ฝ์ํ ํ ๊ฐ์ง๋ง ์ํํด์ผ ํ๋ค.
ํจ์ ๋ด์์ ์์ํ์ง ๋ชปํ ์์ ์ ์๊ฐ์ ์ธ ๊ฒฐํฉ(temporal coupling)์ด๋ ์์ ์ข ์์ฑ(order dependency)๋ฅผ ์ด๋ํ๋ค.
public UserProfile getUserProfile(String userId) {
UserProfile profile = userProfiles.get(userId);
if (profile != null) {
// ์ฌ์ฉ์ ํ๋กํ ์ ๊ทผ ์๊ฐ ์
๋ฐ์ดํธ
lastAccessTimes.put(userId, LocalDateTime.now());
}
return profile;
}
์ฌ์ฉ์ ํ๋กํ์ ๊ฐ์ ธ์ค๋ ํจ์์ด์ง๋ง, ๋ด๋ถ์ ์ผ๋ก๋ ํ๋กํ ์ ๊ทผ ์๊ฐ ์ ๋ฐ์ดํธ, ์ ๊ทผ ํ์ ์ฆ๊ฐ ๋ฑ ๋ถ์์ ์ธ ํจ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
ํด๋น ์ฝ๋๋ ์ผํ ๋ณด๋ฉด ๋ฌธ์ ๊ฐ ์์ด ๋ณด์ด์ง๋ง, ์์คํ ๊ท๋ชจ๊ฐ ์ปค์ง๊ณ ๋ณต์กํด์ง๋ฉด ์ฌ๋ฌ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ ์ ์๋ค.
public UserProfile getUserProfileAndUpdateAccessTime(String userId)
์์ ๊ฐ์ด ์ด๋ฆ์ผ๋ก๋ถํฐ ํจ์์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์์ธกํ ์ ์์ด์ผ ํ๋ค.
๋ช ๋ น๊ณผ ์กฐํ๋ฅผ ๋ถ๋ฆฌ
ํจ์๋ ํน์ ํ๋์ ๋์ํ๊ฑฐ๋ ์กฐํํ๊ฑฐ๋ ๋ ์ค ํ๋๋ง ์ํํด์ผ ํ๋ค.
if (set("a", "b"))
์ฌ๊ธฐ์ set()์ a๊ฐ b๋ก ์ค์ ๋์ด ์๋์ง ํ์ธํ๋ ํจ์์ธ์ง, a๋ฅผ b๋ก ์ค์ ํ๋ ํจ์์ธ์ง ์ ์ ์๋ค.
๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋ช ๋ น ํจ์์ ์กฐํ ํจ์๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ด๋ค.
if (attributeExists("username")) {
setAttribute("username", "unclebob");
}
๋ฐ๋ณต ํผํ๊ธฐ
public double calculateRectangleArea(double length, double width) {
if (length <= 0 || width <= 0) {
throw new IllegalArgumentException("๊ธธ์ด์ ๋๋น๋ ์์์ฌ์ผ ํฉ๋๋ค.");
}
return length * width;
}
public double calculateCircleArea(double radius) {
if (radius <= 0) {
throw new IllegalArgumentException("๋ฐ์ง๋ฆ์ ์์์ฌ์ผ ํฉ๋๋ค.");
}
return Math.PI * radius * radius;
}
public double calculateTriangleArea(double base, double height) {
if (base <= 0 || height <= 0) {
throw new IllegalArgumentException("๋ฐ๋ณ๊ณผ ๋์ด๋ ์์์ฌ์ผ ํฉ๋๋ค.");
}
return 0.5 * base * height;
}
๋ค๋ชจ, ๋๊ทธ๋ผ๋ฏธ, ์ผ๊ฐํ์ ๊ฒ์ฌํ๋ ์ธ ๊ฐ์ง ํจ์๊ฐ ์๋ค.
๋ํ(Shape)๋ฅผ ๊ฒ์ฌํ๊ธฐ ์ํด ์ธ ํจ์๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๊ฒ ๋๋ฉด์ ๊ณ์ฐํ๋ ๋ก์ง์ด ๊ณ์ ์ค๋ณต๋๊ฒ ๋๋ค.
public double calculateArea(Shape shape) {
return shape.calculateArea();
}
public static void validatePositive(double value, String paramName) {
if (value <= 0) {
throw new IllegalArgumentException(paramName + "์(๋) ์์์ฌ์ผ ํฉ๋๋ค.");
}
}
์์ ๊ฐ์ด validate ํ๋ ํ ํจ์๋ก ๋ง๋ค์ด ํตํฉํ์ฌ ์ค๋ณต์ ์ค์ด๋ ๊ฒ์ด ์ข๋ค.
๊ตฌ์กฐ์ ํ๋ก๊ทธ๋๋ฐ
์์ธ ํ๋ฅด ๋ฐ์ดํฌ์คํธ๋ผ Edsger Dijkstra์ ๊ตฌ์กฐ์ ํ๋ก๊ทธ๋๋ฐ ์์น์ ๋ฐ๋ฅด๋ฉด, ๋ชจ๋ ํจ์์ ํจ์ ๋ด ๋ชจ๋ ๋ธ๋ก์๋ ์ ๊ตฌ์ ์ถ๊ตฌ๊ฐ ํ๋๋ง ์กด์ฌํด์ผ ํ๋ค.
์ฆ, ํจ์์ return๋ฌธ์ ํ๋์ฌ์ผ ํ๊ณ , ๋ฃจํ ๋ด์์ break๋ continue๋ฅผ ์ฌ์ฉํด๋ ์๋๊ณ , goto๋ ์ ๋๋ก ์ฌ์ฉํ๋ฉด ์๋๋ค.
public static int findFirstEvenGreaterThan(int[] numbers, int threshold) {
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] <= threshold) {
continue;
}
if (numbers[i] % 2 == 0) {
return numbers[i];
}
if (i == numbers.length - 1) {
break;
}
}
return -1;
}
์ ํจ์๋ continue, break, ์ฌ๋ฌ return์ ์ฌ์ฉํ๋ ์ต์ ์ ๊ฒฝ์ฐ์ผ๊น?
ํน์ ์๊ณ ๋ฆฌ์ฆ์์ ~~์ธ ๊ฒฝ์ฐ์๋ -1์ ๋ฆฌํด์ธ ๊ฒฝ์ฐ๋ ๋ง์ด ๋ณด์๋ค.
์ ๊ท์น์ ํจ์๊ฐ ์์ฃผ ํด ๋๋ง ์๋นํ ์ด์ต์ ์ ๊ณตํ๋ค.
์์ ํจ์์ผ ๊ฒฝ์ฐ์๋ ๋๋ก๋ ์ /์ถ๊ตฌ ๊ท์น๋ณด๋ค ์๋๋ฅผ ํํํ๊ธฐ ์ฌ์์ง ๋๊ฐ ์๋ค.
์ถ์ฒ
Clean Code: A Handbook of Agile Software Craftsmanship
by Robert C. Martin
'Clean Code' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Clean Code] ์ข์ ๋ค์ด๋ฐ ๋ฐฉ๋ฒ (0) | 2024.08.16 |
---|