712
4
부
고급 주제 및 실전 응용
그로 인해 컴파일러 자체를 포함하여 다양한 애플리케이션에서 케이크 패턴의 사용을 덜 강조
하는 결과를 낳았다. 그 패턴은 여전히 유용하지만, 현명하게 사용해야 한다.
23.4
디자인 패턴
디자인 패턴은 최근 비판에 직면해 있다. 평론가들은 디자인 패턴을 언어가 제공하는 특징의 결
여를 우회하기 위한 방법이라고 일축하기도 한다. 실제로 사인방
Gang
of
Four
패턴
3
의 일부는 스
칼라에서 제공하는 더 나은 기능으로 인해 더 이상 필요하지 않다. 다른 패턴은 스칼라 언어의
일부이기 때문에 특별히 따로 코딩할 필요가 없다. 물론 패턴을 모든 설계 문제에 대한 만병통치
약으로 오용하거나 과용하는 경우도 자주 있지만, 그것은 패턴 자체의 문제가 아니다.
디자인 패턴은 반복적으로 널리 사용되는 아이디어를 문서화한 것이다. 패턴은 개발자들이 서
로 의사소통할 때 유용한 어휘의 일부가 될 수 있다. 나는
16
.
2
절 ‘카테고리 이론’에서 카테고
리가 수학에서 함수형 프로그래밍으로 가져온 설계 패턴이라고 주장했다.
4
인방 패턴을 나열하면서 각각 스칼라 또는 아카와 같은 툴킷에 어떤 의미가 있는지 논의해보
자. 해당 패턴을 실제로 활용하고 있는 구체적 예제로 살펴볼 것이다 (그 패턴의 이름을 사용하는
지 여부와 관계없이 ). 원래의 책에 있는 분류를 따라 생성, 구조, 행동 패턴으로 나눌 것이다.
23.4.1
생성 패턴
추상 팩토리
타입을 구체적으로 지정하지 않고, 어떤 타입의 계열로부터 인스턴스를 만들 수 있는 추상화
다.
object
에 있는
apply
메서드를 이런 목적에 사용할 수 있으며, 그 메서드에 전달되는 인
자의 타입에 따라 적절한 타입의 인스턴스를 생성할 수 있다.
Monad
.
flatMap
에 전달되는 함
수나 스칼라제드의 애플리케이티브에 의해 정의된
apply
메서드도 생성에 대한 추상화다.
3
주_ 원서는『
Design
Patterns
:
Elements
of
Reusable
Object
-
Oriented
Software
』(에리히감마(
Erich
Gamma
)등저,
Addison
-
Wesley
,
1995
),한글판은『
GoF
의디자인패턴:재사용성을지닌객체지향소프트웨어의핵심요소(개정판)』(김정아역,프
로텍미디어,
2015
).
713
23
장
애플리케이션 설계
빌더
복잡한 객체의 생성을 내부 표현과 분리해서 여러 표현 방식에 같은 생성 과정을 사용할 수 있
게 한다.
map
과 같은 콤비네이터 메서드가 입력 컬렉션과 같은 타입의 새로운 컬렉션을 만들
수 있게 해주는
collection
.
generic
.
CanBuildFrom
(
http
://
bit
.
ly
/
1zRqZC9
)이 고전적
인 예다.
팩토리 메서드
어떤 타입을 어떻게 인스턴스화할지 서브타입이 결정할 수 있도록, 서브타입이 오버라이딩
(또는 구현)할 수 있는 메서드를 정의한다.
CanBuildFrom
.
apply
는 인스턴스를 만들 수 있
는 빌더를 구성할 수 있는 추상 메서드다. 서브타입이나 특정 인스턴스가 자세한 구현을 제
공한다.
Applicative
.
apply
도 비슷한 추상화를 제공한다.
프로토타입
프로토타입 인스턴스를 복사한 다음 일부 선택적인 변경을 적용해서 새로운 인스턴스를 만
든다. 케이스 클래스의
copy
메서드가 훌륭한 예다. 그 메서드를 사용하면 사용자가 어떤 인
스턴스를 복제하되, 변경할 부분을 인자로 지정할 수 있다.
16
.
2
절 ‘카테고리 이론’에서 비
록 직접 설명하지는 않았지만 렌즈를 언급한 바 있다. 렌즈는 객체 그래프에서 임의의 깊이
에 내포되어 있는 값을 (복사와 함께 ) 가져오거나 설정하는 다른 기법을 제공한다.
싱글턴
어떤 타입이 오직 한 인스턴스만 만들고, 해당 타입을 사용하는 모든 사용자가 그 인스턴스에
접근할 수 있도록 보장한다. 스칼라는 이 패턴을
object
라는 이름으로 언어의
1
급 계층 기능
으로 채택했다.
23.4.2
구조 패턴
어댑터
기존의 추상화 위에 고객이 원하는 추상화를 제공하기 위한 인터페이스를 만든다. 따라서
고객은 그 인터페이스를 활용해서 원래의 추상화를 사용할 수 있다.
9
.
2
절 ‘믹스인으로서의
트레이트’와
14
.
7
절 ‘구조적 타입’에서
Observer
패턴의 여러 구현의 장단점을 설명하면서
714
4
부
고급 주제 및 실전 응용
추상화와 잠재적인 관찰자 사이의 결합에 대해 비교했다. 처음에는 관찰자가 구현해야 하는
트레이트부터 시작했다. 그 후 의존성을 줄이기 위해 구조적 타입으로 트레이트를 대치했고,
그 결과 잠재적인 관찰자가 트레이트를 구현할 필요 없이 특정 메서드만 제공하면 되었다.
또한 익명 함수를 사용한다면 관찰자와의 결합을 완전히 없앨 수 있음을 배웠다. 이 함수는
실제로 어댑터라고 할 수 있다. 주체가 그 함수를 호출하면, 함수 내부에서 필요한 관찰자 관
련 논리를 호출할 수 있다.
브리지
추상과 구현을 분리해서, 각각 독립적으로 변화할 수 있도록 한다. 타입 클래스는 이런 원칙
을 논리적인 극한까지 밀어붙이는 경우 어떤 일이 벌어지는지 보여주는 재미있는 예다. 어
떤 추상화를 그 추상화를 필요로 하는 타입으로부터 없앨 뿐 아니라, 필요할 때 추상화를 다
시 집어넣을 수 있다. 하지만 주어진 타입에 대한 타입 클래스 추상화의 구현은 타입 클래스
추상화와 별도로 정의할 수도 있다.
컴포지트
개별 인스턴스나 여러 부분을 합성한 것을 균일하게 취급할 수 있는 부분
-
전체 계층구조를
표현하는 트리 구조다. 함수형 코드는 타입을 임의로 계층화하는 일을 피하고, 트리와 같은
더 일반적인 구조를 사용하는 것을 선호하는 경향이 있다. 일반적인 구조를 활용하면, 트리를
조작하기 위한 완전한 콤비네이터의 활용이나 트리의 여러 요소에 대한 균일한 접근이 가능
하다. 렌즈는 단순하지 않은 복합적인 구조를 대상으로 작업할 경우에 사용할 수 있는 도구다.
데코레이터
어떤 객체에 ‘동적으로’ 책임을 추가한다. 타입 클래스는 어떤 타입의 원 소스 코드를 변경하
지 않고도 이를 컴파일 시점에 할 수 있다. 정말 실행 시점에 유연성이 필요하다면
Dynamic
트레이트 (
http
://
bit
.
ly
/
1pbhB8b
)가 유용할 것이다. 모나드와 애플리케이티브는 각각 값
이나 계산을 ‘꾸미기’ 위해 효과적으로 사용할 수 있다.
퍼사드
어떤 하위시스템의 여러 인터페이스에 대해 균일한 인터페이스를 제공해서, 그 하위시스템
을 더 쉽게 사용할 수 있게 해준다. 패키지 객체는 이런 패턴을 지원한다. 패키지 객체는 외부
에 공개해야 하는 타입이나 동작만 노출시킬 수 있다.
Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.