Enviar pesquisa
Carregar
Von Java Zu Groovy
•
2 gostaram
•
3,070 visualizações
jlink
Seguir
WJAX 2007 Power Workshop mit Dierk König und Tammo Freese
Leia menos
Leia mais
Tecnologia
Denunciar
Compartilhar
Denunciar
Compartilhar
1 de 66
Recomendados
Java Script Ist Anders
Java Script Ist Anders
jlink
The Writing Initiative: Granted, Technology Makes Better Writers
The Writing Initiative: Granted, Technology Makes Better Writers
Kenneth Ronkowitz
Mehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch Skriptsprachen
jlink
Lehmanns Rails Erweitern
Lehmanns Rails Erweitern
jan_mindmatters
Tech Talk: Groovy
Tech Talk: Groovy
mwie
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
NETWAYS
Java und Go im Vergleich
Java und Go im Vergleich
QAware GmbH
Ruby on Rails SS09 04
Ruby on Rails SS09 04
Daniel Dengler
Recomendados
Java Script Ist Anders
Java Script Ist Anders
jlink
The Writing Initiative: Granted, Technology Makes Better Writers
The Writing Initiative: Granted, Technology Makes Better Writers
Kenneth Ronkowitz
Mehr Dynamik Durch Skriptsprachen
Mehr Dynamik Durch Skriptsprachen
jlink
Lehmanns Rails Erweitern
Lehmanns Rails Erweitern
jan_mindmatters
Tech Talk: Groovy
Tech Talk: Groovy
mwie
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
NETWAYS
Java und Go im Vergleich
Java und Go im Vergleich
QAware GmbH
Ruby on Rails SS09 04
Ruby on Rails SS09 04
Daniel Dengler
jBPM & Drools
jBPM & Drools
camunda services GmbH
Genügend gute Gründe, wieso Ruby besser als PHP ist
Genügend gute Gründe, wieso Ruby besser als PHP ist
Daniel Spangenberg
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Tim Furche
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
DevDay Dresden
2008 02 01 Zeller
2008 02 01 Zeller
CHOOSE
Let’s groove with Groovy
Let’s groove with Groovy
Thorsten Kamann
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
Reto Zahner
Production-ready Infrastruktur in 3 Wochen
Production-ready Infrastruktur in 3 Wochen
André Goliath
JsUnconf 2014
JsUnconf 2014
emrox
Microservices mit Rust
Microservices mit Rust
Jens Siebert
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
Frank Müller
Backend-Services mit Rust
Backend-Services mit Rust
Jens Siebert
Typ-sichere DSLs
Typ-sichere DSLs
Werner Keil
Ruby on Rails SS09 03
Ruby on Rails SS09 03
Daniel Dengler
DSLs in Scala & DB4O
DSLs in Scala & DB4O
Johannes Wachter
An Introduction to Ruby
An Introduction to Ruby
Jonathan Weiss
Automatisierte Linux Administration mit (R)?ex
Automatisierte Linux Administration mit (R)?ex
Jan Gehring
Mein paralleles Leben als Java-Entwickler
Mein paralleles Leben als Java-Entwickler
jlink
Agile08: Test Driven Ajax
Agile08: Test Driven Ajax
jlink
Behaviour-Driven Development
Behaviour-Driven Development
jlink
Mehr Dynamik Mit Groovy
Mehr Dynamik Mit Groovy
jlink
Automated Web 2.0 Testing
Automated Web 2.0 Testing
jlink
Mais conteúdo relacionado
Semelhante a Von Java Zu Groovy
jBPM & Drools
jBPM & Drools
camunda services GmbH
Genügend gute Gründe, wieso Ruby besser als PHP ist
Genügend gute Gründe, wieso Ruby besser als PHP ist
Daniel Spangenberg
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Tim Furche
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
DevDay Dresden
2008 02 01 Zeller
2008 02 01 Zeller
CHOOSE
Let’s groove with Groovy
Let’s groove with Groovy
Thorsten Kamann
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
Reto Zahner
Production-ready Infrastruktur in 3 Wochen
Production-ready Infrastruktur in 3 Wochen
André Goliath
JsUnconf 2014
JsUnconf 2014
emrox
Microservices mit Rust
Microservices mit Rust
Jens Siebert
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
Frank Müller
Backend-Services mit Rust
Backend-Services mit Rust
Jens Siebert
Typ-sichere DSLs
Typ-sichere DSLs
Werner Keil
Ruby on Rails SS09 03
Ruby on Rails SS09 03
Daniel Dengler
DSLs in Scala & DB4O
DSLs in Scala & DB4O
Johannes Wachter
An Introduction to Ruby
An Introduction to Ruby
Jonathan Weiss
Automatisierte Linux Administration mit (R)?ex
Automatisierte Linux Administration mit (R)?ex
Jan Gehring
Semelhante a Von Java Zu Groovy
(17)
jBPM & Drools
jBPM & Drools
Genügend gute Gründe, wieso Ruby besser als PHP ist
Genügend gute Gründe, wieso Ruby besser als PHP ist
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
2008 02 01 Zeller
2008 02 01 Zeller
Let’s groove with Groovy
Let’s groove with Groovy
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
JavaFX - 9. JUGR Stammtisch - 5. Mai 2011
Production-ready Infrastruktur in 3 Wochen
Production-ready Infrastruktur in 3 Wochen
JsUnconf 2014
JsUnconf 2014
Microservices mit Rust
Microservices mit Rust
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
Backend-Services mit Rust
Backend-Services mit Rust
Typ-sichere DSLs
Typ-sichere DSLs
Ruby on Rails SS09 03
Ruby on Rails SS09 03
DSLs in Scala & DB4O
DSLs in Scala & DB4O
An Introduction to Ruby
An Introduction to Ruby
Automatisierte Linux Administration mit (R)?ex
Automatisierte Linux Administration mit (R)?ex
Mais de jlink
Mein paralleles Leben als Java-Entwickler
Mein paralleles Leben als Java-Entwickler
jlink
Agile08: Test Driven Ajax
Agile08: Test Driven Ajax
jlink
Behaviour-Driven Development
Behaviour-Driven Development
jlink
Mehr Dynamik Mit Groovy
Mehr Dynamik Mit Groovy
jlink
Automated Web 2.0 Testing
Automated Web 2.0 Testing
jlink
AdvancedTdd
AdvancedTdd
jlink
XP Day Germany 2006 - Keynote
XP Day Germany 2006 - Keynote
jlink
Testgetriebene Softwareentwicklung
Testgetriebene Softwareentwicklung
jlink
Mais de jlink
(8)
Mein paralleles Leben als Java-Entwickler
Mein paralleles Leben als Java-Entwickler
Agile08: Test Driven Ajax
Agile08: Test Driven Ajax
Behaviour-Driven Development
Behaviour-Driven Development
Mehr Dynamik Mit Groovy
Mehr Dynamik Mit Groovy
Automated Web 2.0 Testing
Automated Web 2.0 Testing
AdvancedTdd
AdvancedTdd
XP Day Germany 2006 - Keynote
XP Day Germany 2006 - Keynote
Testgetriebene Softwareentwicklung
Testgetriebene Softwareentwicklung
Von Java Zu Groovy
1.
W-JAX Workshop
Von Java zu Groovy Dierk König Johannes Link Tammo Freese dierk.koenig@canoo.com business@johanneslink.net business@tammofreese.de
2.
Herzlich Willkommen!
Dierk König • Canoo Engineering AG, Basel (CH) • Rich Internet Applications Produkte, Projekte, Beratung, Schulung www.canoo.com • Trainer, Berater, Softwareentwickler • Groovy- und Grails-Committer • Autor: Groovy in Action © 2007 by Dierk König, Tammo Freese & Johannes Link
3.
Herzlich Willkommen!
Johannes Link • Unabhängiger Softwarecoach • johanneslink.net • Autor: Softwaretests mit Java © 2007 by Dierk König, Tammo Freese & Johannes Link
4.
Herzlich Willkommen!
Tammo Freese • Freiberuflicher Diplom-Informatiker • Extreme Programmer (Ruby/Java/...) • http://tammofreese.de © 2007 by Dierk König, Tammo Freese & Johannes Link
5.
Agenda • Groovy Übersicht
• Präsentation, Demo, Übung • Integration Java/Groovy • Präsentation, Demo, Übung • Meta-Programmierung in Groovy • Präsentation, Übung • Einfacher Testen • Präsentation, Übung • Einsatz von Groovy • Präsentation, Diskussion © 2007 by Dierk König, Tammo Freese & Johannes Link
6.
Groovy in der
Sprachlandschaft © 2007 by Dierk König, Tammo Freese & Johannes Link
7.
Dynamik ist mehr
als Scripting • Meta-Objekt-Protokoll • Auf original JDK Klassen Eigenschaften und Fähigkeiten arbeiten, aber trotzdem mehr zur Laufzeit dynamisch Funktionalität haben (GDK) hinzufügen oder ändern • Nie mehr „incomplete library smell“ • Methodenaufrufe abgreifen • Nicht nur Abhängigkeiten • Tracing und Debugging werden injizierbar, sondern • Mocks und Stubs auch Verhalten • Beliebige Methoden und und zwar „non-intrusive“! Eigenschaften bereitstellen • Patterns nur einmal schreiben • Ähnlich „AOP“ oder „Mixin“ • Vermeidet Code-Duplikation © 2007 by Dierk König, Tammo Freese & Johannes Link
8.
Groovy Bonbons • Volle
Objektorientierung • Closures keine primitiven Datentypen • GPath • Operatoren auf Objekten effiziente Objektnavigation selbst implementierbar • GroovyBeans • Multimethoden Properties und Events Dispatch am dynamischen Typ Deklaration und Zugriff • Klassifikatoren (grep, switch) • Literale Deklaration von Listen • Der ganze Rest (Arrays), Maps, Ranges und Templates, Builder, Swing, Ant, Regular Expressions Markup, XML, HTML, Parser, • Mächtige Operatoren [] SQL, XML-RPC, Windows • Interpolierte Strings (GString) Scripting, GORM, Grails, Unit Tests, Mocks,... © 2007 by Dierk König, Tammo Freese & Johannes Link
9.
Groovy Vorspeise System.out.println(quot;Hello World!quot;);
• optional ; () println 'Hello, World!' GDK method def vorname = 'Stefan' • Typ optional println quot;$vorname, ich hol' den Wagen.quot; • GString String lang = quot;quot;quot;Du, ${vorname}, der Wagen steht eine Zeile weiter.quot;quot;quot; • java.lang.String assert 0.5 == 1/2 • BigDecimal.equals def printSize(obj) { • optionales print obj?.size() duck typing } • safe dereferencing © 2007 by Dierk König, Tammo Freese & Johannes Link
10.
Regular Expressions if (quot;Hello
World!quot; =~ /Hello/) • Find operator if (quot;Hello World!quot; ==~ /Hellob.*/) • Match operator ~/Hellob.*/ • Pattern operator quot;Hello World!quot;.replaceAll(/w+/){ match -> • Replace mit match.size() berechneten } Werten -> 5 5! © 2007 by Dierk König, Tammo Freese & Johannes Link
11.
Listen, Maps, Ranges def
leer = [] def leer = [:] def voll = [1, 2, 'W-JAX'] def voll = [a: 1, b: 2] assert voll + voll == voll * 2 assert voll['a'] == 1 assert voll.a == 1 assert voll[0] == 1 assert voll[0..1] == [1, 2] voll.a = 2 assert voll == [a: 2, b: 2] voll[0..1] = [0, 1, 2, 3] assert voll == def inclusive = 'a'..'z' [0, 1, 2, 3, 'W-JAX'] inclusive.each {…} def exclusive = 0..<10 for (i in exclusive) {…} © 2007 by Dierk König, Tammo Freese & Johannes Link
12.
Closures 3.times { println
'Hi' } def houston(Closure machwas) { (10..1).each { countdown -> [0, 1, 2].each { number -> machwas(countdown) println number } } } [0, 1, 2].each { println it } houston { println it } def printit = { println it } [0, 1, 2].each printit new File('/data.txt').eachLine { println it } © 2007 by Dierk König, Tammo Freese & Johannes Link
13.
GroovyBeans und GPath class
Dir { assert root.dirs.name == String name ['a','b'] List dirs } assert root.dirs.name*.size() == [1, 1] def root = new Dir (name: '/', dirs: [ Dir.methods.name. new Dir (name: 'a'), grep(~/(g|s)et.*/) new Dir (name: 'b') -> [getName, setName, getDirs, ]) setDirs, …] assert root.dirs[0].name == 'a' © 2007 by Dierk König, Tammo Freese & Johannes Link
14.
Kontrollstrukturen if (1)
switch (10) { if (object) case 0 : println 'ist 0'; break if (list) case 0..9 :… case [8,9,11] :… for (item in iterable) { } case Float :… case {it%3 == 0}: … [a:1, b:2].each { key, value -> case ~/../ :… println quot;$key : $valuequot; default : } } throw, catch, finally implementiere isCase() while, eachWithIndex, eachLine © 2007 by Dierk König, Tammo Freese & Johannes Link
15.
Ausgewählte Methoden col.sort()
obj.find { } col.sort { a, b -> a <=> b } obj.findAll { } col.sort { a -> a.foo() } obj.grep (case) obj.findIndexOf { } +, -, *, <<, ==, [], []= remove(pos), remove(item), obj.collect { } removeAll(col), unique(), obj.each { } size(), pop(), flatten(), reverse() obj.eachWithIndex { item, i -> } intersect(col), disjoint(col), max(), min(), sum(), obj.every { } count(item), join(trenner), obj.any { } inject(start) { temp, item -> } © 2007 by Dierk König, Tammo Freese & Johannes Link
16.
Toolbox • Original Java
support für Profiling, Debugging, Code Coverage, etc. • IDE Integrations • Eclipse: eigene Arbeitsgruppe • IntelliJ IDEA: JetBrains • NetBeans: Sun Microsystems • Editoren Emacs, Vim, UltraEdit, Textmate, ... © 2007 by Dierk König, Tammo Freese & Johannes Link
17.
Demo I • Arbeiten
mit der groovyConsole • Erstelle Klasse Person mit Property name • Erstelle Liste von Person Objekten • Schreibe die Liste aller Namen, durch Komma getrennt • Suche nach Personen mit 'a' im Namen • Variationen © 2007 by Dierk König, Tammo Freese & Johannes Link
18.
Demo II •
Erweitere Person um 'tags' • Schreibe alle tags • Entferne Doppler • Sortiere nach Taglänge © 2007 by Dierk König, Tammo Freese & Johannes Link
19.
Übung I • Sortiere
die Liste von Personen nach der Anzahl ihrer tags • Geeks: Säuberungsaktion • Lösche alle Personen ohne Groovy tag • Ultra-Geeks: Tag quot;Cloudquot; • Sortiere die Liste eindeutiger tags nach ihrer Häufigkeit absteigend © 2007 by Dierk König, Tammo Freese & Johannes Link
20.
Integration von Groovy in
Java
21.
Groovy Objekte sind
Java Objekte • Egal ob Scripts oder Klassen, immer werden Objekte vom Typ java.lang.Class erzeugt • Verzahnung Compilezeit / Laufzeit • JVM Sicherheitsmodell • JVM Klassen sind geschlossen Groovy Klassen scheinen offen © 2007 by Dierk König, Tammo Freese & Johannes Link
22.
Direktmodus contra Precompiled •
Kompilation • groovyc -> *.class files • Cross-compiler behebt Henne-Ei Problem IDEs mit cross-compilation javac auch bald soweit? • Gemeinsame Interfaces sind trotzdem nützlich • Direktmodus fühlt sich an wie 'interpretiert', ist es aber nicht! © 2007 by Dierk König, Tammo Freese & Johannes Link
23.
Dynamische Evaluation zur
Laufzeit • Eval.x (users, quot;x.grep{ it.salary > 100000 }.address.townquot;); // me, x(), xy(), xyz() • GroovyShell, parse, binding, evaluate (String|File|Url) • GroovyScriptEngine für viele Sourcen und Pfadunterstützung • GroovyClassLoader (transparente Quellen, Security!) • Bean Scripting Framework und JSR-223 (Java 6) • Groovy Spring Beans © 2007 by Dierk König, Tammo Freese & Johannes Link
24.
Dynamisches Groovy mit Metaprogrammierung
25.
Methodenaufrufe in Java
und Groovy In Java: In Groovy: • Zur Übersetzungszeit wird • Zur Ausführungszeit wird festgelegt, welche Methode dynamisch ermittelt, auf welcher wie auf einen Methodenaufruf Vererbungshierarchie reagiert wird aufgerufen wird • Zur Ausführungszeit wird dynamisch ermittelt, wie auf einen Property-Zugriff reagiert wird © 2007 by Dierk König, Tammo Freese & Johannes Link
26.
Dynamischer Aufruf class X
{ def x = new X() def a = 1 def method, property def b = 2 method = 'foo' def foo () { assert 1 == x.quot;$methodquot;() 1 } method = 'bar' def bar () { assert 2 == x.quot;$methodquot;() 2 } property = 'a' } assert 1 == x.quot;$propertyquot; property = 'b' assert 2 == x.quot;$propertyquot; © 2007 by Dierk König, Tammo Freese & Johannes Link
27.
Multimethoden class MultiMethods {
def mm = new MultiMethods() def foo(String s) { 'string' } def foo(Object o) { 'object' }def arg = 'a string' def foo(Integer i) { 'integer' } assert 'string' == mm.foo(arg) } arg = 42 assert 'integer' == mm.foo(arg) class Complex { def real, im arg = [] boolean equals(Complex other) assert 'object' == mm.foo(arg) { this.real == other.real && assert new Complex(real:1.0, im:2.0) this.im == other.im .equals(new Complex(real:1.0, im:2.0)) } assert !new Complex(real:1.0,im:2.0) } .equals(new Object()) © 2007 by Dierk König, Tammo Freese & Johannes Link
28.
Kategorien class FooCategory {
• Kategorie: Klasse mit static def foo(List self, arg) { statischen Methoden self + [arg] } • Erstes Argument ist static def foo(String self, arg) { Empfänger der self + arg Methode } • Weitere Argumente } sind Parameter der Methode use(FooCategory) { assert [123].foo(456) == [123, 456] • Verwendung der assert '123'.foo('456') == '123456' Kategorie mittels } use(...) { ... } © 2007 by Dierk König, Tammo Freese & Johannes Link
29.
invokeMethod() class PrintMethodInvocations {
• Fängt Aufrufe nicht def invokeMethod(String name, args) { vorhandener Methoden println quot;Invoked $name with $argsquot; • Erstes Argument ist args.size() Name der Methode } } • Zweites Argument sind Parameter der Methode x = new PrintMethodInvocations() • Implementiert die Klasse assert 2 == x.foo(1,2) das Marker Interface assert 3 == x.bar('just', 'a', 'test') GroovyInterceptable, werden alle Methodenaufrufe gefangen! © 2007 by Dierk König, Tammo Freese & Johannes Link
30.
methodMissing() class PrintMissingMethods {
• Seit Groovy 1.1 def methodMissing(String name, args) { println quot;missing $name with $argsquot; args.size() • Wie invokeMethod() } } • Unterschied: Wird immer nur für fehlende x = new PrintMissingMethods() Methoden aufgerufen assert 2 == x.foo(1,2) • Empfehlung: Bei 1.1 assert 3 == x.bar('just', 'a', 'test') methodMissing() verwenden, falls möglich © 2007 by Dierk König, Tammo Freese & Johannes Link
31.
Methoden zur Laufzeit
hinzufügen (1) String.metaClass.upperCaseCount = { -> • Seit Groovy 1.1 (delegate =~ /[A-Z]/).size() } • Sogenannte assert 1 == quot;Onequot;.upperCaseCount() ExpandoMetaClass assert 2 == quot;TWoquot;.upperCaseCount() assert 3 == quot;ThReEquot;.upperCaseCount() • Methode definieren: Property der Metaklasse Integer.metaClass.'static'. auf eine Closure setzen, theAnswerToEverything = { -> 42 } fertig! assert 42 == Integer.theAnswerToEverything() • Auch Klassenmethoden können definiert werden © 2007 by Dierk König, Tammo Freese & Johannes Link
32.
Methoden zur Laufzeit
hinzufügen (2) ExpandoMetaClass.enableGlobally() • Defaultmäßig funktionieren ExpandoMetaClasses nicht Map.metaClass.toArray = { -> bei Vererbung delegate.collect { key, value -> [key, value] } • Kann aber eingeschaltet } werden assert [['a', 1], ['b', 2]] == • Dann können sogar auf [a:1, b:2].toArray() Interfaces Methoden für alle implementierenden Klassen definiert werden © 2007 by Dierk König, Tammo Freese & Johannes Link
33.
Wie passt das
alles zusammen? (1) • Groovy-Methodenaufruf: object.aMethod(arguments) bedeutet (vereinfacht) • Für Java-Objekte: MetaClassRegistry.getMetaClass(object.getClass()). invokeMethod(object, quot;aMethodquot;, arguments); • Für Groovy-Objekte: object.getMetaClass(). invokeMethod(object, quot;aMethodquot;, arguments); • Für Groovy-Objekte, die GroovyInterceptable implementieren: object.invokeMethod(quot;aMethod“); • Der Methodenaufruf wird also meist an eine Metaklasse delegiert © 2007 by Dierk König, Tammo Freese & Johannes Link
34.
Wie passt das
alles zusammen? (2) • Die Metaklasse • versucht, eine passende Methode in den Kategorien zu finden • versucht, eine passende Methode bei sich zu finden • ruft methodMissing() auf, falls keine Methode gefunden wurde • Methoden der Metaklasse (Auswahl) • invokeMethod(object, name, params); • invokeConstructor(params); • getProperty(object, name); • setProperty(object, name, value); © 2007 by Dierk König, Tammo Freese & Johannes Link
35.
Meta-Übungen © 2007 by
Dierk König, Tammo Freese & Johannes Link
36.
Einfacher Testen mit
Groovy
37.
Warum einfacher? •
assert ist eingebaut - und immer eingeschaltet • Einfacher: Literale Testdaten, Selektionen, Duplikationen vermeiden • class MyTest extends GroovyTestCase extends junit.framework.TestCase assertArrayEquals(..) assertLength(..) assertContains(..) assertScript(String script) shouldFail(exceptionType, closure) • Es ist möglich - und manchmal auch sinnvoll - Unit Tests für Java Code in Groovy zu schreiben © 2007 by Dierk König, Tammo Freese & Johannes Link
38.
Isolierte Unit Tests
im Objektgeflecht Ein »Unit Test« soll eine Klasse, ein Objekt oder eine Gruppe von Klassen und Objekten in Isolation testen • Problem: Programmeinheiten arbeiten nicht isoliert. • Aufbau der Testumgebung ist oft aufwändig • Testen von Ausnahmesituationen • langsame Tests bei Überschreiten der Systemgrenzen • Lösung: Für die Dauer der Tests ersetzen wir Abhängigkeiten zu mitwirkenden Units durch die Einführung einfacher »Attrappen« • Tests laufen schnell • Auftretende Fehler sind leicht zu lokalisieren • Geringer Aufwand für Aufbau der Testumgebung © 2007 by Dierk König, Tammo Freese & Johannes Link
39.
Attrappen im Test
TestCase ClassUnderTest <<interface>> Collaborator <<replacement>> RealCollaborator Collaborator Attrappe © 2007 by Dierk König, Tammo Freese & Johannes Link
40.
Wie testet man
euroAmount() ? public class EuroCalculator { private RateProvider provider; public void setProvider(RateProvider provider) { this.provider = provider; } public double euroAmount(double amount, String curr) { return amount * provider.getRate(curr, quot;EURquot;); } } public interface RateProvider { double getRate(String fromCurr, String toCurr); } © 2007 by Dierk König, Tammo Freese & Johannes Link
41.
Attrappe / Dummy
mit Java public class EuroCalculatorTest extends TestCase { public void testEuroAmount() { RateProvider provider = new DummyRateProvider(); EuroConverter calculator = new EuroCalculator(); calculator.setProvider(provider); assertEquals(7.5, converter.euroAmount(5.0, quot;CHFquot;), 0.001); } } public class DummyRateProvider implements RateProvider { public double getRate(String from, String to) { return 1.5; } } © 2007 by Dierk König, Tammo Freese & Johannes Link
42.
Einfaches Dummy-Objekt mit
Groovy class EuroCalculatorTest extends GroovyTestCase { def calculator = new EuroCalculator() void testEuroAmount() { calculator.provider = { from, to -> 1.5d } as RateProvider assert 7.5 == calculator.euroAmount(5.0, quot;CHFquot;) } } Wichtig: Anzahl der Closure-Parameter muss stimmen! © 2007 by Dierk König, Tammo Freese & Johannes Link
43.
Crash Test Dummies
class EuroCalculatorTest... void testEuroAmountWithUnknownCurrency() { def dummy = {from, to -> throw new IllegalArgumentException() } as RateProvider calculator.provider = dummy assert 0 == calculator.euroAmount(5.0, quot;XYZquot;) } void testProviderNotAvailable() { def dummy = {from, to -> throw new ProviderNotAvailableException() } as RateProvider calculator.provider = dummy shouldFail(EuroCalculatorException) { calculator.euroAmount(5.0, ”CHFquot;) } } © 2007 by Dierk König, Tammo Freese & Johannes Link
44.
Komplexere Attrappen (1)
interface RateProvider { double getRate(String from, String to) String providerName() } void testGetRateParametersAndProviderName() { def mock = [ providerName: {quot;open ratexquot;}, getRate: {from, to -> assert from == quot;CHFquot; assert to == quot;EURquot; 2.0d } ] as RateProvider assert quot;open ratexquot; == mock.providerName() assert 2.0d == mock.getRate(quot;CHFquot;, quot;EURquot;) } © 2007 by Dierk König, Tammo Freese & Johannes Link
45.
Komplexere Attrappen (2)
interface RateProvider { double getRate(String from, String to) } class ProviderMock implements RateProvider { def returns, expects double getRate(String from, String to) { assert expects.from == from assert expects.to == to return returns.rate } } void testStaticMock() { def mock = new ProviderMock( returns: [rate: 2.0d], expects: [from: quot;CHFquot;, to: quot;EURquot;] ) assert 2.0 == mock.getRate(quot;CHFquot;, quot;EURquot;) } © 2007 by Dierk König, Tammo Freese & Johannes Link
46.
Übung 4: Tests,
Tests, Tests Übung 4a Schreiben Sie einen Test, der überprüft, dass auch der quot;umgekehrtequot; (to- >from) Wechselkurs vom RateProvider ausreicht, falls der quot;richtigequot; (from->to) nicht vorhanden ist. Decken Sie mit dem Test den Fehler in der Implementierung auf und korrigieren Sie ihn! Übung 4b Schreiben Sie einen oder mehrere Tests, die überprüfen, dass bereits ermittelte Wechselkurse gecacht werden. Implementieren Sie anschließend diese Funktionalität im EuroCalculator! Übung 4c Schreiben Sie einen oder mehrere Tests, die überprüfen, dass gecachte Wechselkurse nach einer Stunde neu vom RateProvider geholt werden. Implementieren Sie anschließend diese Funktionalität im EuroCalculator! Anmerkung: Die Zeit ist im EuroCalculator über die timer-Property verfügbar © 2007 by Dierk König, Tammo Freese & Johannes Link
47.
Einsatz-Patterns für Groovy
48.
7 Patterns zum
Einsatz von Scripting • Alleskleber • Weiches Herz • Endoskopische Operation • Kluge Anpassung • Grenzenlose Offenheit • Heinzelmännchen • Prototyp © 2007 by Dierk König, Tammo Freese & Johannes Link
49.
#1 Alleskleber • Applikationen
aus bestehenden Komponenten zusammenbauen • Java ist gut geeignet für stabile Infrastruktur: Middleware, Frameworks, Widget Sets, Services • Scripting ist gut geeignet flexible (agile) Applikationslayer: View und Controller • Grails, GSP, JBoss Seam, WebWork, Struts 2 Actions,... • Beispiel: Zusammenzug von XML Parser, Java Networking und Swing Widget Bibliothek, um einen Standard-RSS Feed darzustellen © 2007 by Dierk König, Tammo Freese & Johannes Link
50.
Alleskleber Beispiel: RSS
Reader def base = 'http://news.bbc.co.uk/rss/newsonline_uk_edition/' def url = base +'front_page/rss091.xml' def items = new XmlParser().parse(url).channel[0].item def swing = new groovy.swing.SwingBuilder() def frame = swing.frame(title: 'Top 10 BBC News') { scrollPane { table() { tableModel(list: items[0..9]) { closureColumn(header: 'title', read: { item -> item.title.text() } ) closureColumn(header: 'text', read: { item -> item.description.text() } ) } } } } frame.pack(); frame.show() © 2007 by Dierk König, Tammo Freese & Johannes Link
51.
#2 Weiches Herz •
Fachliche Modelle auslagern • Vorgegebenes Applikationsgerüst in Java • Fachlichen Erkenntnisfortschritt ermöglichen: Entitäten, Beziehungen und Verhalten durch Scripting flexibel halten • Anwender: Rule Engines (JBoss Rules, groovyrules.dev.java.net, JSR-94), Grails, Versicherungswesen: Mutual of Omaha • Beispiel: Berechnungsregeln für Boni © 2007 by Dierk König, Tammo Freese & Johannes Link
52.
Weiches Herz Beispiel:
Bonusberechnung umsatz = mitarbeiter.umsatz switch(umsatz / 1000) { case 0..100 : return umsatz * 0.04 case 100..200 : return umsatz * 0.05 case {it > 200} : bonusClub.add(mitarbeiter) return umsatz * 0.06 } Binding binding = new Binding(); binding.setVariable(quot;mitarbeiterquot;, mitarbeiter); binding.setVariable(quot;bonusClubquot;, bonusClub); GroovyShell shell = new GroovyShell(binding); File script = new File(filename); float bonus = (float) shell.evaluate(script); © 2007 by Dierk König, Tammo Freese & Johannes Link
53.
#3 Endoskopische Operation •
Minimal-invasive Eingriffe quot;in vivoquot; • Viele Notwendigkeiten für Anpassungen ad-hoc Anfragen sind nicht vorhersehbar • Schlüsselloch für die Live Ausführung von Scripts • Unglaublich wertvoll für Produkt-Support, Fehleranalyse, Hot-Fixes, Notfälle • Anwender: Oracle JMX Beans, XWiki, SnipSnap, Ant, Canoo WebTest, Grails Console, ULC Admin Console • Beispiel: ein Live-Groovy Servlet © 2007 by Dierk König, Tammo Freese & Johannes Link
54.
Endoskopische Operation: im
Servlet Probleme mit der Datenbank Verbindung? def ds = Config.dataSource ds.connection = new DebugConnection(ds.connection) Gefährliche Benutzer rauswerfen users = servletContext.getAttribute('users') bad = users.findAll { user -> user.cart.items.any { it.price < 0 } } servletContext.setAttribute('users', users - bad) © 2007 by Dierk König, Tammo Freese & Johannes Link
55.
#4 Kluge Anpassung •
Konfigurationen mit Ausführungs-Logik, aka Smart Configuration • Ersatz für XML-Konfigurationen • Mit Referenzen, Schleifen, Bedingungen, Vererbung, Ausführungslogik, Umgebungsermittlung, ... • Typischer Anwendungsfall für domänen-spezifische Sprachen (DSLs), Groovy Builder, Grails plugins, Benutzer-Macros, Function Plotter • Beispiel: Navis SPARCS N4 © 2007 by Dierk König, Tammo Freese & Johannes Link
56.
Smart Config Beispiel:
Container Routing def ensureEvent = { change -> if (! event.getMostRecentEvent(change) { event.postNewEvent(change) } } switch (event.REROUTE_CTR) { case 'OutboundCarrierId' : ensureEvent('CHANGE_VSL') break case 'POD' : if (! event.CHANGE_VSL) ensureEvent('CHANGE_POD') break } © 2007 by Dierk König, Tammo Freese & Johannes Link
57.
#5 Grenzenlose Offenheit •
Jede Zeile Code wird änderbar • Manchmal sind die vorgesehenen Variationspunkte nicht ausreichend • Einfache Änderungen ohne langwierigen Setup für Kompilation und Deployment • Perl, PHP, Python, etc. machen es vor • Beispiel: groovyblogs.org (Grails Applikation) © 2007 by Dierk König, Tammo Freese & Johannes Link
58.
#6 Heinzelmännchen • Repetitive
Aufgaben automatisieren • Automatisierter Build, kontinuierliche Integration, Deployment, Installationen, Server-Überwachung, Reports, Statistiken, Erzeugen von Dokumentation, funktionale Tests, HTML Scraping, Web Fernbedienung, XML-RPC, WebServices • Anwendungen mit Ant, Maven, AntBuilder, Gant, Canoo WebTest, Grails scaffolding, ... • Beispiele: dynamisch Mails per Ant verschicken, Skripte mit Ant verbinden © 2007 by Dierk König, Tammo Freese & Johannes Link
59.
Heinzelmännchen Beispiel: Mail
schicken def users = [ [name:'Dierk', email:'dierk.koenig@canoo.com'], [name:'Other', email:'other@no.such.server'] ] def ant = new AntBuilder() for (user in users) { ant.mail(mailhost: 'my.email.server', subject: 'build ist fertig') { from(address: 'my@email.com') to (address: user.email) message( quot;quot;quot; Hallo ${user.name}, Der Build ist mal wieder fertig: ${new Date().toGMTString()} quot;quot;quot; ) } } © 2007 by Dierk König, Tammo Freese & Johannes Link
60.
Heinzelmännchen II: Musisches
Ant <groovy> import org.apache.tools.ant.* import org.jfugue.* project.addBuildListener(new PlayListener()) class PlayListener implements BuildListener { def play = { new Player().play(new Pattern(it)) } void buildStarted(event) { } void buildFinished(event) { } void messageLogged(event) { } void targetStarted(event) { play(quot;D Equot;) } void targetFinished(event) { play(quot;C5majquot;) } void taskStarted(event) { } void taskFinished(event) { } } </groovy> © 2007 by Dierk König, Tammo Freese & Johannes Link
61.
#7 Prototyp • Machbarkeitsstudien
auf der Zielplattform • quot;Spikesquot; für technologische oder algorithmische Ideen mit besserer Ausdrucksmächtigkeit, schnellerem Feedback und besseren Analysemöglichkeiten • Wahlmöglichkeit für spätere (Teil-)Portierung nach Java • Anwendungen: Benutzerfeedback über Domänenmodell mit funktionalem Grails Prototyp abfragen, Java Bildbearbeitungs- Algorithmen • Beispiel: Primzahlzerlegung © 2007 by Dierk König, Tammo Freese & Johannes Link
62.
Prototyp Beispiel: Primzahlzerlegung
boolean isPrime(x) { return ! (2..<x).any { y -> x % y == 0 } } int primeBelow(x) { (x..1).find { isPrime(it) } } List primeFactors(x) { if (isPrime(x)) return [x] int p = primeBelow(x) while (p > 1) { if (x % p == 0) return [p, *primeFactors(x.intdiv(p))] p = primeBelow(p-1) } } for (n in 100..110) { println quot;$n : quot;+primeFactors(n)} © 2007 by Dierk König, Tammo Freese & Johannes Link
63.
Primzahlzerlegung: Modulo ops
zählen class ModCountCategory { static int count = 0 static int mod(Integer self, Integer argument) { count++ return self - argument * self.intdiv(argument) } } use (ModCountCategory) { for (n in 1000..1010) { ModCountCategory.count = 0 factors = primeFactors(n) println quot;$n : $factorsquot;.padRight(30) + quot;(in quot; + quot;${ModCountCategory.count}quot;.padLeft(5) + quot; steps)quot; assert n == factors.inject(1){result, item -> result *= item } } } © 2007 by Dierk König, Tammo Freese & Johannes Link
64.
Pattern Zusammenfassung •
Alleskleber • Weiches Herz • Endoskopische Operation • Kluge Anpassung • Grenzenlose Offenheit • Heinzelmännchen • Prototyp Keep groovin' ! © 2007 by Dierk König, Tammo Freese & Johannes Link
65.
Weitere Informationen • groovy.codehaus.org •
grails.org • Groovy in Action groovy.canoo.com/gina Manning, 2007, Vorwort von James Gosling König mit Glover, Laforge, King, Skeet • + Groovy Recipes © 2007 by Dierk König, Tammo Freese & Johannes Link
66.
Offene Fragen © 2007
by Dierk König, Tammo Freese & Johannes Link