Post on 26-May-2015
description
transcript
Type-safe DSLs
Using Xtext/TS, Xtend, Groovy and other languages
Werner Keil
Eclipse DemoCamp Hamburg
14th June 2012
AVOIDING ARITHMETIC OR TYPE ERRORS IN A DSL
Our Goal
2 © 2007-2012 Creative Arts & Technologies
Overview
• Introduction• What is a DSL?• Internal and External DSLS• Type-Safety
•Units and Healthcare• Unit-API, UOMo
• UCUM, HL7, Groovy used by Healthcare
•Other Languages• Jython/WLST• Xtext/Xbase/Xtend• Scala, Fantom, F#
•Demo•Q&A3 © 2007-2012 Creative Arts & Technologies
Who am I?
4 © 2007-2012 Creative Arts & Technologies
Werner Keil
• Consultant – Coach
• Creative Cosmopolitan
• Open Source Evangelist
• Software Architect
• Java Godfather
• …
Twitter @wernerkeil
What is a DSL?
•A DSL is a computer language (specification, modeling, programming) tailored to a particular domain. But, what is a domain?
•DSL examples: SQL, CSS, Sawzall (Google)
•Gains in expressiveness and ease of use (the future could be end-user programming)
•Gains in productivity •Reduced maintenance costs
5 © 2007-2012 Creative Arts & Technologies
What is a Domain?
6 © 2007-2012 Creative Arts & Technologies
Implementation
Specification
Requirements
Deployment
Business
SystemsReal-Time
Systems
Aircraft
control
systems
Patient Management
Systems
Insurance
Management
Systems
Internal Domain Specific Languages
•These are languages built using the syntactic elements of the underlying language
• In the case of Java, building a DSL using Java classes and methods
•With other JVM-based languages, that’s usually similar, Java code generated in many cases
7 © 2007-2012 Creative Arts & Technologies
External Domain Specific Languages•External DSLs
• Written in a different language than the main (host) language of the application
• Transformed into it using some form of compiler or interpreter
•May include• XML configuration files• Plain text configuration files• Full-blown languages
8 © 2007-2012 Creative Arts & Technologies
Type-Safety
•Java does not have strongly typed primitive types (like e.g. Ada language).
•For performance reasons most developer prefer primitive types over objects in their interface.
•Primitives type arguments often lead to name clashes (methods with the same signature)
9 © 2007-2012 Creative Arts & Technologies
What do these disasters have in common?•Patriot MissileThe cause was an inaccurate calculation of the time since boot due to a computer arithmetic error.
•Ariane 5 ExplosionThe floating point number which a value was converted from had a value greater than what would be represented by a 16 bit signed integer.
10 © 2007-2012 Creative Arts & Technologies
• Gimli Glider (near disaster)Fuel loading was miscalculated through misunderstanding of the recently adopted Metric System, replacing the Imperial System
• Mars Orbiter Preliminary findings indicate that one team used English units (e.g. inches, feet and pounds) while the other used metric units for a key spacecraft operation.
• NASA lost a $125 million Mars orbiter because a Lockheed Martin engineering team used English units of measurement while the agency's team used the more conventional metric system for a key spacecraft operation
• This also underlines the added risk when 3rd party contractors are involved or projects are developed Offshore
What do these disasters have in common?
11 © 2007-2012 Creative Arts & Technologies
Unit Tests wouldn‘t find these…
•All previous example illustrate three categories of errors difficult to find through Unit Testing:
• Interface Errors (e.g. millisecond/second, radian/degree, meters/feet).
• Arithmetic Errors (e.g. overflow).
• Conversion Errors.
Despite their name
17 © 2007-2012 Creative Arts & Technologies
SQL Example with ErrorsStringBuilder sql = new StringBuilder();
sql.append("SELECT o.sum,(SELECT first_name,last_name");
sql.append(" FROM person p");
sql.append(" WHERE o.person_id=p.id) AS client");
sql.append(" FROM order o");
sql.append("WHERE o.id = "+orderId);
sql.append(" AND o.status_code IN (?,?)");
PreparedStatement stmt = conn.prepareStatement(sql.toString());
stmt.setString(1, "PAID");
//...
19 © 2007-2012 Creative Arts & Technologies
Typesafe SQL ExamplePerson p = new Person();
List<Tuple<String, Integer, Date>> rows =
new QueryBuilder(datasource)
.from(p)
.where(gt(p.height, 170))
.select(p.name, p.height, p.birthday)
.list();
for (Tuple<String, Integer, Date> row : rows) {
String name = row.v1;
Integer height = row.v2;
Date birthday = row.v3;
System.out.println(
name + " " + height + " " + birthday);
}
20 © 2007-2012 Creative Arts & Technologies
Results with
Same Dimension Different Dimension
Binary Operations Binary Operations
add(double) or (long) root(int)
multiply(double) or (long) power(int)
divide(double) or (long) multiply(Unit)
compound(Unit) divide(Unit)
Unary Operations
inverse()
Unit-API | Operations
Unified Code for Units of Measure
The Unified Code for Units of Measure is inspired byand heavily based on
• ISO 2955-1983
• ANSI X3.50-1986
• HL7's extensions called ISO+
UOMo UCUM
25 © 2007-2012 Creative Arts & Technologies
HL7 DSL
26 © 2007-2012 Creative Arts & Technologies
def mySegment = ... // assignment to another NK1 segment instance
def group = message.PATIENT_RESULT(0).PATIENT
group.NK1(0) = 'abc' // syntax error!
msg1.NK1(0) = mySegment // syntax error!
msg1.NK1(0).from(mySegment) // works!
def nk1 = message.PATIENT_RESULT(0).PATIENT.NK1(0)
def otherNk1 = message.PATIENT_RESULT(0).PATIENT.NK1(0)
nk1[4] = otherNk1[4] // copy address
nk1[4][4] = otherNk1[4][4] // copy state or province only
nk1[4][4].from(otherNk1[4][4])// equivalent
nk1[4][4] = 'NY' // set state or province directly
DEMO
Healthcare DSL with Groovy
Jython
28 © 2007-2012 Creative Arts & Technologies
/** * Java calculator class that contains two simple methods */
public class Calculator {
public Calculator(){ }
public double calculateTip(double cost, double tipPercentage) {
return cost * tipPercentage;
}
public double calculateTax(double cost, double taxPercentage) {
return cost * taxPercentage;
}
}
Jython (2)
29 © 2007-2012 Creative Arts & Technologies
import Calculator
from java.lang import Math
class JythonCalc(Calculator):
def __init__(self):
pass
def calculateTotal(self, cost, tip, tax):
return cost + self.calculateTip(tip) + self.calculateTax(tax)
if __name__ == "__main__":
calc = JythonCalc()
cost = 23.75
tip = .15
tax = .07
print "Starting Cost: ", cost
print "Tip Percentage: ", tip
print "Tax Percentage: ", tax
print Math.round(calc.calculateTotal(cost, tip, tax))
Jython (3)
30 © 2007-2012 Creative Arts & Technologies
Starting Cost: 23.75
Tip Percentage: 0.15
Tax Percentage: 0.07
29
Result
DEMO
Xtext Examples
Scala, Fantom, F#
•Scala• Functional programming language. Type-safe, as the company driving it was
called.• Very popular for DSLs
•Fantom• Functional programming language• Units of Measurement support built in.• Runs on both JVM and CLR
•F#• Functional programming language• Units of Measurement support built in.
33 © 2007-2012 Creative Arts & Technologies
DEMO
Scala and Fantom Examples
Eclipse – Project UOMo
http://www.eclipse.org/uomo/
Units of Measurement API
http://www.unitsofmeasurement.org
UCUM
http://www.unitsofmeasure.org
Links
OpenHealth Project
http://www.openhealth.org
Groovy DSL Example
http://groovy.dzone.com/news/domain-specific-language-unit-
Jython
http://www.jython.org
Links (2)
Xtext
http://www.eclipse.org/xtext
Scala DSLs
http://www.scala-lang.org/node/1403
Fantom
http://fantom.org/
Links (3)
Q & ALet‘s talk
Contact
werner@catmedia.us
or
uomo@catmedia.us
Twitter: @wernerkeil
Hashtag #EclipseUOMo