• Save
Mehr Dynamik Mit Groovy
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Mehr Dynamik Mit Groovy

on

  • 6,036 views

Problems with Java and how dynamic scripting languages (especially Groovy) tackle some of them. A short introduction to some aspects of Groovy is included.

Problems with Java and how dynamic scripting languages (especially Groovy) tackle some of them. A short introduction to some aspects of Groovy is included.

Statistics

Views

Total Views
6,036
Views on SlideShare
6,030
Embed Views
6

Actions

Likes
2
Downloads
0
Comments
0

1 Embed 6

http://www.slideshare.net 6

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

Mehr Dynamik Mit Groovy Presentation Transcript

  • 1. Groovy Mehr Dynamik bei der Java- Entwicklung
  • 2. Wer ich bin...
  • 3. Wer ich bin... Mein eigener Chef (Extremer) Softwareentwickler (Agiler) Coach Testgetrieben http://johanneslink.net
  • 4. Java-Frust
  • 5. Java-Frust public class Person... public String getName() { return name; }
  • 6. Java-Frust public class Person... public String getName() { return name; } public static List<Person> sortByName(Set<Person> people) { List<Person> sortedResult = new ArrayList<Person>(people); Comparator<Person> nameComparator = new Comparator<Person>() { public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; }
  • 7. Java-Frust public class Person... public String getName() { return name; } public static List<Person> sortByName(Set<Person> people) { List<Person> sortedResult = new ArrayList<Person>(people); Comparator<Person> nameComparator = new Comparator<Person>() { public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; } public class FinancialInstrument... public String getName() { return name; }
  • 8. Java-Frust public class Person implements Namable... public String getName() { return name; } public static List<Person> sortByName(Set<Person> people) { List<Person> sortedResult = new ArrayList<Person>(people); Comparator<Person> nameComparator = new Comparator<Person>() { public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; } public class FinancialInstrument implements Namable... public String getName() { return name; }
  • 9. Java-Frust public class Person implements Namable... public String getName() { return name; } public class MyHelper... public static List<Person> Namable> List<T> sortByName(Set<T> namables) { public static <T extends sortByName(Set<Person> people) { List<Person> sortedResult = ArrayList<T>(namables); List<T> sortedResult = new new ArrayList<Person>(people); Comparator<Person> nameComparator = Comparator<T>() { Comparator<T> nameComparator = new new Comparator<Person>() { public int compare(Person T o2) { public int compare(T o1, o1, Person o2) { return o1.getName().compareTo(o2.getName()); return o1.getName().compareTo(o2.getName()); } } }; }; Collections.sort(sortedResult, nameComparator); Collections.sort(sortedResult, nameComparator); return sortedResult; return sortedResult; } } public class FinancialInstrument implements Namable... public String getName() { return name; }
  • 10. Java-Frust public class Person... public String getName() { return name; } public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; } public class FinancialInstrument... public String getName() { return name; }
  • 11. Java-Frust public class Person... public String getName() { return name; } public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { Collection sortByName return o1.getName().compareTo(o2.getName()); self sort: [:each | each name] }; } Collections.sort(sortedResult, nameComparator); return sortedResult; } public class FinancialInstrument... public String getName() { return name; }
  • 12. Typische Java Smells public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; }
  • 13. Typische Java Smells public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; }
  • 14. Typische Java Smells public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; }
  • 15. Typische Java Smells public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; }
  • 16. Typische Java Smells public class MyHelper... public static <T extends Namable> List<T> sortByName(Set<T> namables) { List<T> sortedResult = new ArrayList<T>(namables); Comparator<T> nameComparator = new Comparator<T>() { public int compare(T o1, T o2) { return o1.getName().compareTo(o2.getName()); } }; Collections.sort(sortedResult, nameComparator); return sortedResult; } • Variables Verhalten erfordert eigene (anonyme) Klasse • Incomplete Library Smell • Statische Typisierung erzwingt viele gemeinsame Interfaces • Unvorhergesehenes Veränderung => Neukompilierung
  • 17. Die Rettung naht: Dynamische Skriptsprachen • Scripting • Dynamik
  • 18. Scripting • Knappe und ausdrucksstarke Syntax • Ausführung von Programmcode ohne (spürbare) Compilierung • Selbstständige Skripte • Aus einer Applikation heraus
  • 19. Scripting • Knappe und ausdrucksstarke Syntax • Ausführung von Programmcode ohne (spürbare) Compilierung • Selbstständige Skripte • Aus einer Applikation heraus List<Person> people = new ArrayList<Person>(); people.add(new Person(quot;Dierkquot;)); ... List<Person> sorted = (List<Person>) Eval.x(people, quot;x.sort {it.name}quot; );
  • 20. Scripting • Knappe und ausdrucksstarke Syntax • Ausführung von Programmcode ohne (spürbare) Compilierung • Selbstständige Skripte • Aus einer Applikation heraus List<Person> people = new ArrayList<Person>(); people.add(new Person(quot;Dierkquot;)); ... List<Person> sorted = (List<Person>) Eval.x(people, quot;x.sort {it.name}quot; );
  • 21. Dynamik • Dynamische Typisierung • Closures • Meta-Programmierung
  • 22. Dynamische Typisierung aka „Duck Typing“ def sortByName(unsorted) { unsorted.sort {it.name} } def people = [ new Student(quot;Johannesquot;), new Person(quot;Dierkquot;) ] def sorted = sortByName(people) assert sorted[0].name == quot;Dierkquot; assert sorted[1].name == quot;Johannesquot;
  • 23. Closures (1) Programmlogik als vollwertiges Objekt def sorter = { unsorted -> unsorted.sort {it.name} } def sorted = sorter(people) //oder so: def sorted = sorter.call(people)
  • 24. Closures (2) • Iteration als typischer Anwendungsfall
  • 25. Closures (2) • Iteration als typischer Anwendungsfall def namen = [quot;Johannesquot;, quot;Frankquot;, quot;Dierkquot;] def auswahl = namen.findAll {name -> name.contains quot;nquot;} assert auswahl == [quot;Johannesquot;, quot;Frankquot;]
  • 26. Closures (2) • Iteration als typischer Anwendungsfall def namen = [quot;Johannesquot;, quot;Frankquot;, quot;Dierkquot;] def auswahl = namen.findAll {name -> name.contains quot;nquot;} assert auswahl == [quot;Johannesquot;, quot;Frankquot;] List<String> auswahl = new ArrayList<String>(); for (String name : namen) { if (name.contains(quot;nquot;)) { auswahl.add(name); } } Äquivalenter Java Code
  • 27. Meta-Programmierung • Erweiterung existierender Klassen • Hinzufügen von Methoden zur Laufzeit • Erweiterung / Veränderung der Sprache durch Verwendung eines „Meta Object Protocol“
  • 28. Meta Object Protocol „A metaobject protocol (MOP) is an interpreter of the semantics of a program that is open and extensible“ (Wikipedia) class MyObject { def prop void setProperty(String name, value) { prop = value } def getProperty(String name) { prop } } def obj = new MyObject() obj.firstName = quot;Johannesquot; obj.lastName = quot;Linkquot; assert obj.firstName == quot;Linkquot;
  • 29. Meta Object Protocol „A metaobject protocol (MOP) is an interpreter of the semantics of a program that is open and extensible“ (Wikipedia) Class.metaClass.'static'.create = { Object[] args -> delegate.metaClass.invokeConstructor(*args) } assert new ArrayList() == ArrayList.create() assert new HashMap() == HashMap.create() assert new Integer(42) == Integer.create(42) assert new Dimension(1,1) == Dimension.create(1,1)
  • 30. Vorteile / Nachteile dynamischer Skriptsprachen • Vorteile: • Weniger Code • Weniger Duplikation • Verständlichere Abstraktionen • Mehr Deployment-Optionen
  • 31. Vorteile / Nachteile dynamischer Skriptsprachen • Vorteile: • Weniger Code • Weniger Duplikation • Verständlichere Abstraktionen • Mehr Deployment-Optionen • Nachteile: • Erschwerte statische Codeanalyse • Schlechtere Performance
  • 32. Welche Skriptsprachen gibt es? • Verbreiteste Skriptsprachen: Perl, PHP, Python, Ruby, JavaScript • Mehr als 200 verschiedene Sprachen allein auf der Java VM: Groovy, JRuby, Scala, Bistro ...
  • 33. Groovy in der Sprachlandschaft Text (c) Dierk König
  • 34. Groovy
  • 35. Groovy • Volle Objekt- Orientierung ohne primitive Typen
  • 36. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung
  • 37. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung • Closures
  • 38. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung • Closures • Listen und Maps als Literale
  • 39. Groovy • Volle Objekt- • Volle Integration Orientierung ohne mit der Java- primitive Typen Plattform • Optionale statische • Generics Typisierung • Annotations • Closures • Security-Model • Listen und Maps als Literale
  • 40. Groovy • Volle Objekt- • Volle Integration Orientierung ohne mit der Java- primitive Typen Plattform • Optionale statische • Generics Typisierung • Annotations • Closures • Security-Model • Listen und Maps • Wird (immer) in als Literale echten Bytecode kompiliert
  • 41. Groovy - Vereinfachte Syntax System.out.println(quot;Hello World!quot;); //Java style println 'Hello, World!' def vorname = 'Stefan' println quot;$vorname, ich hol' den Wagen.quot; String lang = quot;quot;quot;Du, ${vorname}, der Wagen steht eine Zeile weiter.quot;quot;quot; assert 0.5 == 1/2 def printSize(obj) { print obj?.size() } printSize(null) -> null
  • 42. Reguläre Ausdrücke assert (quot;Hello World!quot; =~ /Hello/) // Find-Operator assert (quot;Hello World!quot; ==~ /Hellob.*/) // Match-Operator def pattern = ~/.*ll.*/ // java.util.regex.Pattern.compile(quot;.*ll.*quot;) assert [quot;halloquot;, quot;helloquot;, quot;holaquot;].grep(pattern) == [quot;halloquot;, quot;helloquot;] def coded = quot;Hallo, JUG Cologne!quot;.replaceAll(/w+/){ match -> match.size() } assert coded == quot;5, 3 7!quot;
  • 43. Listen, ... def leer = [] def voll = [1, 2, 'JUGC'] assert voll + voll == voll * 2 assert voll[0] == 1 assert voll[0..1] == [1, 2] voll[0..1] = [0, 1, 2, 3] assert voll == [0, 1, 2, 3, 'JUGC'] assert voll[2..-1] == [2, 3, 'JUGC']
  • 44. ... Maps und Ranges def leer = [:] def voll = [a: 1, b: 2] assert voll['a'] == 1 assert voll.a == 1 voll.a = 2 assert voll == [a: 2, b: 2] def inclusive = 'a'..'z' inclusive.each {c -> print c} def exclusive = 0..<10 for (i in exclusive) {print i}
  • 45. Groovy Beans & GPath class Person { def name def kinder = [] } def johannes = new Person(name: quot;Johannesquot;) assert johannes.name == quot;Johannesquot;
  • 46. Groovy Beans & GPath class Person { def name def kinder = [] } def johannes = new Person(name: quot;Johannesquot;) assert johannes.name == quot;Johannesquot; johannes.kinder += new Person(name: quot;Jannekquot;) johannes.kinder += new Person(name: quot;Niklasquot;) assert johannes.kinder.size() == 2 assert johannes.kinder[0].name == quot;Jannekquot;
  • 47. Groovy Beans & GPath class Person { def name def kinder = [] } def johannes = new Person(name: quot;Johannesquot;) assert johannes.name == quot;Johannesquot; johannes.kinder += new Person(name: quot;Jannekquot;) johannes.kinder += new Person(name: quot;Niklasquot;) assert johannes.kinder.size() == 2 assert johannes.kinder[0].name == quot;Jannekquot; assert johannes.kinder.name == [quot;Jannekquot;, quot;Niklasquot;] assert johannes.kinder.kinder*.size() == [0, 0]
  • 48. Groovy -Closures def to = quot;JUGSquot; def say = { msg -> msg + quot;, $toquot; } assert say(quot;Halloquot;) == quot;Hallo, JUGSquot; to = quot;JUG Colognequot; assert say(quot;Halloquot;) == quot;Hallo, JUG Colognequot; (1..10).each { println it } [a:1, b:2].each { key, value -> println quot;key: $key, value: $valuequot; }
  • 49. Java VM <-> Groovy
  • 50. Java VM <-> Groovy • Groovy-Klassen können beliebig auf Java-Klassen zugreifen • und umgekehrt!
  • 51. Java VM <-> Groovy • Groovy-Klassen können beliebig auf Java-Klassen zugreifen • und umgekehrt! • Es werden immer Klassen im Bytecode erzeugt • Egal ob Scripts oder Klassen • Egal ob vorkompiliert oder zur Laufzeit
  • 52. Vorkompilierter Groovy-Code • groovyc -> *.class files • groovyc -jointCompilation behebt Henne-Ei-Problem • Auslieferung meist als JAR • groovy-all-x.y.z.jar mitausliefern
  • 53. Dynamische Evaluation zur Laufzeit
  • 54. Dynamische Evaluation zur Laufzeit • Eval.x(users, quot;x.grep{ it.salary -> 100000 }.address.townquot;); // me, x(), xy(), xyz()
  • 55. 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)
  • 56. 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
  • 57. 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!)
  • 58. 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)
  • 59. 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
  • 60. Dynamik & Metaprogrammierung • Dynamischer Methodenaufruf und Hooks • Kategorien • Methoden zur Laufzeit hinzufügen
  • 61. Methodenaufrufe in Java und Groovy In Java: In Groovy: • Zur Übersetzungszeit • Zur Ausführungszeit wird festgelegt, welche wird dynamisch Methode ermittelt, auf welcher wie auf einen Vererbungshierarchie Methodenaufruf aufgerufen wird reagiert wird • Zur Ausführungszeit wird dynamisch ermittelt, wie auf einen Property- Zugriff reagiert wird
  • 62. Dynamischer Aufruf class X { def x = new X() def a = 1 def methodName, propName def b = 2 def foo () { methodName = 'foo' 3 assert 3 == x.quot;$methodNamequot;() } } propName = 'a' assert 1 == x.quot;$propNamequot; propName = 'b' assert 2 == x.quot;$propNamequot;
  • 63. methodMissing() class PrintMissingMethods { def methodMissing(String name, args) { println quot;missing $name with $argsquot; args.size() } } x = new PrintMissingMethods() assert 2 == x.foo(1,2) -> missing foo with {1, 2} assert 3 == x.bar('just', 'a', 'test') -> missing bar with {quot;justquot;, quot;aquot;, quot;testquot;}
  • 64. Kategorien class FooCategory { • Kategorie: Klasse static def foo(List self, arg) { mit statischen self + [arg] Methoden } • 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(...) { ... }
  • 65. Methoden zur Laufzeit hinzufügen String.metaClass.upperCaseCount = { -> • Sogenannte (delegate =~ /[A-Z]/).size() ExpandoMetaClass } • Methode definieren: assert 1 == quot;Onequot;.upperCaseCount() Property der assert 2 == quot;TWoquot;.upperCaseCount() Metaklasse auf eine assert 3 == quot;ThReEquot;.upperCaseCount() Closure setzen, fertig! Integer.metaClass.'static'. answerToEverything = { -> 42 } • Auch assert 42 == Integer.answerToEverything() Klassenmethoden können definiert werden ExpandoMetaClass.enableGlobally() Object.metaClass.tate = { -> 42 } • Auch Vererbung assert 42 == new X().tate() funktioniert
  • 66. Was gibt es noch? • XML-Support eingebaut • Builder-Konzept (z.B. SwingBuilder) • Nahtlose Ant-Integration • Testen leicht gemacht • Web-Applikationen mit Grails (= Spring + Hibernate + Groovy) • ...
  • 67. Wie entwickle ich Groovy-Programme? • groovysh • groovyConsole • IDE-Support • IDEA IntelliJ • Eclipse • NetBeans
  • 68. Einsatzmuster für Scripting (von Dierk König) • Alleskleber • Weiches Herz • Kluge Anpassung • Endoskopische Operation • Grenzenlose Offenheit • Heinzelmännchen • Prototyp
  • 69. Einsatzmuster: Alleskleber • Applikationen aus bestehenden Komponenten zusammenbauen • Java ist gut geeignet für stabile Infrastruktur: Middleware, Frameworks, Widget Sets, Services • Scripting ist gut geeignet für flexible View- und Controller-Schichten (z.B. Grails)
  • 70. Alleskleber Demo: RSS Reader • Zusammenbau von XML Parser, Java Networking und Swing Widget Bibliothek, um einen Standard-RSS Feed darzustellen
  • 71. Einsatzmuster: Weiches Herz • Fachliche Modelle auslagern bei vorgegebenem Java-Applikationsgerüst • Fachlichen Erkenntnisfortschritt ermöglichen: Entitäten, Beziehungen und Verhalten bleiben durch Scripting flexibel • Verhaltensänderung zur Laufzeit
  • 72. 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 }
  • 73. 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); BigDecimal bonus = (BigDecimal) shell.evaluate(script);
  • 74. Einsatzmuster: Kluge Anpassung • Konfigurationen mit Ausführungs-Logik als Ersatz für XML-Konfigurationen • Mit Referenzen, Schleifen, Bedingungen, Vererbung, Ausführungslogik, Umgebungsermittlung, ... • Typischer Anwendungsfall für domänen- spezifische Sprachen (DSLs) • Veränderungen durch den Experten
  • 75. DSL-Beispiel (von Bernd Schiffer): Entfernungsberechnung assert 5001.m == 2000.m + 3.km + 1.m
  • 76. DSL-Beispiel (von Bernd Schiffer): Entfernungsberechnung assert 5001.m == 2000.m + 3.km + 1.m class Meter { def meter Meter(meter) { this.meter = meter } def plus(kilometer) { new Meter(meter + kilometer.meter) } boolean equals(other) { this.meter == other.meter } } class Kilometer { def meter Kilometer(kilometer) { meter = kilometer * 1000 } } class Distance { static def getM(distance) { new Meter(distance) } static def getKm(distance) { new Kilometer(distance) } }
  • 77. DSL-Beispiel (von Bernd Schiffer): Entfernungsberechnung assert 5001.m == 2000.m + 3.km + 1.m class Meter { def meter assert werteAus('5002 m == 2000 m + 3 km + 2 m') Meter(meter) { this.meter = meter } def plus(kilometer) { def werteAus(String anweisung) { new Meter(meter + kilometer.meter) } Eval.me( boolean equals(other) { anweisung.replaceAll(quot; (m|km)quot;, { } this.meter == other.meter } alle, einheit -> quot;.${einheit}quot; class Kilometer { })) def meter Kilometer(kilometer) { } meter = kilometer * 1000 } } class Distance { static def getM(distance) { new Meter(distance) } static def getKm(distance) { new Kilometer(distance) } }
  • 78. Einsatzmuster: 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 schaffen, z.B. in einem speziellen Servlet • Unglaublich wertvoll für Produkt-Support, Fehleranalyse, Hot-Fixes, Notfälle
  • 79. Endoskopische Operation: im Servlet
  • 80. Endoskopische Operation: im Servlet Probleme mit der Datenbank Verbindung? def ds = Config.dataSource ds.connection = new DebugConnection(ds.connection)
  • 81. 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)
  • 82. Einsatzmuster: Grenzenlose Offenheit • Jede Zeile Code wird änderbar • Manchmal sind die vorgesehenen Variationspunkte nicht ausreichend • Einfache Änderungen ohne langwieriges Setup für Kompilation und Deployment • Perl, PHP, Python, etc. machen es vor
  • 83. Einsatzmuster: Heinzelmännchen • Repetitive Aufgaben automatisieren • Automatisierter Build, kontinuierliche Integration, Deployment, Installationen, Server-Überwachung, Reports, Statistiken, Erzeugen von Dokumentation, funktionale Tests uvm. • Anwendungen mit Ant, Maven und Co.
  • 84. Heinzelmännchen: Mail schicken def users = [ [name:'Johannes', email:'jl@johanneslink.net'], [name:'Teilnehmer', email:'wer@wo.net']] def ant = new groovy.util.AntBuilder() for (user in users) { ant.mail(mailhost: 'smtp.googlemail.com', mailport: '465', ssl: 'true', user: quot;$mailUserquot;, password: quot;$passwordquot;, subject: 'Vortrag ist bald fertig') { from(address: 'johannes.link@googlemail.com') to(address: user.email) message( quot;quot;quot; Hallo ${user.name}, Der Vortrag ist fast fertig: ${new Date().toGMTString()} quot;quot;quot; ) } }
  • 85. Einsatzmuster: 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 / C#
  • 86. Weitere Informationen • http://groovy.codehaus.org/ • http://grails.codehaus.org/ • Dierk König et al: „Groovy in Action“
  • 87. Zusammenfassung • Die Programmiersprache Java hat Einschränkungen: • Anpassungen zur Laufzeit • Präzision im Ausdruck • Erweiterbarkeit der Sprache • Groovy als dynamische Skriptsprache ist in diesen Punkten flexibler und mächtiger • Groovys Ziel ist die best mögliche Integration in die Java-Plattform • Es existieren typische Einsatzmuster
  • 88. Fragen und Anmerkungen? http://www.slideshare.net/jlink/ mehr-dynamik-mit-groovy/