SlideShare a Scribd company logo
DSL	101_
Alexander	(Sascha)	Klein
1
About	me
Alexander	(Sascha)	Klein
Branchmanager	Stuttgart
codecentric	AG
Heßbrühlstr.	7
70565	Stuttgart
	+49	172	529	40	20
	alexander.klein@codecentric.de
	www.codecentric.de
	blog.codecentric.de
	@saschaklein
2
What	are	DSLs?
3
Definition
Domain	Specific	Language
programming	language
to	target	a	specific	problem	area
at	the	same	level	of	abstraction	as	the	problem	domain
using	a	tongue	related	to	the	problem	domain
4
Examples
SQL	-	to	create,	edit	and	query	relational	database	systems
Ant-File	-	to	define	a	build-process
SELECT	*	FROM	USERS;
<project	name="MyProject"	default="dist"	basedir=".">
		<description>	simple	example	build	file	</description>
		<target	name="init">
				<tstamp/>
				<mkdir	dir="${build}"/>
		</target>
		<target	name="compile"	depends="init"	description="compile	the	source">
				<javac	srcdir="${src}"	destdir="${build}"/>
		</target>
</project>
5
Examples	2
CSS	-	to	specify	the	look	and	feel	of	a	webpage
SwingBuilder	-	to	define	Swing-UI’s	in	a	declarative	way
p.info	{
	 font-family:	arial,	sans-serif;
	 line-height:	150%;
}
p.info	span	{
	 font-weight:	bold;
}
p.info	span::after	{
	 content:	":	";
}
sb	=	new	groovy.swing.SwingBuilder()
frame	=	sb.frame(title:	"Click",	size:	[200,	100],
				defaultCloseOperation:	WindowConstants.EXIT_ON_CLOSE)	{
		panel()	{
				button	("Red",	foreground:	Color.RED,
								actionPerformed:	{println	"Red	clicked"})
				button	("Blue",	foreground:	Color.BLUE,
								actionPerformed:	{println	"Blue	clicked"})
		}
}
frame.visible	=	true 6
Types	of	DSL’s
internal
external
non-textual
eg.	Scratch
CC	BY-SA	3.0	http://commons.wikimedia.org/wiki/File:Scratch_Hello_World.png
7
Why	DSL’s
expressive	and	concise	syntax
increases	readability	through	higher	abstraction	level
simplify	development	with	different	skill	levels
integration	of	business	domain	members	into	development
8
Creating	DSLs
9
Scopes	of	DSLs
Command
Closure
@groovy.transform.builder.Builder
class	User	{
				String	name
				int	age
}
println	User.builder().name('Sascha	Klein').age(43).build()				
def	user	=	new	User()
Closure	dsl	=	{
				name	=	'Sascha	Klein'
				age	=	43
}
dsl.resolveStrategy	=	Closure.DELEGATE_FIRST				
dsl.delegate	=	user				
dsl()
println	user
10
Scopes	of	DSLs	2
Script
Script
myscript.groovy
Custom	ScriptBase
Usage
@groovy.transform.BaseScript	UserBaseScript	script				
name	'Sascha	Klein'
age	43
abstract	class	UserBaseScript	extends	Script	{
				@Delegate	User	user	=	new	User()
}
def	cl	=	new	GroovyClassLoader()
Script	script	=	cl.parseClass(new	File('myscript.groovy')).newInstance()				
script.run()
println	script.user
11
Scopes	of	DSLs	3
alternative	way:
Script
myscript.groovy
Usage
name	'Sascha	Klein'
age	43
import	org.codehaus.groovy.control.CompilerConfiguration
def	config	=	new	CompilerConfiguration(scriptBaseClass:	'UserBaseScript')				
def	cl	=	new	GroovyClassLoader(getClass().classLoader,	config)															
Script	script	=	cl.parseClass(new	File('myscript.groovy')).newInstance()
script.run()
println	script.user
12
Script	binding
undefined	variables	access	the	Script’s	binding
'injecting'	variables	and	functions
myscript.groovy
myVar	=	100
println	myVar	//	100
Binding	binding	=	new	Binding()																								
binding.setVariable('myVar',	50)																							
binding.setVariable('myFunc',	{	it.toUpperCase()	})				
Script	script	=	cl.parseClass(new	File('myscript.groovy')).newInstance()
script.setBinding(binding)																													
script.run()
name	myFunc('Sascha	Klein')
age	myVar
13
Command	chains
turn	left	then	right
turn(left).then(right)
take	2.pills	of	aspirin	after	6.hours
take(2.pills).of(aspirin).after(6.hours)
check	that:	margarita	tastes	good
check(that:	margarita).tastes(good)
given	{}	when	{}	then	{}
given({}).when({}).then({})
14
Command	chains	2
please	show	the	square_root	of	100
please(show).the(square_root).of(100)
show	=	{	println	it	}
square_root	=	{	Math.sqrt(it)	}
def	please(action)	{
				new	Object()	{
								Map<String,	Closure>	the(Closure	what)	{				
								}
												[of:	{	n	->	action(what(n))	}]										
				}
}
15
Command	chains	3
split	"a	,_b	,c__"	on	','	trimming	'_'
split("a	,_b	,c__").on(',').trimming('_')
@Grab('com.google.guava:guava:r09')
import	com.google.common.base.*
Splitter.on(',')
				.trimResults(CharMatcher.is('_'	as	char))
				.split("_a	,_b_	,c__")
				.iterator()
				.toList()
