태태개발일지 - 객체 지향 생활 체조 원칙
자바 플레이그라운드 with TDD, 클린 코드
항해 플러스 백엔드 코스가 끝난 후. 약 3달간 해보고 싶은 공부에 대해 정리를 해보았다.
1. Java 심화적으로 파고들어서 공부하기
2. 디자인 패턴 공부하기
3. Query Dsl 공부하기
4. JPA 복습하기
5. 스프링 기본원리 공부하기
6. TDD 공부하기
너무 방대해 보이지만, Query Dsl, 스프링 기본원리는 퇴근후, JPA는 출퇴근할때 TDD는 자바 플레이 그라운드로, 디자인 패턴은 책으로 공부할 예정이다.
향후에는 Redis , Kafka, Docker, Index 등등 항해에서 나왔던 내용들을 더 심화로 공부할 예정이고 1~6번에 부족한 부분들은 더 연장해서 공부할 예정이다.
객체지향 생활 체조 원칙
- 책에서 주장하는 9가지의 원칙은 다음과 같다.
1. 한 메서드에 오직 한 단계의 들여쓰기만 한다.
ex)
public void processItems(List<String> items) {
for (String item : items) {
System.out.println(item); // 한 단계의 들여쓰기만 사용
}
}
이게 정확하게 이해가 안될 수 있는데 아래 코드를 보면
public void processItems(List<String> items) {
for (String item : items) {
if (item != null) {
if (item.length() > 0) {
System.out.println(item); // 중첩된 코드 (들여쓰기 3단계)
}
}
}
}
for문안에 if안에 if가 있어서 들여쓰기가 3단계가 된다. 이것을 1단계로 유지하라는 뜻이다.
public void processItems(List<String> items) {
for (String item : items) {
if (item == null || item.length() == 0) {
continue; // 불필요한 중첩을 피하고 한 단계의 들여쓰기만 유지
}
System.out.println(item); // 들여쓰기 한 단계
}
}
2. else 예약어는 쓰지 않는다.
ex)
public String checkPositive(int number) {
if (number > 0) {
return "Positive";
}
return "Not Positive"; // else 대신 바로 return
}
3. 모든 원시 값과 문자열을 포장한다.
ex)
public class Age {
private int value;
public Age(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Age age = new Age(25); // 숫자 25를 포장
조금더 설명을 보태자면, int age = 25라는 값을 쓰면 너무 불명확하기 때문에
Person이란 사람이 age를 쓴다면 위 코드와 같이 Age라는 객체로 감싸서 의미를 더 확실히 주는 것을 뜻한다.
원시 값을 객체로 포장하는 이유
1. 의미 명확성: 값을 표현하는 클래스 이름을 통해 코드의 의미가 명확해진다.
2. 유효성 검사: 값을 포장하면서 생성자에서 유효성 검사를 할 수 있다.
3. 행동을 추가: 포장된 값에 관련된 메서드를 쉽게 추가할 수 있다.
4. 불변성: 값을 불변 객체로 만들어 변하지 않게 할 수 있다.
4. 한 줄에 점을 하나만 찍는다.
ex)
Address address = user.getAddress(); // 점 하나
String city = address.getCity(); // 한 줄에 하나의 점
String city = person.getAddress().getCity().toUpperCase(); // 한 줄에 점을 3번 찍음
아래와 같이 메서드 체인을 여러 번 연결해서 사용하지 말라는 뜻이다.
이유
1. 가독성: 메서드 호출을 분리하면 각 단계에서 어떤 일이 일어나는지 더 쉽게 파악할 수 있어요.
2. 디버깅: 중간 변수에 값을 저장하면, 나중에 문제가 발생했을 때 디버깅하기 쉬워집니다.
3. NullPointerException 방지: 각 메서드 호출에서 반환된 값이 null인지 확인할 수 있는 기회가 생겨서 null 관련 에러를 방지할 수 있어요.
5. 줄여 쓰지 않는다(축약 금지).
ex)
public int calculateTotalPrice(int price, int quantity) {
return price * quantity; // 변수 이름을 축약하지 않음
}
6. 모든 엔티티를 작게 유지한다.
ex)
public class PersonName {
private String firstName;
private String lastName;
public PersonName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
public class User {
private String name;
private String email;
private String password;
// 비밀번호 변경
public void changePassword(String newPassword) {
this.password = newPassword;
}
// 이메일 유효성 검사
public boolean isValidEmail() {
return email.contains("@");
}
// 사용자 정보를 출력
public void printUserInfo() {
System.out.println("Name: " + name + ", Email: " + email);
}
}
클래스나 메서드가 작을수록 더 이해하기 쉽고, 유지보수하기 쉽다는 원칙을 따르는 것이다.
단일 책임 원칙과 연관이있다.
클래스나 메서드가 너무 커지면 여러 기능을 포함하게 되어 복잡성이 증가하고, 유지보수가 어려워진다.
7. 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
ex)
public class Car {
private String model;
private int year;
private String color;
public Car(String model, int year, String color) {
this.model = model;
this.year = year;
this.color = color;
}
}
8. 일급 컬랙션을 쓴다.
ex)
public class Students {
private List<String> students;
public Students(List<String> studentsList) {
this.students = studentsList;
}
public void addStudent(String student) {
students.add(student);
}
}
9. getter/setter/ 프로퍼티를 쓰지않는다.
ex)
public class Person {
public int age;
public Person(int age) {
this.age = age; // getter/setter 없이 직접 접근
}
}
기한을 맞추는 유일한 방법은, 그러니까 빨리 가는 유일한 방법은 언제나 코드를 최대한 깨끗하게 유지하는 습관이다.
-Clean Code - Robert C. Martin