참고
DSL(Domain-specific-Language, 도메인 전용 언어)
NOTE
DSL은 특정 비즈니스 도메인의 문제를 해결하려고 만든, 작은, 범용이 아닌 특정 도메인을 대상으로 만들어진 프로그래밍 언어다!
•
비즈니스 도메인
◦
ex) 쇼핑몰 플랫폼을 개발한다 ⇒ 상품결제, 배송처리
•
DSL
◦
특정 비즈니스 도메인을 인터페이스로 만든 API
◦
대표적으로 SQL ⇒ DB에 데이터를 참조하기 위한 목적으로 만든언어!
◦
자바8에서는 Stream, Collector등 여러 DSL이 추가되었다.
DSL 개발 필요성
1.
코드의 의도가 명확히 전달되어야 하며, 개발자가 아닌사람도 이해할 수 있어야하고, 요구사항에 부합하는지 확인해야 한다.
2.
가독성은 유지보수의 핵심이다.
DSL의 장점과 단점
NOTE
DSL은 만병통치약이 아니다, 잘못사용하면 독이 될 수 있다!
장점
•
간결함
◦
도메인 영역의 용어를 사용하므로, 비 도메인 전문가도 쉽게 이해한다.
◦
다양한 조직 구성원 간에 코드와 도메인 영역이 공유될 수 있다.
•
가독성
◦
도메인 영역의 용어를 사용하므로 비 도메인 전문가도 코드를 쉽게 이해할 수 있다.
◦
결과적으로 다양한 조직 구성원 간에 코드와 도메인 영역이 공유될 수 있다.
•
유지보수
◦
잘 설계된 DSL로 구현한 코드는 쉽게 유지보수 할 수 있다.
•
높은 수준의 추상화
◦
DSL은 도메인과 같은 추상화 수준에서 동작하므로 도메인의 문제와 직접적으로 관련되지 않은 세부사항을 숨긴다.
단점
•
DSL설계의 어려움
◦
간결하게 제한적인 언어에 도메인 지식을 담는건 어렵다.
•
개발 비용
◦
코드에 DSL을 추가하는 작업은 초기 프로젝트에 많은 비용과 시간을 소모한다.
•
새로배워야 하는 언어
◦
DSL을 프로젝트에 추가함으로서, 언어가 1개 늘어나는 부담이 있다.
자바로 DSL을 만드는 패턴법
NOTE
쇼핑몰에서 주문을 하는 간단한 예제로 DSL을 만드는 패턴을 알아보자!
대표적인 구현방법 3가지
Product product1 = new Product("청소기", 200_000);
Product product2 = new Product("냉장고", 1_200_000);
Coupon coupon = new Coupon("100,000원 할인 쿠폰", 100_000);
Order order = new Order();
// 청소기 1개 선택
OrderBasket orderBasket1 = new OrderBasket(product1, 1);
// 장바구니 추가
order.addOrderBasket(orderBasket1);
// 냉장고 1개 선택
OrderBasket orderBasket2 = new OrderBasket(product2, 1);
// 냉장고 2개 선택
orderBasket2.countUp();
// 냉장고 3개 선택
orderBasket2.countUp();
// 장바구니 추가
order.addOrderBasket(orderBasket2);
// 쿠폰 적용
order.applyCoupon(coupon);
// 주문 완료
order.completed();
Java
복사
특정 상품들을 장바구니에 담는 주문을 만드는 로직을 구현한다.
쇼핑몰 참고코드
•
지금은 그래도 볼만하지만, 필드와 메서드가 더 많아진다면 가독성이 더욱 떨어져 직관적인 코드를 이해하고, 검증 할 수 없어진다.
•
조금 더 직접적이고, 직관적으로 도메인 모델을 반영할 수 있는 DSL이 필요하다
1. 메서드 체인(플루언트 스타일)을 이용한 DSL
NOTE
DSL을 구현하는 가장 흔한 방식이며, 인스턴스의 생성단계를 Builder 클래스에 구현해서 지정된 절차에따라 API를 호출하도록 할 수 있다!
Order order = MethodChainingOrderBuilder.builder()
.choice()
.product(product1).count(1)
.and()
.product(product2).count(1).countUp().countUp()
.end()
.applyCoupon(coupon)
.completed();
Java
복사
가독성이 훨씬 좋아졌다.
Builder 구현코드 참고
장점/단점
•
메서드의 이름이 인수의 이름을 대신하도록 만듦으로 가독성 개선, 문법적 잡음이 최소화된다!
•
빌더를 구현해야 한다는 단점이 있다.
2. 중첩된 함수 이용
NOTE
다른 함수안에 함수를 이용해서 도메인을 만든다.
Product product1 = new Product("청소기", 200_000);
Product product2 = new Product("냉장고", 1_200_000);
Coupon coupon = new Coupon("100,000원 할인 쿠폰", 100_000);
Order order = order(
coupon,
choice(
product(product1),
orderCount(1)
),
choice(
product(product2),
orderCount(1)
)
).completed();
Java
복사
좋은건가? 난 잘모르겠다
중첩된 함수 구현
장점/단점
•
메서드 체인에 비해 함수의 중첩 방식이 도메인 계층 구조에 그대로 반영된다.
•
DSL에 더 많은 괄호를 사용해야하고, 인수 목록을 정적 메서드에 넘겨줘야 한다.
3. 람다 표현식을 이용한 시퀀싱
NOTE
Product product1 = new Product("청소기", 200_000);
Product product2 = new Product("냉장고", 1_200_000);
Coupon coupon = new Coupon("100,000원 할인 쿠폰", 100_000);
Order order = order(b -> {
b.choice(b2 -> {
b2.product(product1);
b2.orderCount(1);
});
b.choice(b2 -> {
b2.product(product2);
b2.orderCount(1);
});
b.applyCoupon(coupon);
});
Java
복사
람다 표현식 구현
장점/단점
•
메서드 체인, 중첩 함수의 장점을 가져왔다.
•
많은 설정 코드가 필요하며, DSL 자체가 Java8 람다표현식 문법에 의한 잡음의 영향을 받는다.