본문 바로가기
C#/Effective C#

[Effective C#] Item 40 지연 수행과 즉시 수행을 구분하라

by 코모's 2023. 5. 2.
반응형

명령형 코드(Imperative Code) [즉시 수행]

  • 어떻게 작업을 수행해야 하는지를 단계별로 세분화 하여 기술한다.
  • 필요한 매개변수를 모두 계산한 다음에야 비로소 메서드를 호출한다.
  • 아래의 예시에서는 항상 모든 메서드를 호출하며, 각 메서드의 부수효과는 반드시 한 번씩만 발생한다.
  • 메서드를 호출하고 그 결과를 다른 메서드에 전달한다.
var answer = Dostuff(Method1(), Method2(), Method3());

선언적 코드(Declarative Code) [지연 수행]

  • 해결석이며 무슨 작업을 해야 하는지를 정의한다.
  • 각 메서드의 수행 경로가가 필요한 경우에만 호출된다.
  • 아래의 예시에서는 메서드가 각기 호출될 수 도 있고 아닐 수 도 있으며, 여러번 호출 될 수 도 있다.
var answer = DoStuff(() => Method1(), () => Method2(), () => Method3());

 

두 코드는 호출 시점의 차이가 발생하기 때문에 두가지 방식을 섞어서 사용하면 문제를 일으킬 수 있다.

 

데이터와 메서드

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

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

 

지연 평가로 인해 부수 효과가 발생하지 않는다는 전제로 두 방식 중 선택해야 한다면, 입출력을 위해 사용하는 공간 비용과 출력을 만들기 위한 계산 비용간의 관계를 고려해야 한다.

 

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

이를 대체하기 위해 사전에 모든 정수를 약수로 저장해둔 테이블을 만들고, 여기서 값을 찾아서 리턴한다면, 데이터 테이블을 유지하기 위한 공간비용이 약수를 계산하는 함수에 비해 너무나 클 것이다.

 

 

두 가지 방식을 혼합하여 사용하기

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

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

 

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

 

결론

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

반응형