다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.
컴포넌트의 계약을 기술하기
델리게이트를 사용하여 컴포넌트의 계약을 기술하면 클라이언트 측에서 코드를 사용하기가 쉬워진다.
다른 개발자가 사용할 코드를 작성하는 경우 의존성 문제를 코드에서 분리하는 것은 상당히 까다롭다.
첫번째방법 : 상속
- 추상 베이스 클래스를 작성하여 이를 상속하는 방식
- 장점
최종 사용자가 컴포넌트를 매우 쉽게 사용할 수 있는 장점이 있다.
- 단점
베이스 클래스가 필요로 하는 구성요소를 파생 클래스에서 작성하도록 강요하기 때문에 제약이 크다는 것.
두번째방법 : 인터페이스
- 인터페이스를 작성하고 이를 구현하도록 하는 방식
- 장점
클래스의 계층구조를 강제하지 않으며, 느슨한 결합을 얻을 수 있다는 장점이 있다.
- 단점
재사용 가능 코드를 제공하기 어렵다.
단지 특정 메서드를 하나 사용하기 위해서 인터페이스를 구현하기 위해서 추가 작업을 하는 것은 적절하지 않다.
세번째 방법 : 함수를 매개변수로 취하는 델리게이트
이때 함수를 매개변수로 사용하면 사용하는 측과 구현하는 측의 코드를 분리할 수 있다.
단점은 코드의 복잡도가 올라가고 비용도 증가하게 된다.
다음은 앞서 살펴본 2개의 시퀀스를 결합하는 Zip 메서드이다.
public static IEnumerable<string> Zip(IEnumerable<string> first, IEnumerable<string> second)
{
using(var firstSequence = first.GetEnumerator())
{
using(var secondSequence = second.GetEnumerator())
{
while(firstSequence.MoveNext() && secondSequence.MoveNext())
yield return $"{firstSequence.Current} {secondSequence.Current}";
}
}
}
이 메서드를 조금 수정하여 함수를 매개변수로 받게 개선할 수 있다.
public static IEnumerable<TResult> Zip<T1, T2, TResult>(
IEnumerable<T1> first,
IEnumerable<T2> second,
Func<T1, T2, TResult> zipper)
{
using (var firstSequence = first.GetEnumerator())
{
using (var secondSequence = second.GetEnumerator())
{
while (firstSequence.MoveNext() && secondSequence.MoveNext())
yield return zipper(firstSequence.Current, secondSequence.Current);
}
}
}
사용하는 측에서는 다음과 같이 람다식을 사용할 수 있다.
List<int> first = new List<int>() { 0, 1, 2, 3 };
List<string> second = new List<string>() { "A", "B", "C", "D" };
var result = Zip(first, second, (one, two) => $"{one} {two}");
하지만 이렇게 결합도를 느슨하게 구성하려면 오류를 처리하기 위해서 추가적인 작업이 필요하다.
이벤트를 발생시킬 때 해당 이벤트가 null인지 확인해야하고,
델리게이트가 null 인경우 이를 위해 기본동작을 마련해야할지 등 여러 생각할 거리가 생긴다.
결론
- 예측가능한 수준에서 델리게이트를 잘 사용한다면 명시성은 조금 희생하는 대신 유연성을 취할 수 있을 것이다.
'🌍 C# Study > 이펙티브 C#' 카테고리의 다른 글
[36] 쿼리 표현식과 메서드 호출 구문이 어떻게 대응되는지 이해하라 (0) | 2021.05.02 |
---|---|
[35] 확장 메서드는 절대 오버로드하지 마라 (0) | 2021.04.30 |
[33] 필요한 시점에 필요한 요소를 생성하라 (0) | 2021.04.30 |
[32] Action, Predicate, Function과 순회 방식을 분리하라 (0) | 2021.04.30 |
[31] 시퀀스에 사용할 수 있는 조합 가능한 API를 작성하라 (0) | 2021.04.30 |