조기 리턴
조건을 만족하지 않는 경우 바로 리턴하는 방법이다. 다음은 if문이 여러번 중첩되어 알아보기 힘든 코드 예시이다.
// 살아 있는가
if (member.getHitPoint() > 0) {
// 움직일 수 있는가
if (member.canAct()) {
// 매직포인트가 남아 있는가
if (magic.getCostMagicPoint() <= member.getMagicPoint()) {
member.consumeMagicPoint(magic.getCostMagicPoint());
member.chant(magic);
}
}
}
다음은 조기 리턴으로 개선한 코드이다. 살아있는가?를 죽었는가?로 반전하여 조기리턴할 수 있게 되었다.
if (member.hitPoint <= 0) return;
if (!member.canAct()) return;
if (member.magicPoint <magic.costMagicPoint) return;
member.consumeMagicPoint(magic.costMagicPoint);
member.chant(magic);
switch 조건문은 하나로 모으기
동일한 switch 조건분기를 여러번 작성하는 대신 switch는 한 번만 쓰도록 리팩토링 하는 것이 좋다. 다음은 수정전 코드이다. `magicType`에 의해 이름, 매직 포인트, 어택 파워 등 여러가지가 분기되어야 하는 상황이다. 이 경우에는 만약 `magicType`이 새로 추가되는 경우나 혹은 magicType에 따라 분기처리해야하는 로직이 추가되는 경우 수정해야 하는 코드가 많다.
class MagicManager {
String getName (MagicType magicType) {
String name = "";
switch (magicType) {
case fire:
name "파이어";
break;
case lightning:
name = "라이트닝";
break;
}
return name;
}
int costMagicPoint (MagicType magicType, Member member) {
int magicPoint = 0;
switch (magicType) {
case fire:
magicPoint = 2;
break;
case lightning:
magicPoint = 5;
break;
}
return magicPoint;
}
int attackPower (MagicType magicType, Member member) {
int attackPower = 0;
switch (magicType) {
case fire:
attackPower = 20 + (int)(member.level * 0.5);
break;
case lightning:
attackPower = 20 + (int)(member.agility * 1.5);
break;
}
return attackPower;
}
}
수정한 코드는 다음과 같다. switch 조건문을 하나로 통일했다.
class Magic {
final String name;
final int costMagicPoint;
final int attackPower;
final int costTechnicalPoint;
Magic(final MagicType magicType, final Member member) {
switch (magicType) {
case fire:
name = "파이어";
costMagicPoint =2;
attackPower = 20+ (int)(member.level *0.5);
costTechnicalPoint =0;
break;
case lightning:
name = "라이트닝";
costMagicPoint =5+ (int)(member.level *0.2);
attackPower = 50+ (int)(member.agility * 1.5);
costTechnicalPoint = 5;
break;
default:
throw new IllegalArgumentException();
}
}
}
}
switch를 인터페이스로 대체하기
switch를 하나로 통일시킨다해도 타입의 갯수가 늘어나면 switch문이 비대해질 우려가 있다. 따라서 switch를 인터페이스로 대체하는 것이 바람직하다. 우선 여러가지 `MagicType`을 `Magic`이라는 인터페이스로 묶는다. 모든 MagicType은 이름 조회(`name()`), 소모 매직 포인트 계산(`costMagicPoint()`), 공격 파워 계산(`attackPower()`) 세 가지 분기를 해야하므로 이를 메서드로 정의한다.
interface Magic {
String name();
MagicPoint costMagicPoint();
AttackPower attackPower();
}
그리고 각 MagicType을 인터페이스의 구현체로 정의한다. 다음은 Fire 매직 타입에 대한 Concrete Class이다.
class Fire implements Magic {
private final Member member;
Fire(final Member member) {
this.member =member;
}
public String name() {
return "파이어";
}
public MagicPoint costMagicPoint() {
return new MagicPoint(2);
}
public AttackPower attackPower() {
final int value = 20 + (int)(member.level *0.5);
return new AttackPower(value);
}
public TechnicalPoint costTechnicalPoint()
return new TechnicalPoint(0);
}
}
'디자인패턴 > 내 코드가 그렇게 이상한가요?' 카테고리의 다른 글
for문 내 if문 중첩 없애기 - 내 코드가 그렇게 이상한가요? 7장 요약 (1) (2) | 2025.01.01 |
---|---|
분기문 적게 쓰는 법 - 내 코드가 그렇게 이상한가요? 6장 요약 (2) (0) | 2024.12.31 |
응집도란? - 내 코드가 그렇게 이상한가요? 5장 요약 (0) | 2024.12.24 |
불변과 가변 장단점과 주의할 점 - 내 코드가 그렇게 이상한가요? 4장 요약 (0) | 2024.12.20 |
클래스 설계 원칙 - 내 코드가 그렇게 이상한가요? 3장 요약 (0) | 2024.12.19 |