@Grab('com.google.guava:guava:r09')
import	com.google.common.base.*
def	split(string)	{
				[on:	{	separator	->															
								[trimming:	{	trimChar	->						
												Splitter.on(separator)
																.trimResults(CharMatcher.is(trimChar	as	char))
																.split(string)
																.iterator()
																.toList()
								}]
				}]
}
16
Method	and	Property	access
Collect	all	key,	value	pairs	in	a	Map:
Intercept	all	method	calls
Caution:
methodMissing	will	be	called	from	invokeMethod
name	'Sascha'
age	43
myProperty	1.2345
abstract	class	MyBaseScript	extends	Script	{
				Map	data	=	[:]
				def	methodMissing(String	name,	args)	{
								data[name]	=	args
				}
}
class	Interception	implements	GroovyInterceptable	{
				def	invokeMethod(String	name,	Object	args)	{	...	}
}
17
Method	and	Property	access	2
Collect	all	key,	value	pairs	in	a	Map:
Intercept	all	property	access
Caution:
propertyMissing	will	be	called	from	get/setProperty
name	=	'Sascha'
age	=	43
myProperty	=	1.2345
abstract	class	MyBaseScript	extends	Script	{
				Map	data	=	[:]
				def	propertyMissing(String	name,	value)	{
								data[name]	=	value
				}
				def	propertyMissing(String	name)	{
								return	data[name]
				}
}
def	getProperty(String	name)	{	...	}
void	setProperty(String	name,	value)	{	...	}
18
MetaClasses
6.pills	calls	6.getPills()
You	have	to	add	getPills	to	the	class	Integer
All	classes	have	a	MetaClass
It	manages	all	properties	and	methods	of	a	class
static	and	dynamic
All	calls	will	be	redirected	through	the	MetaClass
19
Usage	of	MetaClasses
adding	a	method	to	an	existing	class
adding	a	property
Integer.metaClass.getPills	=	{->	[new	Pill()]	*	delegate	}				
assert	3.getPills().every{	it	instanceof	Pill	}
def	storage	=	Collections.synchronizedMap([:])
String.metaClass.getName	=	{->
				return	storage[System.identityHashCode(delegate)	+	"name"]
}
String.metaClass.setName	=	{	String	name	->
				storage[System.identityHashCode(delegate)	+	"name"]	=	name
}
def	test	=	"Test"
test.name	=	"Sascha"
assert	test.name		==	"Sascha"
assert	''.name	==	null
20
Operator	overloading
order	icecream	&	suncream	when	temperature	>	20
order(icecream	&	suncream).when(temperature	>	20)
def	suncream	=	"suncream"
def	icecream	=	"icecream"
def	temperature	=	30
String.metaClass.and	=	{a	->	delegate	+	"	and	"+	a}
def	order	=	{	what	->
				[	when:	{	condition	->
								println	condition	?	what	:	"nothing	to	order"
						}
				]
}
21
Operator	overloading	2
Operator Method Operator Method
a	+	b a.plus(b) -a a.negative()
a	-	b a.minus(b) +a a.positive()
a	*	b a.multiply(b) a++,	++a a.next(b)
a	/	b a.div(b) a--,	--a a.previous(b)
a	%	b a.mod(b) a	==	b a.equals(b)
a	|	b a.or(b) a	!=	b !a.equals(b)
a	<	b a.compareTo(b)<0 a	>	b a.compareTo(b)>0
a	<=	b a.compareTo(b)<=0 a	>=	b a.compareTo(b)>=0
a[b] a.getAt(b) a[b]	=	c a.setAt(b,	c)
~a a.bitwiseNegate(b) a**b a.power(b)
a	in	b a.isCase(b) a	as	b a.asType()
a	<=>	b a.compareTo(b) 22
Extension	Modules
StringHelper.groovy
META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
To	use	multiple	extensionClasses,	separate	them	with	commas
class	StringHelper	{
				static	String	low(String	string)	{
								return	string.toLowerCase()
				}
}
moduleName	=	my-module
moduleVersion	=	1.0
extensionClasses	=	StringHelper
assert	"test"	==	"TeSt".low()
23
AST	transformations
AST	=	abstract	syntax	tree
AST	transformation
manipulating	AST	to	add	or	modify	classes	at	compiletime
local:	triggered	by	an	annotation
global:	always	active	when	registered
most	flexible	instrument
enables	syntaxes	otherwise	not	possible
can	be	used	to	change	the	result	from	ground	up
changes	get	'melted'	into	byte	code
grants	best	IDE	support
24
AST	transformations	2
local	AST-transformations
Annotation
astNodes	contains
AnnotationNode	triggeringAnnotation
Node	annotatedNode
@Retention	(RetentionPolicy.SOURCE)
@Target	([ElementType.METHOD])
@GroovyASTTransformationClass	("MyTransformation")
public	@interface	MyAnnotation	{
				String	value()	default	"this	is	the	default	value"
}
package	my.pkg
@GroovyASTTransformation(phase	=	CompilePhase.CANONICALIZATION)
class	MyTransformation	implements	ASTTransformation	{
				void	visit(ASTNode[]	astNodes,	SourceUnit	sourceUnit)	{	...	}
}
class	MyClass	{
				@MyAnnotation	void	doit()	{	...	}
}
25
AST	transformations	3
global	AST-transformations
ignore	astNodes	parameter
they	have	to	be	part	of	the	classpath
and	have	to	be	registered
META-INF/services/org.codehaus.groovy.transform.ASTTransformation
Groovy	2.5+:	Macros	simplify	AST	transformation	creation
my.pkg.MyTransformation
my.pkg.MySecondTransformation
26
Using	DSLs
27
Embedding	DSLs
GroovyShell
using	CompilationConfiguration
Binding	binding	=	new	Binding()
binding.setVariable("foo",	2)
GroovyShell	shell	=	new	GroovyShell(binding)									
Object	value	=	shell.evaluate(new	File('my.dsl'))				
assert	value	==	20
assert	binding.getVariable("x")	==	123
...
import	org.codehaus.groovy.control.CompilerConfiguration
def	config	=	new	CompilerConfiguration(scriptBaseClass:	'MyBaseScript')				
GroovyShell	shell	=	new	GroovyShell(config,	binding)																							
...
28
Embedding	DSLs	2
GroovyClassLoader
using	CompilationConfiguration
def	cl	=	new	GroovyClassLoader()
Script	script	=	cl.parseClass(new	File('my.dsl')).newInstance()				
script.run()
println	script.user
import	org.codehaus.groovy.control.CompilerConfiguration
def	config	=	new	CompilerConfiguration(scriptBaseClass:	'MyBaseScript')				
def	cl	=	new	GroovyClassLoader(getClass().classLoader,	config)													
...
29
Embedding	DSLs	3
GroovyScriptEngine
using	CompilationConfiguration
import	groovy.lang.Binding
import	groovy.util.GroovyScriptEngine
String[]	roots	=	[	"/my/groovy/script/path",	"/my/other/script/path"	]
GroovyScriptEngine	gse	=	new	GroovyScriptEngine(roots)				
Binding	binding	=	new	Binding()
binding.setVariable("foo",	2)
gse.run("mydsl.groovy",	binding)																										
...
import	org.codehaus.groovy.control.CompilerConfiguration
def	config	=	new	CompilerConfiguration(scriptBaseClass:	'MyBaseScript')				
GroovyScriptEngine	gse	=	new	GroovyScriptEngine(roots)
gs.config	=	config																																																									
...
30
CompilerConfiguration
ScriptBaseClass
ASTTransformationCustomizer
Default	imports
import	org.codehaus.groovy.control.CompilerConfiguration
import	groovy.util.logging.Log
def	config	=	new	CompilerConfiguration()
config.addCompilationCustomizers(new	ASTTransformationCustomizer(Log))				
def	config	=	new	CompilerConfiguration()
def	imports	=	new	ImportCustomizer()
imports.addImport('my.pkg.MyClass')				
imports.addStarImports('java.time')				
config.addCompilationCustomizers(imports)
31
CompilerConfiguration	2
SecureASTCustomizer
SourceAwareCustomizer
def	secureAstCust	=	new	SecureASTCustomizer()
secureAstCust.methodDefinitionAllowed	=	false																													
secureAstCust.statementsBlacklist	=	[SwitchStatement,	AssertStatement]				
def	variableNames	=	{	expr	->
				if	(expr	instanceof	VariableExpression)	{
								!	expr.variable[0]	in	['_',	'$']
				}	else	{	return		true	}
}	as	ExpressionChecker
secureAstCust.addExpressionCheckers(variableNames)																								
config.addCompilationCustomizers(secureAstCust)
def	imports	=	new	ImportCustomizer()
imports.addImport('my.pkg.MyClass')
def	sac	=	new	SourceAwareCustomizer(imports)											
sac.extensionValidator	=	{	ext	->	ext	==	'dsl'	}							
config.addCompilationCustomizers(sac)
32
CompilerConfiguration	3
CompilerCustomizationBuilder
CompilerCustomizationBuilder.withConfig(configuration)		{
				ast(groovy.util.logging.Log)
				ast(includeNames:	true,	groovy.transform.ToString)
				imports	{
								normal	'my.pkg.MyClass'
								star	'java.time'
				}
				def	variableNames	=	{	expr	->
								if	(expr	instanceof	VariableExpression)	{
												!	expr.variable[0]	in	['_',	'$']
								}	else	{	return		true	}
				}	as	ExpressionChecker
				secureAst	{
								addExpressionCheckers	variableNames
								methodDefinitionAllowed	false
								statementsBlacklist	=	[SwitchStatement,	AssertStatement]
				}
				source(extensions:	['dsl'])	{
								imports	{
												normal	'my.pkg.MyClass'
								}
				}
}
33
Compiler	Configuration	Script
config.groovy
build.gradle
import	org.codehaus.groovy.control.customizers.ImportCustomizer
def	imports	=	new	ImportCustomizer()
imports.addImports('org.some.*')
configuration.addCompilationCustomizers(imports)
>>	groovyc	--configscript	pathto/config.groovy
compileGroovy.groovyOptions.configurationScript=file('pathto/config.groovy')
34
Best	practices
35
How	to	design	a	DSL
minimalistic
expose	only	the	behaviour	needed
distilled
remove	all	nonessential	details
extensibel
designed	in	a	way	extensions	have	minimal	impact	on	users
36
Syntax	checking
ExpressionCheckers
can	be	mighty,	but	complex
@TypeChecked	/	@CompileStatic
most	dynamic	features	will	fail
you	have	to	help	the	compiler
37
@DelegatesTo
email	{
				from	'dsl-guru@mycompany.com'
				to	'john.doe@waitaminute.com'
				subject	'The	pope	has	resigned!'
				body	'Really,	the	pope	has	resigned!'
}
class	EmailSpec	{
				void	from(String	from)	{	println	"From:	$from"}
				void	to(String...	to)	{	println	"To:	$to"}
				void	subject(String	subject)	{	println	"Subject:	$subject"}
				void	body(Strig	body)	{	println	body	}
}
def	email(Closure	cl)	{
				def	email	=	new	EmailSpec()
				def	code	=	cl.clone()
				code.delegate	=	email
				code.resolveStrategy	=	Closure.DELEGATE_ONLY
				return	code()
}
38
@DelegatesTo	2
compilation	fails
specification	of	email-Closure	unknown	to	parser
Now	the	compilation	is	successful
@groovy.transform.TypeChecked	//	or	@groovy.transform.CompileStatic
void	sendEmail()	{
				email	{
								from	'dsl-guru@mycompany.com'
								to	'john.doe@waitaminute.com'
								subject	'The	pope	has	resigned!'
								body	'Really,	the	pope	has	resigned!'
				}
}
def	email(@DelegatesTo(EmailSpec)	Closure	cl)	{				
				...
}
def	email(@DelegatesTo(strategy=Closure.DELEGATE_ONLY,				
																							value=EmailSpec)	Closure	cl)	{					
				...
}
39
@DelegatesTo	3
Delegate	to	a	parameter
def	exec(Object	target,	Closure	code)	{
			def	clone	=	code.clone()
			clone.delegate	=	target
			return	clone()
}
class	Greeter	{
			void	sayHello()	{	println	'Hello'	}
}
def	greeter	=	new	Greeter()
exec(greeter)	{
			sayHello()
}
def	exec(@DelegatesTo.Target	Object	target,	@DelegatesTo	Closure	code)	{				
			def	clone	=	code.rehydrate(target,	this,	this)
			clone()
}
40
@DelegatesTo	4
Delegate	to	a	generic	type
For	other	cases	write	a	@TypeChecked	extension
public	<T>	void	configure(List<T>	elements,	Closure	configuration)	{
			elements.each	{	T	element	->
						def	clone	=	configuration.rehydrate(element,	this,	this)
						clone.resolveStrategy	=	Closure.DELEGATE_FIRST
						clone.call()
			}
}
@groovy.transform.ToString
class	Realm	{
				String	name
}
List<Realm>	list	=	[new	Realm()]	*	3
configure(list)	{	name	=	'My	Realm'	}
assert	list.every	{	it.name	==	'My	Realm'	}
public	<T>	void	configure(
				@DelegatesTo.Target	List<T>	elements,																														
				@DelegatesTo(strategy=Closure.DELEGATE_FIRST,																						
																	genericTypeIndex=0)	Closure	configuration)	{	...	}				
