Successfully reported this slideshow.
Your SlideShare is downloading. ×

Real world DSL - making technical and business people speaking the same language

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 26 Ad
Advertisement

More Related Content

Slideshows for you (19)

Viewers also liked (20)

Advertisement

Similar to Real world DSL - making technical and business people speaking the same language (20)

More from Mario Fusco (20)

Advertisement

Recently uploaded (20)

Real world DSL - making technical and business people speaking the same language

  1. 1. Real world DSL making technical and business people speaking the same language by Mario Fusco Red Hat – Senior Software Engineer mario.fusco@gmail.com twitter: @mariofusco
  2. 2. What is a Domain Specific Language? A computer programming language of limited expressiveness focused on a particular domain
  3. 3. Why use a Domain Specific Language? 2 principles driving toward DSL development
  4. 4. Communication is king The only purpose of languages, even programming ones IS COMMUNICATION
  5. 5. Written once, read many times Always code as if the person who will maintain your code is a maniac serial killer that knows where you live
  6. 6. "Any fool can write code that a computer can understand. Good programmers write code that humans can understand“ Martin Fowler
  7. 7. Pros & Cons of DSLs + Expressivity  Communicativity + Conciseness + Readability  Maintainability  Modificability + Higher level of abstraction + Higher productivity in the specific problem domain ̶ Language design is hard ̶ Upfront cost ̶ Additional indirection layer  Performance concerns ̶ Lack of adeguate tool support ̶ Yet-another-language-to-learn syndrome
  8. 8. DSL taxonomy  External DSL  a language having custom syntactical rules separate from the main language of the application it works with  Internal DSL  a particular way of employing a general-purpose language, using only a small subset of the language's features  Language workbench  a specialized IDE for defining and building DSL, usually in a visual way, used both to determine the structure of the DSL and to provide an editing environment for people using it
  9. 9. DSL Types Comparison + learning curve ̶ syntactic noise + cost of building ̶ needs to be recompiled Internal DSL + programmers familiarity (if host language is static) + IDE support (autocompletion …) + composability + flexibility ̶ need to learn of grammars + readability and language parsing External DSL + clear separation between ̶ boundary between DSL business (DSL) and host language and host language + helpful when business code is ̶ easier to grow out of written by a separate team control (domain experts) Language + visual ̶ tools immaturity Workbench + rapid development ̶ vendor lock-in + IDE support for external DSL
  10. 10. What is an internal DSL? A (business) internal DSL is a fluent interface built on top of a clearly defined Command & Query API
  11. 11. The Command & Query API public interface Car { void setColor(Color color); void addEngine(Engine engine); void add Transmission(Transmission transmission); } public interface Engine { enum Type { FUEL, DIESEL, ELECTRIC, HYDROGEN, METHANE } void setType(Type type); void setPower(int power); void setCylinder(int cylinder); } public interface Transmission { enum Type { MANUAL, AUTOMATIC, CONTINOUSLY_VARIABLE } void setType(Type type); void setNumberOfGears(int gears); }
  12. 12. Let's build a car Car car = new CarImpl(); Car.setColor(Color.WHITE); Engine engine1 = new EngineImpl(); engine1.setType(Engine.Type.FUEL); engine1.setPower(73); engine1.setCylinder(4); car.addEngine(engine1); Engine engine2 = new EngineImpl(); engine2.setType(Engine.Type.ELECTRIC); engine2.setPower(60); car.addEngine(engine2); Transmission transmission = new TransmissionImpl(); transmission.setType(Transmission.Type.CONTINOUSLY_VARIABLE); car.setTransmission(transmission);
  13. 13. Quite good … … but you don't expect a (non-technical) domain expert to read this, don't you?
  14. 14. "Domain users shouldn't be writing code in our DSL but it must be designed for them to understand and validate“ Debasish Ghosh
  15. 15. Object Initialization new CarImpl() {{ color(Color.WHITE); + clear hierarchic structure engine(new EngineImpl {{ type(Engine.Type.FUEL); power(73); ̶ syntactial noise cylinder(4); }}); engine(new EngineImpl {{ ̶ explicit use of constructors type(Engine.Type.FUEL); power(60); }}); transmission(new TransmissionImpl {{ type(Transmission.Type.CONTINOUSLY_VARIABLE); }}); }}; + small implementation effort ̶ unclear separation between Command API and DSL
  16. 16. Functions Sequence car(); color(Color.WHITE); + lowest possible syntactic noise engine(); type(Engine.Type.FUEL); power(73); ̶ impossible to enforce right sequence cylinder(4); of global function invocation engine(); type(Engine.Type.ELECTRIC); power(60); ̶ use of global context variable(s) transmission(); type(Transmission.Type.CONTINOUSLY_VARIABLE); end(); + works well for defining the items of a (top level) list ̶ hierarchy defined only by identation convention
  17. 17. Methods Chaining car() .color(Color.WHITE) + object scoping .engine() .type(Engine.Type.FUEL) .power(73) .cylinder(4) + method names act as keyword argument .engine() .type(Engine.Type.ELECTRIC) .power(60) .transmission() + works good with optional parameter .type(Transmission.Type.CONTINOUSLY_VARIABLE) .end(); ̶ hierarchy defined only by identation convention
  18. 18. Nested Functions car( color(Color.WHITE), + no need for context variables transmission( type(Transmission.Type.CONTINOUSLY_VARIABLE), ), engine( ̶ higher punctuation noise type(Engine.Type.FUEL), power(73), ̶ arguments defined by position cylinder(4) rather than name ), engine( type(Engine.Type.ELECTRIC), ̶ rigid list of arguments or power(60) need of methods overloading ) ); ̶ inverted evaluation order + hierarchic structure is echoed by function nesting
  19. 19. Is my DSL good (concise, expressive, readable) enough? You cooked the meal … … now eat it! DSL design is an iterative process
  20. 20. Mixed Strategy car( nested function for top level object creation color(Color.WHITE), transmission() .type(Transmission.Type.CONTINOUSLY_VARIABLE), engine() .type(Engine.Type.FUEL) .power(73) .cylinder(4), method chaining for arguments definition engine() .type(Engine.Type.ELECTRIC) .power(60) ); function sequence for top level lists car( ... );
  21. 21. Advanced DSL examples
  22. 22. Hibernate Criteria Queries List cats = session .createCriteria(Cat.class) .add( Restrictions.like("name", "Fritz%") ) .add( Restrictions.between("weight", min, max) ) .addOrder( Order.desc("age") ) .setMaxResults(50) .list();
  23. 23. jMock Turtle turtle = context.mock(Turtle.class); // The turtle will be told to turn 45 degrees once only oneOf(turtle).turn(45); // The turtle can be told to flash its LEDs any number // of times or not at all allowing(turtle).flashLEDs(); // The turtle can be asked about its pen any number of times // and will always return PEN_DOWN allowing(turtle).queryPen(); will(returnValue(PEN_DOWN)); // The turtle will be told to stop at least once. atLeast(1).of(turtle).stop();
  24. 24. lambdaj Plain Java version: List<Car> automaticCars = new ArrayList<Car>(); for (Car car : cars) { if (car.getTransmission().getType() == Transmission.TYPE.AUTOMATIC) automaticCars.add(car); } lambdaj version: List<Sale> salesOfAFerrari = select(cars, having( on(Car.class).getTransmission().getType(), equalTo(Transmission.TYPE.AUTOMATIC) ));
  25. 25. Q A Mario Fusco mario.fusco@gmail.com Red Hat – Senior Software Engineer twitter: @mariofusco

×