2021
04.30

다음 본문은 도서 이펙티브 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 인경우 이를 위해 기본동작을 마련해야할지 등 여러 생각할 거리가 생긴다.

 

결론

 - 예측가능한 수준에서 델리게이트를 잘 사용한다면 명시성은 조금 희생하는 대신 유연성을 취할 수 있을 것이다.

 

 

COMMENT