http://docs.groovy-lang.org/next/html/documentation/type-checking- 41
Execution	control
@groovy.transform.ThreadInterrupt
adds	thread	interruption	checks	after
loops	(for,	while)
first	instruction	of	a	method
first	instruction	of	a	closure	body
@groovy.transform.TimedInterrupt
interrupts	after	the	given	time
@groovy.transform.ConditionalInterrupt
interrupts	after	the	given	closure	returns	true
42
Dependency	management
Grape
GRoovy	Adaptable	Packaging	Engine
Addable	via	ASTTransformationCustomizer
@Grab(group='org.springframework',
						module='spring-orm',
						version='3.2.5.RELEASE')
import	org.springframework.jdbc.core.JdbcTemplate
@Grab('org.springframework:spring-orm:3.2.5.RELEASE')
import	org.springframework.jdbc.core.JdbcTemplate
@Grapes([
				@Grab(group='commons-primitives',
										module='commons-primitives',
										version='1.0'),
				@Grab(group='org.ccil.cowan.tagsoup',
										module='tagsoup',
										version='0.9.7')
])
43
Errorhandling
Give	detailed	information
clear	message
file,	line
GroovyShell	shell	=	new	GroovyShell()
try	{
				Object	value	=	shell.evaluate	'''	prinln	123	'''
}	catch(ex)	{
				def	ste	=	ex.stackTrace.find	{
								!(it.declaringClass.startsWith("org.codehaus.groovy.")	||
								it.declaringClass.startsWith("groovy.")	||
								it.declaringClass.startsWith("java."))
				}
				println	"Error	at	$ste.fileName(line	$ste.lineNumber):	$ex.message"
}
44
IDE	Support
IntelliJ	IDEA	supports
@DelegatesTo
@BaseScript
GroovyDSL	Script:	.gdsl
abstract	class	UserBaseScript	extends	Script	{
				@Lazy	User	user	=	{	new	User()	}()
				def	methodMissing(String	name,	args)	{
								user."$name"	=	args
				}
}
@groovy.transform.BaseScript	UserBaseScript	script
name	'Sascha	Klein'
age	43
http://www.tothenew.com/blog/gdsl-awesomeness-introduction-to-gdsl-in-
intellij-idea/
45
Questions?
Alexander	(Sascha)	Klein
Branchmanager	Stuttgart
codecentric	AG
Heßbrühlstr.	7
70565	Stuttgart
	+49	172	529	40	20
	alexander.klein@codecentric.de
	www.codecentric.de
	blog.codecentric.de
	@saschaklein
