일급 함수
파이썬의 함수는 일급 객체다. 파이썬에서 함수는 다음과 같은 작업을 수행할 수 있다.
- 런타임에 생성할 수 있다.
- 데이터 구조체의 변수나 요소에 할당할 수 있다.
- 함수 인수로 전달할 수 있다.
- 함수 결과로 반환할 수 있다.
이러한 파이썬의 일급 함수 성질을 이용하여 함수형 스타일로 프로그래밍할 수 있다. 이 글에서는 함수 객체를 이용하여 전략 패턴을 리팩토링하는 방법을 정리한다.
클래스를 사용한 전략 패턴
위 전략 패턴에 대한 UML에서 들어가는 구성요소는 다음과 같다.
- 콘텍스트: 일부 계산을 서로 다른 알고리즘을 구현하는 교환 가능한 컴포넌트에 위임하여 서비스를 제공
- 전략: 여러 알고리즘을 구현하는 컴포넌트에 공통된 인터페이스
- 구체적인 전략: 전략의 구성 서브클래스 중 하나
전략 패턴의 예는 고객의 속성이나 주문한 상품에 따라 할인을 계산하는 전자상거래 영역에서 쉽게 볼 수 있다. 아래와 같은 할인 규칙을 적용하는 온라인 쇼핑몰을 생각하자.
- 충성도 포인트가 1,000점 이상인 고객은 전체 주문에 대해 5% 할인을 적용한다.
- 하나의 주문에서 20개 이상의 동일 상품을 구매하면 해당 상품에 대해 10% 할인을 적용한다.
- 서로 다른 상품을 10종류 이상 주문하면 전체 주문에 대해 7% 할인을 적용한다.
이러한 할인 규칙을 전략 패턴을 적용하여 클래스로 구현하면 아래와 같다.
위 코드에서 각각의 구체적인 전략은 discount()라는 메서드 하나를 가진 클래스다. 그리고 객체는 상태를 가지고 있지 않다. 그래서 이를 일급 함수를 이용하여 클래스 대신 함수로 전략 패턴을 구현해볼 수 있다.
일급 함수를 사용한 전략 패턴
할인 전략을 함수로 구현한 코드는 아래와 같다.
이렇게 함수로 리팩토링된 전략 패턴은 Order 객체를 만들 때마다 할인 전략 객체를 만들 필요가 없다. 할인 전략 함수를 그대로 전달해버리면 되기 때문이다.
함수 이름 이용하여 해킹하기
여기서 좀 더 나아가, *_promo() 이름을 가진 함수들을 모아서 이 중에 최대로 할인받을 금액을 계산하는 best_promo() 함수를 구현해볼 수 있다.
globals() 이용하여 best_promo()가 함수 이름의 접미사를 검사하여 할인 전략으로 구현된 함수만 모을 수 있다.
※ globals(): 현재 전역 심벌 테이블을 나타내는 딕셔너리 객체를 반환하여 현재 모듈에 대한 정보를 가져온다.
마치며
- 파이썬의 일급 함수 성질을 이용하여 코드를 간결하게 짜볼 수 있다.
- Strategy, Visitor 등과 같은 패턴에 일급 함수를 적극적으로 사용해보자. 함수 이름을 이용해서 해킹하는 방법도