際際滷

際際滷Share a Scribd company logo
DSL DYI
...Domain Speci鍖c Languages

       Maciek Pr坦chniak
         mpr@touk.pl


       13 czerwca 2011
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?
Maciek Pr坦chniak




      Niedoszy topolog algebraiczny
      Kontrybutor Activiti
      Integracja: Servicemix, Camel, Drools, OSGi, BPEL...
      Rzeczy mniej przyjemne: GWT, Smartclient, ...
      Last but not least - TouK ;)
DSL


  Domain
  Chcemy m坦c opisa obiekty, reguy z naszej
  dziedziny

  Speci鍖c
  Nie zaprztajc sobie gowy reszt wiata

  Language
  W jakim jzyku (programowania)
DSL - czy nie mamy ju甜 wystarczajco du甜o jzyk坦w?
GPL vs. DSL
DSL - po co?




      Opisywanie regu biznesowych
      atwiejesze przeo甜enie wymaga na kod
      Wsp坦praca z ekspertami
      Zwikszona produktywno
Kto korzysta z DSL?




     Programici/Deweloperzy?


     PO/Eksperci biznesowi?
Cobol fallacy




   Now we can get rid of programmers and have business people
   specify the rules themselves
       - Cobol Fallacy wg. Martina Fowlera
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...
DSL - po co?




      Opisywanie regu biznesowych
      atwiejesze przeo甜enie wymaga na kod
      Wsp坦praca z ekspertami
      Zwikszona produktywno
Ale przecie甜 mamy DDD?




    Bogaty model domenowy to
    podstawa
    DSL - widok na model
    domenowy
    Model domeny to
    trudniejszy fragment
Inny zestaw regu




   Przy budowaniu DSL zwykle amiemy 甜elazne zasady:
       metody globalne/statyczne?
       CQS?
       prawo Demeter?
       mae klasy?
Inny zestaw regu

   Potrzebne warstwy:
DSL - ale jaki?



       zewntrzny (external)
           SQL
           Regexp
           css
           schematy XML?
       wewntrzny (embedded, DSEL) - jest osadzony w GPL
           Apache Camel
           Mockito
           JMock
           Rails
Dlaczego wewntrzne?




   Dostajemy za darmo:
       Parser
       Kompilator
       Wsparcie IDE
       Rozszerzanie i obsuga niestandardowych przypadk坦w
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
Przykad: WS BPEL




     Schemat XML opisu dziaania procesu biznesowego
     Konieczno ujcia wielu rodzaj坦w akcji
     Problem: jzyk staje si GPL
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
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...
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   }
Pynny interfejs - klucz do sukcesu DSL



                              Pynny interfejs
 Klasyczny model obiektowy
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   }
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   }
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   }
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  ) .
Pynny interfejs - zagnie甜d甜anie




   Mo甜liwoci:
       hierarchiczne buildery
       dodatkowe buildery
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   }
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   }
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   }
Pynny interfejs - zagnie甜d甜anie



       hierarchiczne buildery
           lepszy dostp do kontekstu
           lepsze podpowiedzi IDE


       dodatkowe buildery
           prostsze
           reu甜ywalno
           rozszerzalno
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...
Scala comes to the rescue!




      normalny jzyk:
          programowanie obiektowe
          statyczne typowanie
      mo甜na programowa funkcyjnie
      prosty pattern matching
      du甜o lukru syntaktycznego
Scala comes to the rescue!




      uproszczenia skadni, przeci甜anie operator坦w
      domylne (implicit) konwersje i parametry
      funkcje i domknicia
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
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 ) ;
Domylne konwersje




      Dodawanie metod do klas - monkey patching


      Jzyki dynamiczne robi to globalnie


      Jak mo甜na to zrobi bezpieczniej?
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   }
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  ) }
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   }
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   }
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?
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   }
Rozw坦j - rozszerzanie
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  ) ;
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
永看糸壊顎馨看敬顎逮界...




      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
Literatura
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
禽噛庄一顎逮.
U甜yem

  Zdj:
      http://www.鍖ickr.com/photos/gibbons/2294375187/
      http://www.鍖ickr.com/photos/wwworks/2472232245/
      http://www.鍖ickr.com/photos/siomuzzz/2577041081/
      http://www.鍖ickr.com/photos/r4n/3049253551/
      http://www.鍖ickr.com/photos/neilwykes/3219711243/
      http://www.鍖ickr.com/photos/donsolo/3666985941/
      http://www.鍖ickr.com/photos/saeba/4214372479/
      http://www.鍖ickr.com/photos/maysbusinessschool/4948659050/
      http://www.鍖ickr.com/photos/pixelcore/91132699/
             A
  I szablonu LTEXby mcl :)

More Related Content

DSL - DYI

  • 1. DSL DYI ...Domain Speci鍖c Languages Maciek Pr坦chniak mpr@touk.pl 13 czerwca 2011
  • 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?
  • 14. Inny zestaw regu Potrzebne warstwy:
  • 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
  • 51. U甜yem Zdj: http://www.鍖ickr.com/photos/gibbons/2294375187/ http://www.鍖ickr.com/photos/wwworks/2472232245/ http://www.鍖ickr.com/photos/siomuzzz/2577041081/ http://www.鍖ickr.com/photos/r4n/3049253551/ http://www.鍖ickr.com/photos/neilwykes/3219711243/ http://www.鍖ickr.com/photos/donsolo/3666985941/ http://www.鍖ickr.com/photos/saeba/4214372479/ http://www.鍖ickr.com/photos/maysbusinessschool/4948659050/ http://www.鍖ickr.com/photos/pixelcore/91132699/ A I szablonu LTEXby mcl :)