DSL - DYI
Upcoming SlideShare
Loading in...5
×
 

DSL - DYI

on

  • 499 views

Prezentacja pokazana na Confitura 2011

Prezentacja pokazana na Confitura 2011

Statistics

Views

Total Views
499
Views on SlideShare
490
Embed Views
9

Actions

Likes
0
Downloads
2
Comments
0

2 Embeds 9

http://www.linkedin.com 6
https://www.linkedin.com 3

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

DSL - DYI DSL - DYI Presentation Transcript

  • DSL DYI...Domain Specific 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 wewnętrzne, statycznie typowane? Klocki do budowy DSL Co dalej? Gdzie się zatrzymać?
  • Maciek Próchniak Niedoszły 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, reguły z naszej dziedziny Specific Nie zaprzątając sobie głowy resztą świata Language W jakimś języku (programowania)
  • DSL - czy nie mamy już wystarczająco dużo języków?
  • GPL vs. DSL
  • DSL - po co? Opisywanie reguł biznesowych Łatwiejesze przełożenie wymagań na kod Współpraca z ekspertami Zwiększona produktywność
  • Kto korzysta z DSL? Programiści/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 svˇtˇ. Podle Tiobe indexu je Java nejpopul´rnˇjˇ´ programovac´ ee a e sı ı jazyk. (...) Dne 8. kvˇtna 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 przełożenie wymagań na kod Współpraca z ekspertami Zwiększona 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? ”małe” klasy?
  • Inny zestaw reguł Potrzebne warstwy:
  • DSL - ale jaki? zewnętrzny (external) SQL Regexp css schematy XML? wewnętrzny (embedded, DSEL) - jest osadzony w GPL Apache Camel Mockito JMock Rails
  • Dlaczego wewnętrzne? Dostajemy ”za darmo”: Parser Kompilator Wsparcie IDE Rozszerzanie i obsługa niestandardowych przypadków
  • Przykład: WS HumanTask Schemat XML opisu zadań do wykonania przez człowieka W typowym projekcie zadania są podobne Problem: jak zdefiniować typy właściwe dla konkretnego projektu
  • Przykład: WS BPEL Schemat XML opisu działania procesu biznesowego Konieczność ujęcia wielu rodzajów akcji Problem: język staje się GPL
  • Przykład pośredni: Drools Własny język definicji reguł Konieczność ujęcia wielu rodzajów akcji Korzyści: połączenie wyrażalności zewnętrznego DSL i możliwości 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? Języki dynamiczne oferują duże możliwości, ale: Wsparcie IDE Możliwości odkrywania API Każdy projekt trafi w końcu do studentów...
  • Przykład - Apache Camel Implementacja wzorców EIP: router, splitter, aggregator, lista odbiorców, ... Definiowanie przepływów komunikacji Przykład: 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 }
  • Płynny interfejs - klucz do sukcesu DSL Płynny interfejs Klasyczny model obiektowy
  • Płynny 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 ( ”2011−11−12” ) 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 }
  • Płynny 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 ( ”2011−11−12” ) 4 . finish (); 1 p u b l i c Order f i n i s h ( ) { 2 return this . build () 3 }
  • Płynny 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 ( ”2011−11−12” ) 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 }
  • Płynny interfejs - wymuszanie kolejności 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 ” ) .
  • Płynny interfejs - zagnieżdżanie Możliwości: 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 }
  • Płynny interfejs - zagnieżdżanie hierarchiczne buildery lepszy dostęp do kontekstu lepsze podpowiedzi IDE dodatkowe buildery prostsze reużywalność rozszerzalność
  • Co dalej? Cały 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 kończą się możliwości Javy...
  • Scala comes to the rescue! ”normalny” język: programowanie obiektowe statyczne typowanie można programować funkcyjnie prosty pattern matching dużo lukru syntaktycznego
  • Scala comes to the rescue! uproszczenia składni, przeciążanie operatorów domyślne (implicit) konwersje i parametry funkcje i domknięcia
  • Uproszczenia składni W wielu miejscach kropki i przecinki stają się opcjonalne: 1 order () 2 . s i z e ( 1 1 ) . express ( true ) A więc: 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 więc: 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 ) ;
  • Domyślne konwersje Dodawanie metod do klas - monkey patching Języki dynamiczne robią to globalnie Jak można to zrobić bezpieczniej?
  • Domyślne konwersje Dodajemy możliwość autokonwersji w obrębie 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 domknięcia 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 domknięcia 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 SChoiceDefinition2 ( override val target : ChoiceDefinition ) . . . {3 override def otherwise = {4 target . otherwise5 this6 }78 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 this12 }13 }
  • Granice czytelności i wyrażalności Język naturalny:1 Stworz zamowienie2 d l a k l i e n t a ”TouK” Fleksja? Synonimy? Koniugacja?
  • O jeden krok za daleko? Definiowanie 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 - przykład 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 - przykład Trudno ”wpiąć” się ze swoimi rozszerzeniami Problem: Użycie zagnieżdżonych builderów Możliwe rozwiązania: Używanie oddzielnych builderów i obiektu kontekstu Nadpisanie pewnej części źródłowego DSL - może być skomplikowane
  • Podsumowując... DSL może zwiększyć czytelność i zwięzłość kodu Wewnętrzne DSLe w statycznie typowanych językach mają niski koszt budowy i nauki Korzystając ze Scali możemy zmniejszyć szum syntaktyczny w naszym DSLu Projektując DSL trzeba myśleć o jego rozwoju i możliwościach rozszerzania
  • Literatura
  • I inne zasoby http://weblogs.java.net/blog/carcassi/archive /2010/02/04/building-fluent-api-internal-dsl-java http://pragdave.blogs.pragprog.com/pragdave/2008/03/the- language-in.html http://www.infoq.com/articles/internal-dsls-java
  • Dziękuję.
  • Użyłem Zdjęć: http://www.flickr.com/photos/gibbons/2294375187/ http://www.flickr.com/photos/wwworks/2472232245/ http://www.flickr.com/photos/siomuzzz/2577041081/ http://www.flickr.com/photos/r4n/3049253551/ http://www.flickr.com/photos/neilwykes/3219711243/ http://www.flickr.com/photos/donsolo/3666985941/ http://www.flickr.com/photos/saeba/4214372479/ http://www.flickr.com/photos/maysbusinessschool/4948659050/ http://www.flickr.com/photos/pixelcore/91132699/ A I szablonu LTEXby mcl :)