46

More Related Content

Similar to DSL101

Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday SloveniaContinuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Dr. John Tunnicliffe
 
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday SloveniaContinuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Dr. John Tunnicliffe
 
BlueClosure - Brochure 2016
BlueClosure - Brochure 2016BlueClosure - Brochure 2016
BlueClosure - Brochure 2016Matteo Meucci
 
Intro to-ant
Intro to-antIntro to-ant
Intro to-ant
Manav Prasad
 
SQL Bits: Containers and Clones
SQL Bits: Containers and ClonesSQL Bits: Containers and Clones
SQL Bits: Containers and Clones
Alex Yates
 
Cssdoc
CssdocCssdoc
Cssdoc
Maideoz
 
Introducing U-SQL (SQLPASS 2016)
Introducing U-SQL (SQLPASS 2016)Introducing U-SQL (SQLPASS 2016)
Introducing U-SQL (SQLPASS 2016)
Michael Rys
 
Intro to MVC 3 for Government Developers
Intro to MVC 3 for Government DevelopersIntro to MVC 3 for Government Developers
Intro to MVC 3 for Government DevelopersFrank La Vigne
 
android sqlite
android sqliteandroid sqlite
android sqliteDeepa Rani
 
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing ItYou Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
Aleksandr Yampolskiy
 
