코드를 작성하면서 조건문을 작성하는 경우에는 코드가 길어지면서 조건문도 복잡해진다.
if문을 사용하는 경우에는 조건식이 복잡해지거나 부정 연산자가 자주 사용되고 조건식 안에서 2중, 3중으로 작성되면서 가독성이 떨어지는 조건문이 만들어지는 경우도 많다.
switch문을 사용하는 경우에는 case가 늘어나면서 코드가 길어지는 경우 역시 빈번하게 발생한다.
이렇게 복잡한 조건식이 반복되면 코드의 가독성이 떨어지면서 리팩토링이 상당히 어려워지며 새로운 조건이 추가될 때 마다 조건식 전부를 뜯어 고치거나 더욱 복잡한 조건식이 탄생해버린다.
이런 경우에는 아래의 단순화 방법을 참고해서 코드를 작성하면 너무 복잡한 조건식이 탄생하는 빈도를 줄일 수 있다.
조건문을 단순화 하는 방법
1. 부정 연산자(!) 줄이기
- 부정 연산자가 많아지는 경우에는 코드가 가독성이 떨어지는 경우가 많음
- 부정 연산자를 사용해서 조건문의 길이가 짧아지면서 간결해지는 경우도 있음
- 조건문이 조금 길더라도 가독성이 올라가는 코드가 리팩토링 측면에서는 좋은 경우도 있으니 잘 판단해서 사용해야 함
// case 1
if (!(temperature < 0 || humidity > 80 || windSpeed > 50))
{
Console.WriteLine("날씨가 좋습니다.");
}
else
{
Console.WriteLine("날씨가 좋지 않습니다.");
}
// case 2
if (temperature >= 0 && humidity <= 80 && windSpeed <= 50)
{
Console.WriteLine("날씨가 좋습니다.");
}
else
{
Console.WriteLine("날씨가 좋지 않습니다.");
}
- case 1과 2 모두 같은 결과물을 얻기 위한 조건식이다.
- 부정 연산자를 제거하고 조건문의 방식을 조금 수정하면 가독성이 올라가는 조건식이 된다.
2. 삼항 연산자 사용
삼항 연산자란?
- 삼항 연산자의 형태는 ("조건식" ? "참일 때의 값" : "거짓일 때의 값") 의 모양으로 이루어진다.
- 간단한 if else문을 한 줄로 줄일 수 있는 간결한 작성법이다.
//case 1
if (score >= 60)
{
result = "Pass";
}
else
{
result = "Fail";
}
//case 2
if (age >= 18)
{
accessLevel = "Adult";
}
else
{
accessLevel = "Minor";
}
위와 같은 시험 문제를 채점하려는 간단한 조건문이나
성인인지 판별하는 조건식의 경우에도 삼항 연산자를 사용하면 한 줄로 작성이 가능하다.
//case 1
result = score >= 60 ? "Pass" : "Fail";
//case 2
accessLevel = age >= 18 ? "Adult" : "Minor";
3. Switch Expression 사용
Switch문의 경우에는 C# 8.0 이상부터 추가된 Switch Expression을 사용하면 break문 없이 간결하게 Switch문을 작성할 수 있다.
//case 1
switch (score)
{
case >= 90:
grade = "A";
break;
case >= 80:
grade = "B";
break;
case >= 70:
grade = "C";
break;
default:
grade = "F";
break;
}
//case 2
switch (day)
{
case 1:
result = "Monday";
break;
case 2:
result = "Tuesday";
break;
default:
result = "???";
break;
}
위와 같이 작성된 단순한 switch문을 Switch Expression을 사용하면 조금 더 짧게 작성할 수 있다.
//case 1
grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
_ => "F"
};
//case 2
result = day switch
{
1 => "Monday",
2 => "Tuesday",
_ => "Unknown"
};
4. 전략 패턴 사용
비즈니스 로직에서 조건문이 사용되어 있는 경우에는 전략 패턴을 사용해서 조건문들을 객체로 분리해서 사용하면 확장이 용이하고 유지 보수가 간단해진다.
public class DiscountCalculator
{
public float CalculateDiscount(Order order)
{
if (order.IsFirstPurchase && order.Amount >= 50000)
{
return order.Amount * 0.2m; // 첫 구매 20% 할인
}
else if (order.CustomerType == CustomerType.VIP && order.Amount >= 100000)
{
return order.Amount * 0.15m; // VIP 15% 할인
}
else if (order.DayOfWeek == DayOfWeek.Wednesday && order.Amount >= 30000)
{
return order.Amount * 0.1m; // 수요일 특별 할인 10%
}
else if (order.IsHoliday && order.Amount >= 20000)
{
return order.Amount * 0.05m; // 공휴일 5% 할인
}
return 0; // 할인 없음
}
}
위와 같이 마트에서 물건을 구입할때 특정 경우에 따라 할인되는 경우가 나타나는 조건문이 있다.
위 조건문을 할인 혜택이 추가될 때 마다 else if를 추가적으로 사용해서 확장하는 방법도 있겠지만
인터페이스를 만들어 전략 패턴을 사용하면 다음과 같은 순서로 클래스가 분리된다.
1. 할인 정책에 관련된 인터페이스를 정의한다.
2. 할인 케이스에 따른 독립된 클래스를 구현한다.
3. 새로운 할인 혜택이 생겨나는 경우에 새로운 클래스만 추가한다.
// 인터페이스 구현
public interface IDiscountStrategy
{
bool IsApplicable(Order order);
float CalculateDiscount(Order order);
}
// 할인쪽 전략 패턴 구현
public class FirstPurchaseDiscountStrategy : IDiscountStrategy
{
public bool IsApplicable(Order order)
=> order.IsFirstPurchase && order.Amount >= 50000;
public float CalculateDiscount(Order order)
=> order.Amount * 0.2m;
}
public class VipDiscountStrategy : IDiscountStrategy
{
public bool IsApplicable(Order order)
=> order.CustomerType == CustomerType.VIP && order.Amount >= 100000;
public float CalculateDiscount(Order order)
=> order.Amount * 0.15m;
}
public class WednesdayDiscountStrategy : IDiscountStrategy
{
public bool IsApplicable(Order order)
=> order.DayOfWeek == DayOfWeek.Wednesday && order.Amount >= 30000;
public float CalculateDiscount(Order order)
=> order.Amount * 0.1m;
}
public class HolidayDiscountStrategy : IDiscountStrategy
{
public bool IsApplicable(Order order)
=> order.IsHoliday && order.Amount >= 20000;
public float CalculateDiscount(Order order)
=> order.Amount * 0.05m;
}
코드 자체는 조금 더 길어졌지만 조건이 중첩되는 경우보다 훨씬 코드 확장성과 유지 보수가 용이해진 코드로 바뀐다.
'C#' 카테고리의 다른 글
C# - 이터레이터(Iterator) [반복자] (5) | 2024.10.29 |
---|---|
C# [디자인 패턴] - 팩토리 패턴(Factory Pattern) (1) | 2024.10.24 |
C# [디자인 패턴] - 상태 패턴(State Pattern) (0) | 2024.10.22 |
C# [디자인 패턴] - 옵저버 패턴(Observer Pattern) (2) | 2024.10.04 |
C# - LINQ(Language Integrated Query) (3) | 2024.09.24 |