2. DSL - Plan
Co to jest DSL i do czego mo甜e si przyda
Rodzaje DSL - dlaczego wewntrzne, statycznie typowane?
Klocki do budowy DSL
Co dalej? Gdzie si zatrzyma?
3. Maciek Pr坦chniak
Niedoszy topolog algebraiczny
Kontrybutor Activiti
Integracja: Servicemix, Camel, Drools, OSGi, BPEL...
Rzeczy mniej przyjemne: GWT, Smartclient, ...
Last but not least - TouK ;)
4. DSL
Domain
Chcemy m坦c opisa obiekty, reguy z naszej
dziedziny
Speci鍖c
Nie zaprztajc sobie gowy reszt wiata
Language
W jakim jzyku (programowania)
5. DSL - czy nie mamy ju甜 wystarczajco du甜o jzyk坦w?
7. DSL - po co?
Opisywanie regu biznesowych
atwiejesze przeo甜enie wymaga na kod
Wsp坦praca z ekspertami
Zwikszona produktywno
8. Kto korzysta z DSL?
Programici/Deweloperzy?
PO/Eksperci biznesowi?
9. Cobol fallacy
Now we can get rid of programmers and have business people
specify the rules themselves
- Cobol Fallacy wg. Martina Fowlera
10. Znajomo czynna i znajomo bierna
Znajomo bierna:
Java je jedn卒 z nejpou卒 ej卒 programovac卒 jazyk na
脹m z脹van s脹ch 脹ch u
svt. Podle Tiobe indexu je Java nejpopul卒rnj卒 programovac卒
ee a e s脹 脹
jazyk. (...) Dne 8. kvtna 2007 Sun uvolnil zdrojov卒 k坦dy Javy (cca
e e
2,5 mili坦n 卒dk k坦du) a Java bude d卒le vyv卒
u ra u a 脹jena jako open
source.
- http://cs.wikipedia.org/wiki/Java (programovac卒 jazyk)
脹
Znajomo czynna?
To ju甜 trudniejsze...
11. DSL - po co?
Opisywanie regu biznesowych
atwiejesze przeo甜enie wymaga na kod
Wsp坦praca z ekspertami
Zwikszona produktywno
12. Ale przecie甜 mamy DDD?
Bogaty model domenowy to
podstawa
DSL - widok na model
domenowy
Model domeny to
trudniejszy fragment
13. Inny zestaw regu
Przy budowaniu DSL zwykle amiemy 甜elazne zasady:
metody globalne/statyczne?
CQS?
prawo Demeter?
mae klasy?
15. DSL - ale jaki?
zewntrzny (external)
SQL
Regexp
css
schematy XML?
wewntrzny (embedded, DSEL) - jest osadzony w GPL
Apache Camel
Mockito
JMock
Rails
16. Dlaczego wewntrzne?
Dostajemy za darmo:
Parser
Kompilator
Wsparcie IDE
Rozszerzanie i obsuga niestandardowych przypadk坦w
17. Przykad: WS HumanTask
Schemat XML opisu zada do wykonania przez czowieka
W typowym projekcie zadania s podobne
Problem: jak zde鍖niowa typy waciwe dla konkretnego
projektu
18. Przykad: WS BPEL
Schemat XML opisu dziaania procesu biznesowego
Konieczno ujcia wielu rodzaj坦w akcji
Problem: jzyk staje si GPL
19. Przykad poredni: Drools
Wasny jzyk de鍖nicji regu
Konieczno ujcia wielu rodzaj坦w akcji
Korzyci: poczenie wyra甜alnoci zewntrznego DSL i
mo甜liwoci Javy
1 r u l e AcceptOrder
2 when
3 $ c l i e n t : C l i e n t ( s t a t u s==APPROVED)
4 $ o r d e r : O r d e r ( s t a t u s== NEW, c l i e n t==$ c l i e n t )
5 then
6 orderService . acceptOrder ( $order )
7 end
20. Dlaczego statycznie typowane?
Jzyki dynamiczne oferuj du甜e
mo甜liwoci, ale:
Wsparcie IDE
Mo甜liwoci odkrywania API
Ka甜dy projekt tra鍖 w kocu
do student坦w...
21. Przykad - Apache Camel
Implementacja wzorc坦w EIP: router, splitter, aggregator, lista
odbiorc坦w, ...
De鍖niowanie przepyw坦w komunikacji
Przykad:
1 c l a s s JamRouteBuilder extends R o u t e B u i l d e r {
2 public void c o n f i g u r e () {
3 from ( f i l e : / tmp/ i n )
4 . convertBodyTo ( S t r i n g . c l a s s )
5 . bean ( r e c i p i e n t R e p o s i t o r y )
6 . r e c i p i e n t L i s t ( property ( recipients ));
7 }
8 }
22. Pynny interfejs - klucz do sukcesu DSL
Pynny interfejs
Klasyczny model obiektowy
23. Pynny interfejs - rozszerzony budowniczy
1 makeOrder (NORMAL)
2 . w i t h P r i c e ( new B i g D e c i m a l ( 2 2 . 0 0 ) )
3 . w i t h D a t e ( 20111112 )
4 . finish ();
1 p u b l i c O r d e r B u i l d e r makeOrder ( OrderType t y p e ) {
2 r e t u r n new O r d e r B u i l d e r ( t y p e ) ;
3 }
4 //w k l a s i e O r d e r B u i l d e r
5 public OrderBuilder w i t h P r i c e ( BigDecimal p r i c e ) {
6 this . price = price ;
7 return this ;
8 }
24. Pynny interfejs - problem stopu
1 makeOrder (NORMAL)
2 . w i t h P r i c e ( new B i g D e c i m a l ( 2 2 . 0 0 ) )
3 . w i t h D a t e ( 20111112 )
4 . finish ();
1 p u b l i c Order f i n i s h ( ) {
2 return this . build ()
3 }
25. Pynny interfejs - problem stopu
1 makeOrder (NORMAL)
2 . w i t h P r i c e ( new B i g D e c i m a l ( 2 2 . 0 0 ) )
3 . w i t h D a t e ( 20111112 )
4 . withClientId (1334);
Id klienta jest wymagane:
1 p u b l i c Order w i t h C l i e n t I d ( long l ) {
2 clientId = l ;
3 return this . build ( ) ;
4 }
26. Pynny interfejs - wymuszanie kolejnoci
1
2 interface ClientPhoneBuilder {
3 S t r e e t B u i l d e r w i t h P h o n e ( S t r i n g phone ) ;
4 S t r e e t B u i l d e r withoutPhone ( ) ;
5 }
6
7 interface StreetBuilder {
8 ClientApartmentBuilder livingOn ( String street );
9 C l i e n t homeless ( ) ;
10 }
11 ...
1
2 . w i t h P h o n e ( 2245556 ) . l i v i n g O n ( J e r o z o l i m s k i e ) .
27. Pynny interfejs - zagnie甜d甜anie
Mo甜liwoci:
hierarchiczne buildery
dodatkowe buildery
28. Zagnie甜d甜anie builder坦w - hierarchie
1 . f i l t e r ()
2 . x p a t h ( // o r d e r I d )
3 . isEqualTo (15)
4 . send ( http : / / . . . )
1 class RouteBuilder {
2 ...
3 ExpressionBuilder f i l t e r () {
4 t h i s . f i l t e r = new E x p r e s s i o n B u i l d e r ( t h i s ) ;
5 return this . f i l t e r ;
6 }
7 v o i d s e n d ( S t r i n g where ) {
8 ...
9 }
29. Zagnie甜d甜anie builder坦w - hierarchie
1 . f i l t e r ()
2 . x p a t h ( // o r d e r I d )
3 . isEqualTo (15)
4 . send ( http : / / . . . )
1 c l a s s E x p r e s s i o n B u i l d e r <T> {
2
3 T parent ;
4
5 E x p r e s s i o n B u i l d e r xpath ( S t r i n g xpath ) {
6 t h i s . e x p r e s s i o n = new X P a t h E x p r e s s i o n ( x p a t h ) ;
7 return this ;
8 }
9 T isEqualTo ( String value ) {
10 t h i s . a s s e r t i o n = new E q u a l i t y ( v a l u e ) :
11 return parent ;
12 }
13 }
30. Zagnie甜d甜anie builder坦w - oddzielne buildery
1
2 c la s s SenderRouter extends RouteBuilder {
3 ...
4 . filter (
5 x p a t h ( // o r d e r I d ) . i s E q u a l T o ( 1 5 )
6 ) . send ( http : / / . . . )
7 ...
8 E x p r e s s i o n B u i l d e r xpath ( S t r i n g xpath ) {
9 r e t u r n new X P a t h B u i l d e r ( x p a t h ) ;
10 }
11 }
Obiekt kontekstu jest lepszy ni甜 funkcje globalne
1 class XpathBuilder extends ExpressionBuilder {
2 Expression isEqualTo ( String value ) {
3 t h i s . a s s e r t i o n = new E q u a l i t y ( v a l u e ) :
4 return build ( ) ;
5 }
31. Pynny interfejs - zagnie甜d甜anie
hierarchiczne buildery
lepszy dostp do kontekstu
lepsze podpowiedzi IDE
dodatkowe buildery
prostsze
reu甜ywalno
rozszerzalno
32. Co dalej?
Cay czas du甜o szumu syntaktycznego:
1 from ( s e d a : a )
2 . choice ()
3 . when ( h e a d e r ( f o o ) . i s E q u a l T o ( b a r ) )
4 . to ( seda : b )
5 . otherwise ()
6 . p r o c e s s ( new P r o c e s s o r ( ) {
7 p u b l i c v o i d p r o c e s s ( Exchange e x ) {
8 e x . s e t P r o p e r t y ( d a t e , new Date ( ) ) ;
9 }
10 });
Tu kocz si mo甜liwoci Javy...
33. Scala comes to the rescue!
normalny jzyk:
programowanie obiektowe
statyczne typowanie
mo甜na programowa funkcyjnie
prosty pattern matching
du甜o lukru syntaktycznego
34. Scala comes to the rescue!
uproszczenia skadni, przeci甜anie operator坦w
domylne (implicit) konwersje i parametry
funkcje i domknicia
35. Uproszczenia skadni
W wielu miejscach kropki i przecinki staj si opcjonalne:
1 order ()
2 . s i z e ( 1 1 ) . express ( true )
A wic:
1 order ()
2 s i z e 11
3 express true
36. Przeci甜anie operator坦w
Wszystko jest metod
1 c l a s s Balance ( balance : BigDecimal ) {
2 d e f + ( toAdd : B a l a n c e ) : B a l a n c e = {
3 new B a l a n c e ( b a l a n c e+toAdd . g e t B a l a n c e ) }
4 def getBalance = balance
5 }
A wic:
1 println
2 ( ( new B a l a n c e ( 1 0 ) + new B a l a n c e ( 1 0 ) ) . g e t B a l a n c e ) ;
37. Domylne konwersje
Dodawanie metod do klas - monkey patching
Jzyki dynamiczne robi to globalnie
Jak mo甜na to zrobi bezpieczniej?
38. Domylne konwersje
Dodajemy mo甜liwo autokonwersji w obrbie danej klasy:
1 c l a s s Orders {
2 i m p l i c i t def stringToOrder ( s t r : String ) =
3 new O r d e r B u i l d e r ( s t r ) ;
4 }
5
6 class OrderBuilder ( c l i e n t : String ) {
7 var p r i c e : BigDecimal = 0;
8 def w i t h P r i c e ( newPrice : BigDecimal ) =
9 { p r i c e = newPrice ; b u i l d ; }
10 def build = . . .
11 };
I mo甜emy napisa:
1 c l a s s VIPOrders extends Orders {
2 c l i e n t withPrice 1.22
3 }
39. Przekazywanie strategii - funkcje i domknicia
Przekazywanie wyra甜e, predykat坦w - Java
1 . f i l t e r ( new E x p r e s s i o n ( ) {
2 p u b l i c b o o l e a n e v a l u a t e ( Message message ) {
3 r e t u r n VIP == message . g e t P r o p e r t y ( c l i e n t T y p e ) ;
4 }
5 }).
Scala:
1 . f i l t e r { e x c h a n g e =>
2 VIP==e x c h a n g e . g e t P r o p e r t y ( c l i e n t T y p e ) }
40. Przekazywanie strategii - funkcje i domknicia
Przekazywanie wyra甜e, predykat坦w - Scala
1 d i r e c t : b == { >
2 when ( . i n == < h a l l o /> ) {
3 > ( mock : b )
4 t o ( mock : c )
5 } otherwise {
6 p r o c e s s ( e x => e x . s e t P r o p e r t y ( d a t e , new Date ( ) ) )
7 }
8 t o ( mock : d )
9 }
41. 1 case c l a s s SChoiceDefinition
2 ( override val target : ChoiceDefinition ) . . . {
3 override def otherwise = {
4 target . otherwise
5 this
6 }
7
8 o v e r r i d e d e f when ( f i l t e r : Exchange => Any ) = {
9 val predicate = PredicateBuilder . toPredicate ( f i l t e r )
10 t a r g e t . when ( p r e d i c a t e )
11 this
12 }
13 }
42. Granice czytelnoci i wyra甜alnoci
Jzyk naturalny:
1 Stworz zamowienie
2 d l a k l i e n t a TouK
Fleksja?
Synonimy?
Koniugacja?
43. O jeden krok za daleko?
De鍖niowanie
1 class OrderBuilder ( c l i e n t : String ) {
2 var nameField : S t r i n g = ;
3 def name = { n a m e F i e l d = }
4 def with a = t h i s ;
5 };
By napisa
1 c l a s s VIPOrders extends Orders {
2 c l i e n t . w i t h a name a l a ;
3 }
45. Rozszerzanie - przykad
DSL do bardzo prostych proces坦w stanowych
interakcje oparte na Apache Camel
1 s t a r t ( d i r e c t : employee ) . f o r k (
2 s t a t e ( h r S t a r t ) . to ( f i l e :/// hr )
3 . w a i t S t a t e ( waitingForHR , f i l e :/// h r I n )
4 . s t a t e ( hrEnd ) ,
5 s t a t e ( i t S t a r t ) . to ( f i l e :/// i t )
6 . waitState ( waitingForIT , f i l e :/// i t I n )
7 . state ( itEnd )
8 ) . s t a t e ( end ) ;
46. Rozszerzanie - przykad
Trudno wpi si ze swoimi rozszerzeniami
Problem: U甜ycie zagnie甜d甜onych builder坦w
Mo甜liwe rozwizania:
U甜ywanie oddzielnych builder坦w i obiektu kontekstu
Nadpisanie pewnej czci 添r坦dowego DSL - mo甜e by
skomplikowane
47. 永看糸壊顎馨看敬顎逮界...
DSL mo甜e zwikszy czytelno i zwizo kodu
Wewntrzne DSLe w statycznie typowanych jzykach maj
niski koszt budowy i nauki
Korzystajc ze Scali mo甜emy zmniejszy szum syntaktyczny w
naszym DSLu
Projektujc DSL trzeba myle o jego rozwoju i mo甜liwociach
rozszerzania
49. I inne zasoby
http://weblogs.java.net/blog/carcassi/archive
/2010/02/04/building-鍖uent-api-internal-dsl-java
http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-
language-in.html
http://www.infoq.com/articles/internal-dsls-java