내 코드가 그렇게 이상한가요? - 1장, 2장 정리

dev_hyun·2023년 12월 22일
2
post-thumbnail

'내 코드가 그렇게 이상한가요?' 개발 서적을 읽고 정리합니다.
책의 코드가 전부 JAVA 로 구성되어 있기 때문에 Typescript 를 사용해서 변경하여 정리하였습니다. 프론트엔드에서도 사용가능한 지식이 충분히 잘 담겨있는 설계 책이라 선택하였고, 차근 차근 정리해나가고자 합니다.

1장 잘못된 구조의 문제 깨닫기

1. 의미를 알 수 없는 이름

  • 기술 중심 명명, 일련번호 명명은 사용하지 말자

2. 조건 분기 중첩은 코드를 읽고 이해하기 힘들게 만든다.

if (조건) {
   if(조건) {
      if(조건) {
      } 
   }

// 매우 많은 코드
}

3. 데이터 클래스의 사용은 수많은 버그를 만든다.

  • 데이터 클래스란 데이터를 가지고만 있는 클래스
  • 데이터 클래스가 일으키는 문제점들
    • 코드 중복
    • 수정 누락
    • 가독성 저하
    • 초기화되지 않는 상태
    • 잘못된 값 할당

2장 설계 첫걸음

1. 의도를 분명히 전달할 수 있는 이름 설계하기

변수의 이름은 코드의 의도에 맞는 이름을 붙여 읽고 이해하기 쉽게 만들도록 한다.

// BAD
int d = 0;
d = p1 + p2;
d = d - ((d1 + d2) /2);
if (d < 0) {
   d = 0;
}

// GOOD
int damageAmount = 0;
damageAmount = playerArmPower + playerWeaponPower;
damageAmount = damageAmount - ((enemyBodyDefence + enemyArmorDefence) / 2);

if(damageAmount < 0) {
   damageAmount = 0;
}
// BAD
let d = 0;
d = p1 + p2;
d = d - ((d1 + d2) /2);
if (d < 0) {
   d = 0;
}

// GOOD
let damageAmount = 0;
damageAmount = playerArmPower + playerWeaponPower;
damageAmount = damageAmount - ((enemyBodyDefence + enemyArmorDefence) / 2);

if(damageAmount < 0) {
   damageAmount = 0;
}

2. 목적별로 변수를 따로 만들어 사용하기

위 코드에서는 damageAmount 라는 변수에 여러번 재할당해서 사용되는 코드가 존재한다.

이를 목적에 맞는 변수를 선언해 코드를 변경할 수 있다.

int totalPlayerAttackPower = playerArmPower + playerWeaponPower;
int totalEnemyDefence = enemyBodyDefecne + enemyArmorDefence;

int damageAmount = totalPlayerAttackPower - (totalEnemyDefence / 2);

if(damageAmount < 0) {
   damageAmount = 0;
}
const totalPlayerAttackPower = playerArmPower + playerWeaponPower;
const totalEnemyDefence = enemyBodyDefecne + enemyArmorDefence;

const damageAmount = totalPlayerAttackPower - (totalEnemyDefence / 2);

if(damageAmount < 0) {
   damageAmount = 0;
}

3. 단순 나열이 아니라, 의미 있는 것을 모아 메서드로 만들기

일련의 흐름으로 나열해서 로직을 작성하는 것이 아니라 의미 있는 로직을 메서드로 만들어서 사용하면 더 좋은 코드로 구현이 가능하다.

int sumUpPlayerAttackPower(int playerArmPower, int playerWeaponPower) {
   return playerArmPower + playerWeaponPower;
}
int sumUpEnemyDefence(int enemyBodyDefence, int enemyArmorDefecne) {
   return enemyBodyDefecne + enemyArmorDefence;
}
int estimateDamage(int totalPlayerAttackPower, int totalEnemyDefence) {
   int damageAmount = totalPlayerAttackPower - (totalEnemyDefence / 2);
   if(damageAmount < 0) {
     damageAmount = 0;
   }
   return damageAmount;
}

// 사용하는 코드
int totalPlayerAttackPower = sumUpPlayerAttackPower(playerArmPower, playerWeaponPower);
int totalEnemyDefence = sumUpEnemyDefence(enemyBodyDefecne, enemyArmorDefence);
int damageAmount = estimateDamage(totalPlayerAttackPower, totalEnemyDefence);
function sumUpPlayerAttackPower(playerArmPower: number, int playerWeaponPower: number) {
   return playerArmPower + playerWeaponPower;
}
function sumUpEnemyDefence(enemyBodyDefence: number, enemyArmorDefecne: number) {
   return enemyBodyDefecne + enemyArmorDefence;
}
function estimateDamage(totalPlayerAttackPower: number, totalEnemyDefence: number) {
   const damageAmount = totalPlayerAttackPower - (totalEnemyDefence / 2);
   if(damageAmount < 0) {
     damageAmount = 0;
   }
   return damageAmount;
}

// 사용하는 코드
const totalPlayerAttackPower = sumUpPlayerAttackPower(playerArmPower, playerWeaponPower);
const totalEnemyDefence = sumUpEnemyDefence(enemyBodyDefecne, enemyArmorDefence);
const damageAmount = estimateDamage(totalPlayerAttackPower, totalEnemyDefence);

4. 관련된 데이터와 로직을 클래스로 모으기

서로 밀접한 데이터와 로직을 한곳에 모아서 관리하면 유지보수도 쉬워지고 코드를 이해하기도 좋다.

class HitPoint {
  private static readonly MIN = 0;
  private static readonly MAX = 999;
  private value: number;

  constructor(value: number) {
     if(value < HitPoint.MIN) throw new Error(HitPoint.MIN + " 이상을 지정해주세요.");
     if(HitPoint.MAX < value) throw new Error(HitPoint.MAX + " 이하를 지정해주세요.");
	 this.value = value;
  }

  private damage(damageAmount: number) {
     const damaged = this.value - damageAmount;
     const corrected = damaged < HitPoint.MIN ? HitPoint.MIN : damaged;
     return new HitPoint(corrected);  
	}

  private recover(recoveryAmount: number) {
      const recovered = this.value + recoveryAmount;
      const corrected = HitPoint.MAX < recovered ? HitPoint.MAX : recovered;
      return new HitPoint(corrected);
  }
}

예제 코드

profile
하다보면 안되는 것이 없다고 생각하는 3년차 프론트엔드 개발자입니다.

0개의 댓글