덕분에 인터페이스 기본 구현에 대한 적절한 용도를 더 잘 알게 된 것 같습니다.
다만, 링크에서 소개된 내용은 인터페이스 구현 코드, 소비 코드를 자유롭게 재작성/빌드가 가능한 경우만 유효할 것 같습니다.
물론 대부분 여기에 해당되지만, 그 모듈이 외부 모듈(다른 업체가 제공한 패키지)이라면, 수정 요청에 대한 대응이 원활하지 않은 경우도 있을 수 있습니다.
FP 는 데이터와 함수를 분리해서 선언하기 때문에, 이러한 제약에서 자유로운 편인데, 이는 소비 코드가 기존 모듈을 변경하지 않고도 형식에 행위를 추가하는 것이 얼마든지 가능하다는 의미가 됩니다.
C#은 FP가 요구하는 데이터 불변성(record), 데이터 형식의 파생, 강력한 형식의 함수(delegate) 를 모두 제공하기 때문에 FP 의 장점도 향유할 수 있습니다.
링크의 예제 중 일부를 FP 로 표현한다면,
namespace Original;
public record CustomerType( // ... );
public record OrderType(//...);
아래는 버전 1입니다.
using Original;
namespace Version1;
public static class Customer
{
public static decimal ComputeLoyaltyDiscount(CustomerType customer)
{
DateTime TwoYearsAgo = DateTime.Now.AddYears(-2);
if ((customer.DateJoined < TwoYearsAgo) && (customer.PreviousOrders.Count() > 10))
{
return 0.10m;
}
return 0;
}
}
아래는 버전1의 소비 코드입니다.
using Version1;
// ...
// Check the discount:
Console.WriteLine($"Current discount: {Customer.ComputeLoyaltyDiscount(c)}");
아래는 버전2입니다.
using Original;
namespace Version2;
public static class Customer
{
public static void SetLoyaltyThresholds(
TimeSpan ago,
int minimumOrders = 10,
decimal percentageDiscount = 0.10m)
{
length = ago;
orderCount = minimumOrders;
discountPercent = percentageDiscount;
}
private static TimeSpan length = new TimeSpan(365 * 2, 0,0,0); // two years
private static int orderCount = 10;
private static decimal discountPercent = 0.10m;
public static decimal ComputeLoyaltyDiscount(CustomerType customer)
{
DateTime start = DateTime.Now - length;
if ((customer.DateJoined < start) && (customer.PreviousOrders.Count() > orderCount))
{
return discountPercent;
}
return 0;
}
}
소비코드
using Version2;
// ...
Customer.SetLoyaltyThresholds(new TimeSpan(30, 0, 0, 0), 1, 0.25m);
Console.WriteLine($"Current discount: {Customer.ComputeLoyaltyDiscount(c)}");
보시다시피, 구모듈의 코드를 수정(과 재빌드)할 필요도 없고, 나중에 작성되는 버전들은 기존 버전들 뿐만 아니라 과거의 소비 코드에도 어떠한 영향을 미치지 않습니다.
뿐만 아니라, 링크의 OOP 코드에 비해서, FP 코드는 간결하고 가독성 측면에서도 크게 달라지는 부분도 없습니다.
특히 주목할 부분은, 링크된 글의 다음 글의
기본 인터페이스 메서드를 사용하여 mixin 형식 만들기 - C# | Microsoft Learn
맨 마지막에 있는 주의 사항에 대한 우려는 FP에는 적용되지 않습니다.
물론, 모든 C# 코드를 FP 스타일로 바꿀 수는 없습니다.
OOP 만의 장점이 특히 부각되는 부분, 예를 들면 서비스 객체의 구현에는 적절하지 않은 것 같습니다.
원글의 프로젝트는 이러한 FP 의 장점을 실험해보기 위한 것인데, 덕분에 그 장점과 단점이 더욱 선명해지는 계기가 된 것 같아 큰 도움이 되었습니다.