Spring 4.0 - Evolution or Revolution
Spring 4.0 - Evolution or RevolutionSpring 4.0 - Evolution or Revolution
Spring 4.0 - Evolution or Revolution
Raffael Schmid
 
Windows Azure through the eyes of an it pro
Windows Azure through the eyes of an it proWindows Azure through the eyes of an it pro
Windows Azure through the eyes of an it proMike Martin
 
Create a landing page
Create a landing pageCreate a landing page
Create a landing page
Fabien Vauchelles
 
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
Wolfgang Strasser
 
Future-proof Development for Classic SharePoint
Future-proof Development for Classic SharePointFuture-proof Development for Classic SharePoint
Future-proof Development for Classic SharePoint
Bob German
 
Generating Code with Oracle SQL Developer Data Modeler
Generating Code with Oracle SQL Developer Data ModelerGenerating Code with Oracle SQL Developer Data Modeler
Generating Code with Oracle SQL Developer Data Modeler
Rob van den Berg
 
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Cathrine Wilhelmsen
 
Azure presentation nnug dec 2010
Azure presentation nnug  dec 2010Azure presentation nnug  dec 2010
Azure presentation nnug dec 2010
Ethos Technologies
 
Design Systems, Pattern Libraries & WordPress
Design Systems, Pattern Libraries & WordPressDesign Systems, Pattern Libraries & WordPress
Design Systems, Pattern Libraries & WordPress
Jesse James Arnold
 

