1. 데드 코드
- 실제로 실행되는 코드가 아니면 제거하자.
2. YAGNI 원칙
- 'You Aren't Gonna Need It.' 의 약자로 '지금 필요 없는 기능을 만들지 말라!'
- 소프트웨어에 대한 요구는 매일매일 변한다.
미리 예측하고 구현해도, 이러한 예측은 대부분 맞지 않다.
예측에 들어맞이 않는 로직은 데드 코드가 된다.
3. 매직 넘버
class ComicManager{
//생략
boolean isOk(){
return 60 <= value;
}
}
- 설명이 없는 숫자는 개발자를 혼란스럽게 만든다.
class ComicManager{
/** 체험 구독 소비 포인트 */
private static final int TRIAL_READING_POINT = 60;
// 생략
boolean isOk(){
return TRIAL_READING_POINT <= value;
}
}
- 상수로 만들어서 이해하기 쉽게 만들자.
4. 문자열 자료형에 대한 집착
// 레이블 문자열, 표시 색(RGB), 최대 문자 수
String title = "타이틀,255,250,240,64";
- 읽어 들인 CSV 파일에서 데이터를 추출할 때 split 메서드를 사용하는 경우가 있다.
- 하지만, 그 용도가 아닌데 의미가 여러 개의 값을 하나의 String 변수에 무리하게 넣으면 의미를 알기 어렵고 split 메서드 등을 활용해야하므로 로직이 쓸데없이 복잡해진다.
5. 전역 변수
public OrderManager{
public static int currentOrderId;
}
- 모든 곳에서 접근할 수 있는 변수를 전역 변수라고 한다. (public static)
조심해야하는 이유
- 어디에서 어떤 시점에 값을 변경했는지 파악하기 힘들다.
- 전역 변수를 참조하고 있는 로직을 변경해야 할 때, 해당 변수를 참조하는 다른 로직에서 버그가 발생하는 지도 검토해야 한다.
- 동기화 문제가 생기면 데드락 상태에 빠질 수 있다.
6. null 문제
class Member{
private Equipment head;
private Equipment body;
private Equipment arm;
private int defence;
...
}
void takeOffAllEquipments(){
// 장착하지 않은 상태를 null로 초기화
head = null;
body = null;
arm = null;
}
- null이 들어갈 수 있다고 전제하고 로직을 만들면, 모든 곳에서 null 체크를 해야 한다. 결국 null 체크 코드가 너무 많아져서 가독성이 떨어지고, 실수로 null 체크를 안하는 곳이 생기면 버그가 된다.
해결 방법
1) null을 리턴/전달하지 말기
- null을 리턴하지 않는 설계
메서드에서 null을 리턴하지 않게 작성
- null을 전달하지 않는 설계
메서드에서 null을 변수에 할당 하지 않는 것
class Equipment{
static final Equipment EMPTY = new Equipment("장비 없음", 0, 0, 0);
final String name;
final int price;
final int defence;
final int magicDefence;
Equipment(final String name, final int price, final int defence, final magicDefence){
this.name = name;
this.price = price;
this.defence = defence;
this.magicDefence = magicDefence;
}
}
void takeOffAllEquipments(){
// 방어구를 해제하는 경우도 EMPTY를 할당해 기본형으로 초기화하기
head = Equipment.EMPTY;
body = Equipment.EMPTY;
arm = Equipment.EMPTY;
}
2) null 안전
- null 안전이란 null에 의한 오류가 아예 발생하지 않게 만드는 구조이다.
- 코틀린은 기본적으로 모든 자료형에 null 안전 자료형을 사용한다.
7. 예외를 catch하고서 무시하는 코드
try{
reservation.add(product);
}catch(Exception e){
}
- catch를 구현해 놓고 사용하지 않을 경우, 오류가 나도 오류를 탐지할 방법이 없다.
- 최소한의 로그를 기록하고 상위 레이어의 클래스로 오류를 통지하는 것이 좋다.
8. 설계 질서를 파괴하는 메타 프로그래밍
- 리플렉션으로 인한 클래스 구조와 값 변경 문제
class Level {
private static final int MIN = 1;
private static final int MAX = 99;
final int value;
private Level(final int value){
if(value < MIN || MAX < value){
throw new IllegalArgumentException();
}
this.value = value;
}
//초기 레벨 리턴
static Level initialize(){
return new Level(MIN);
}
}
- 변수 value에는 final 수식자가 붙어 있으므로 이후에 변경할 수 없고, 상수 MIN/MAX와 가드를 활용해서, 레벨은 1~99범위 내에서만 지정할 수 있게 했다.
하지만, 리플렉션을 사용해 불변 변수인 value의 값이 바뀌어 버린다. 게다가 MIN/MAX의 범위를 넘어 999가 됬다.
Level level = Level.initialize();
Field field = Level.class.getDeclaredField("value");
field.setAccessible(true);
field.setInt(level, 999);
9. 기술 중심 패키징
- 구조에 따라 폴더와 패키지를 나누는 것이 기술 중심 패키징
- 레일스, 장고(Django), 스프링(Spring) MVC 아키텍처 구조(model, views, controllers) : 기술 중심 패키징
- 비즈니스 클래스는 관련된 비즈니스 개념을 기준으로 폴더를 구분
예)
재고
- 재고_유스케이스.java
- 발주_엔티티.java
- 입고_엔티티.java
...
주문
- 주문_유스케이스.java
- 장바구니_엔티티.java
- 주문_엔티티.java
...
10. 샘플 코드 복사해서 붙여넣기
- 샘플 코드는 어디까지나 참고만 하고, 클래스 구조를 잘 설계해서 사용하기
11. 은 탄환
- 서양에서 늑대 인간과 악마는 은으로 만들어진 총알로 죽일 수 있다고 알려져 있다. 그래서 어떤 문제를 해결하는 비장의 무기, 묘책을 '은 탄환'이라고 부른다.
그래서 어떤 문제를 해결하는 비장의 무기, 묘책을 '은 탄환'이라고 부른다.
하지만 소프트웨어 개발에는 은 탄환이 없다.
- 현실에서 발생하는 여러 문제는 특정 기술 하나로 해결할 수 있을 정도로 단순하지 않다. 문제와 목적을 머릿 속에 새겨 두고, 적절한 기술을 선택할 수 있도록 노력하자.
'일상 > 레벨업 독서' 카테고리의 다른 글
[내 코드가 그렇게 이상한가요?] 11장 주석:유지 보수와 변경의 정확성을 높이는 주석 작성 방법 (0) | 2024.11.14 |
---|---|
[내 코드가 그렇게 이상한가요?] 10장 이름 설계:구조를 파악할 수 있는 이름 (3) | 2024.11.14 |
[내 코드가 그렇게 이상한가요?] 8장 강한 결합: 복잡하게 얽혀서 풀 수 없는 구조 (1) | 2024.10.27 |
[내 코드가 그렇게 이상한가요?] 7장-컬렉션:중첩을 제거하는 구조화 테크닉 (0) | 2024.08.28 |
[내 코드가 그렇게 이상한가요?] 6장-조건 분기 : 미궁처럼 복잡한 분기 처리를 무너뜨리는 방법 (0) | 2024.07.16 |