1) 클래스는 클래스 하나로도 잘 동작할 수 있도록 설계해야 합니다. 또한 복잡한 초기 설정을 하지 않아도 곧바로 사용할 수 있게 해야합니다.
모든 클래스는 자기방어 임무가 있습니다. 다른 클래스를 사용하여 초기화하거나 유효성 검사를 해야하는 클래스는 그 자체로는 안전하게 사용할 수 없는 미성숙한 클래스 입니다.
올바른 예
Class Money {
final int amount;
final Currency currency;
Money(int amount, Currency) {
if (amount < 0) {
throw new IllegalArgumentException("금액은 0 이상의 값을 지정해 주세요.");
}
if (currency == null) {
throw new NullPointerException("통화 단위를 지정해 주세요.");
}
this.amount = amount;
this.currency = currency;
}
}
final을 통하여 불변으로 만들고, 파라미터 유효성 검증을 스스로 해낼 수 있는 Class를 만들었습니다.
불변인 변수를 사용한 경우 해당 변수의 내용을 변경코자 한다면 변경된 값을 가진 새로운 인스턴스를 만들어서 사용하면 됩니다. 그리고 추가로 Money 자료형만을 매개변수로 받도록 설계하여 의미가 다른 값을 전달할 경우 컴파일 오류가 발생하므로 더 튼튼합니다. (기본 자료형 위주로 사용하면, 의미가 다른 값이 여러개 있어도 모두 int자료형이나 String 자료형으로 정의하게 쉽습니다. 따라서 실수로 의미가 다른 값을 전달하기 쉽습니다.
올바른 예
class Money {
// 생략
Money add (final Money other) {
final int added = amount + other.amount;
return new Money(added, currency);
}
}
즉 클래스 설계는 인스턴스 변수가 잘못된 상태에 빠지지 않게 하기 위한 구조를 만드는것 이라고 해도 과언이 아닙니다.
2) 변수에 값을 다시 할당하는 것을 재할당이라고 합니다.
잘못된 예
int damage() {
int tmp = member.power() + member.weaponAttack();
tmp = (int)(tmp * (if + member.speed() / 100f));
tmp = tmp - (int)(enemy.defence / 2);
tmp = Math.max(0, tmp);
return tmp
}
이때는 불변 변수를 사용하면 좋습니다.
올바른 예
int damage() {
final int basicAttackPower = member.power() + member.weaponAttack();
final int finalAttackPower = (int)(basicAttackPower * (if + member.speed() / 100f));
final int reduction = (int)(enemy.defence / 2);
final int damage = Math.max(0, finalAttackPower - reduction);
return damage;
}
인스턴스를 그대로 재사용하여 문제가 발생하는 경우도 있습니다.
잘못된 예
AttackPower attackPower = new AttackPower(20);
Weapon weaponA = new Weapon(attackPower);
Weapon weaponB = new Weapon(attackPower);
weaponA.attackPower.value = 25;
System.out.println("Weapon A attack power : " + weaponA.attackPower.value);
System.out.println("Weapon B attack power : " + weaponB.attackPower.value);
인스턴스를 재사용하지 못하게 만들면 됩니다.
올바른 예
AttackPower attackPowerA = new AttackPower(20);
AttackPower attackPowerB = new AttackPower(20);
Weapon weaponA = new Weapon(attackPowerA);
Weapon weaponB = new Weapon(attackPowerB);
...
3) 불변과 가변은 어떻게 다루어야 할까?
기본적으로 불변으로 만들면 다음과 같은 장점이 있습니다.
- 변수의 의미가 변하지 않으므로 혼란을 줄일 수 있음
- 동작이 안정적이게 되므로, 결과를 예측하기 쉬움
- 코드의 영향 범위가 한정적이므로, 유지보수 편리해짐
가변으로 설계해야 하는 경우는
불변으로 값을 변경할때 새로운 인스턴스를 생성하는데, 이때의 인스턴스 크기가 큰 것을 새로 생성한다면 오래걸려 성능에 문제가 생길 수 있습니다.
'Programming > 기타' 카테고리의 다른 글
코드 품질올리기, 코드 설계 - 3 성숙한 클래스 만들기 (3/3) (0) | 2023.08.30 |
---|---|
코드 품질올리기, 코드 설계 - 3 성숙한 클래스 만들기 (2/3) (0) | 2023.08.30 |
코드 품질올리기, 코드 설계 - 2 분기중접 줄이기 (3/3) (0) | 2023.08.28 |
코드 품질올리기, 코드 설계 - 2 분기중접 줄이기 (2/3) (0) | 2023.08.28 |
코드 품질올리기, 코드 설계 - 2 분기중접 줄이기 (1/3) (0) | 2023.08.28 |