Similar to DSL101 (20)

Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday SloveniaContinuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
 
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday SloveniaContinuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
Continuous Integration and the Data Warehouse - PASS SQL Saturday Slovenia
 
Day2
Day2Day2
Day2
 
BlueClosure - Brochure 2016
BlueClosure - Brochure 2016BlueClosure - Brochure 2016
BlueClosure - Brochure 2016
 
Intro to-ant
Intro to-antIntro to-ant
Intro to-ant
 
SQL Bits: Containers and Clones
SQL Bits: Containers and ClonesSQL Bits: Containers and Clones
SQL Bits: Containers and Clones
 
Cssdoc
CssdocCssdoc
Cssdoc
 
Introducing U-SQL (SQLPASS 2016)
Introducing U-SQL (SQLPASS 2016)Introducing U-SQL (SQLPASS 2016)
Introducing U-SQL (SQLPASS 2016)
 
Intro to MVC 3 for Government Developers
Intro to MVC 3 for Government DevelopersIntro to MVC 3 for Government Developers
Intro to MVC 3 for Government Developers
 
android sqlite
android sqliteandroid sqlite
android sqlite
 
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing ItYou Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
You Too Can Be a Radio Host Or How We Scaled a .NET Startup And Had Fun Doing It
 
Spring 4.0 - Evolution or Revolution
Spring 4.0 - Evolution or RevolutionSpring 4.0 - Evolution or Revolution
Spring 4.0 - Evolution or Revolution
 
