[40] 지연 수행과 즉시 수행을 구분하라

다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.

 

 

명령형 코드(Imperative Code)

 - 어떻게 작업을 수행해야 하는지를 단계별로 세분화하여 기술한다.

 - 필요한 매개변수를 모두 계산한 다음에야 비로소 메서드를 호출한다.

 - 아래의 예시에서는 항상 모든 메서드를 호출하며, 각 메서드의 부수효과는 반드시 한 번씩만 발생한다.

 - 메서드를 호출하고 그 결과를 다른 메서드에 전달한다.

var answer = DoStuff(Method1(), Method2(), Method3());

 

선언적 코드(Declarative Code)

 - 해결석이며 무슨 작업을 해야 하는지를 정의한다.

 - 각 메서드의 수행 결과가 필요한 경우에만 호출된다.

 - 아래의 예시에서는 메서드가 각기 호출될 수도 있고 호출되지 않을 수 있으며, 여러 번 호출될 수도 있다.

 - 델리게이트를 매개변수로 전달한다.

var answer = DoStuff(() => Method1(), () => Method2(), () => Method3());

 

명령적 코드 vs 선언적 코드

호출 시점의 차이가 발생하기 때문에 명령형 코드(즉시 수행)와 선언적 코드(지연 수행)의
두 가지 방식을 섞어서 사용하면 문제를 일으킬 수 있다.

 

데이터와 메서드

같은 맥락으로 데이터와 메서드를 비교해 볼 수 있다.

데이터는 사용하기 전에 반드시 값을 확정하지만, 메서드는 지연 평가가 가능하다.

 

지연 평가로 인한 부수 효과가 발생하지 않는다는 전제로 두 방식 중 선택해야 한다면,

입출력을 위해 사용하는 공간 비용과 출력을 만들기 위한 계산 비용간의 관계를 고려해야 한다.

 

특정 숫자의 약수를 계산하여 구하는 함수가 존재한다고 해보자.

이를 대체하기 위해 사전에 모든 정수의 약수를 저장해둔 테이블을 만들고, 여기서 값을 찾아서 리턴한다면?

데이터 테이블을 유지하기 위한 공간비용이 약수를 계산하는 함수에 비해서 너무나 클 것이다.

 

두 가지 전략 섞어 사용하기

메서드의 효율을 높이기 위해 두 방식을 섞어서 사용해볼 수도 있다.

일례로 캐시를 사용하는 방법이 있다. 캐싱된 값을 반환하는 델리게이트를 넘기는 것이다.

var cache = Method1();
var answer = DoStuff(() => cache, () => Method2(), () => Method3());

 

결론

 - 입력 데이터가 크지 않다면 데이터를 전달하고, 그 외에는 알고리즘 자체를 매개 변수로 취하는 것이 낫다.

 

 

댓글

Designed by JB FACTORY