Windows Azure through the eyes of an it pro
Windows Azure through the eyes of an it proWindows Azure through the eyes of an it pro
Windows Azure through the eyes of an it pro
 
Create a landing page
Create a landing pageCreate a landing page
Create a landing page
 
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
Professional Recycling - SSIS Custom Control Flow Components With Visual Stud...
 
Future-proof Development for Classic SharePoint
Future-proof Development for Classic SharePointFuture-proof Development for Classic SharePoint
Future-proof Development for Classic SharePoint
 
Generating Code with Oracle SQL Developer Data Modeler
Generating Code with Oracle SQL Developer Data ModelerGenerating Code with Oracle SQL Developer Data Modeler
Generating Code with Oracle SQL Developer Data Modeler
 
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
 
Azure presentation nnug dec 2010
Azure presentation nnug  dec 2010Azure presentation nnug  dec 2010
Azure presentation nnug dec 2010
 
Design Systems, Pattern Libraries & WordPress
Design Systems, Pattern Libraries & WordPressDesign Systems, Pattern Libraries & WordPress
Design Systems, Pattern Libraries & WordPress
 

More from sascha_klein

Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shell
sascha_klein
 
GroovyFX - groove JavaFX Gr8Conf EU 2017
GroovyFX - groove JavaFX Gr8Conf EU 2017GroovyFX - groove JavaFX Gr8Conf EU 2017
GroovyFX - groove JavaFX Gr8Conf EU 2017
sascha_klein
 
Bob the Builder - Gr8Conf EU 2017
Bob the Builder - Gr8Conf EU 2017Bob the Builder - Gr8Conf EU 2017
Bob the Builder - Gr8Conf EU 2017
sascha_klein
 
GroovyFX - Groove JavaFX
GroovyFX - Groove JavaFXGroovyFX - Groove JavaFX
GroovyFX - Groove JavaFX
sascha_klein
 
Using Groovy with Jenkins
Using Groovy with JenkinsUsing Groovy with Jenkins
Using Groovy with Jenkins
sascha_klein
 
Introduction to Graphics- and UI-Design
Introduction to Graphics- and UI-DesignIntroduction to Graphics- and UI-Design
Introduction to Graphics- and UI-Design
sascha_klein
 
Android on Groovy
Android on GroovyAndroid on Groovy
Android on Groovy
sascha_klein
 
Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shell
sascha_klein
 
Groovy on the Shell
Groovy on the ShellGroovy on the Shell
Groovy on the Shell
sascha_klein
 
Vert.x using Groovy - Simplifying non-blocking code
Vert.x using Groovy - Simplifying non-blocking codeVert.x using Groovy - Simplifying non-blocking code
Vert.x using Groovy - Simplifying non-blocking code
sascha_klein
 

More from sascha_klein (10)

Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shell
 
GroovyFX - groove JavaFX Gr8Conf EU 2017
GroovyFX - groove JavaFX Gr8Conf EU 2017GroovyFX - groove JavaFX Gr8Conf EU 2017
GroovyFX - groove JavaFX Gr8Conf EU 2017
 
Bob the Builder - Gr8Conf EU 2017
Bob the Builder - Gr8Conf EU 2017Bob the Builder - Gr8Conf EU 2017
Bob the Builder - Gr8Conf EU 2017
 
GroovyFX - Groove JavaFX
GroovyFX - Groove JavaFXGroovyFX - Groove JavaFX
GroovyFX - Groove JavaFX
 
Using Groovy with Jenkins
Using Groovy with JenkinsUsing Groovy with Jenkins
Using Groovy with Jenkins
 
Introduction to Graphics- and UI-Design
Introduction to Graphics- and UI-DesignIntroduction to Graphics- and UI-Design
Introduction to Graphics- and UI-Design
 
Android on Groovy
Android on GroovyAndroid on Groovy
Android on Groovy
 
Groovy on the shell
Groovy on the shellGroovy on the shell
Groovy on the shell
 
Groovy on the Shell
Groovy on the ShellGroovy on the Shell
Groovy on the Shell
 
Vert.x using Groovy - Simplifying non-blocking code
Vert.x using Groovy - Simplifying non-blocking codeVert.x using Groovy - Simplifying non-blocking code
Vert.x using Groovy - Simplifying non-blocking code
 

Recently uploaded

GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 

Recently uploaded (20)

GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 

DSL101