Mehr Dynamik Mit Groovy

4,555
-1

Published on

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

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,555
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Mehr Dynamik Mit Groovy

  1. 1. Groovy Mehr Dynamik bei der Java- Entwicklung
  2. 2. Wer ich bin...
  3. 3. Wer ich bin... Mein eigener Chef (Extremer) Softwareentwickler (Agiler) Coach Testgetrieben http://johanneslink.net
  4. 4. Java-Frust
  5. 5. Java-Frust public class Person... public String getName() { return name; }
  6. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 17. Die Rettung naht: Dynamische Skriptsprachen • Scripting • Dynamik
  18. 18. Scripting • Knappe und ausdrucksstarke Syntax • Ausführung von Programmcode ohne (spürbare) Compilierung • Selbstständige Skripte • Aus einer Applikation heraus
  19. 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. 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. 21. Dynamik • Dynamische Typisierung • Closures • Meta-Programmierung
  22. 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. 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. 24. Closures (2) • Iteration als typischer Anwendungsfall
  25. 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. 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. 27. Meta-Programmierung • Erweiterung existierender Klassen • Hinzufügen von Methoden zur Laufzeit • Erweiterung / Veränderung der Sprache durch Verwendung eines „Meta Object Protocol“
  28. 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. 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. 30. Vorteile / Nachteile dynamischer Skriptsprachen • Vorteile: • Weniger Code • Weniger Duplikation • Verständlichere Abstraktionen • Mehr Deployment-Optionen
  31. 31. Vorteile / Nachteile dynamischer Skriptsprachen • Vorteile: • Weniger Code • Weniger Duplikation • Verständlichere Abstraktionen • Mehr Deployment-Optionen • Nachteile: • Erschwerte statische Codeanalyse • Schlechtere Performance
  32. 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. 33. Groovy in der Sprachlandschaft Text (c) Dierk König
  34. 34. Groovy
  35. 35. Groovy • Volle Objekt- Orientierung ohne primitive Typen
  36. 36. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung
  37. 37. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung • Closures
  38. 38. Groovy • Volle Objekt- Orientierung ohne primitive Typen • Optionale statische Typisierung • Closures • Listen und Maps als Literale
  39. 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. 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. 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. 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. 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. 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. 45. Groovy Beans & GPath class Person { def name def kinder = [] } def johannes = new Person(name: quot;Johannesquot;) assert johannes.name == quot;Johannesquot;
  46. 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. 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. 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. 49. Java VM <-> Groovy
  50. 50. Java VM <-> Groovy • Groovy-Klassen können beliebig auf Java-Klassen zugreifen • und umgekehrt!
  51. 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. 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. 53. Dynamische Evaluation zur Laufzeit
  54. 54. Dynamische Evaluation zur Laufzeit • Eval.x(users, quot;x.grep{ it.salary -> 100000 }.address.townquot;); // me, x(), xy(), xyz()
  55. 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. 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. 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. 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. 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. 60. Dynamik & Metaprogrammierung • Dynamischer Methodenaufruf und Hooks • Kategorien • Methoden zur Laufzeit hinzufügen
  61. 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. 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. 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. 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. 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. 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. 67. Wie entwickle ich Groovy-Programme? • groovysh • groovyConsole • IDE-Support • IDEA IntelliJ • Eclipse • NetBeans
  68. 68. Einsatzmuster für Scripting (von Dierk König) • Alleskleber • Weiches Herz • Kluge Anpassung • Endoskopische Operation • Grenzenlose Offenheit • Heinzelmännchen • Prototyp
  69. 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. 70. Alleskleber Demo: RSS Reader • Zusammenbau von XML Parser, Java Networking und Swing Widget Bibliothek, um einen Standard-RSS Feed darzustellen
  71. 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. 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. 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. 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. 75. DSL-Beispiel (von Bernd Schiffer): Entfernungsberechnung assert 5001.m == 2000.m + 3.km + 1.m
  76. 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. 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. 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. 79. Endoskopische Operation: im Servlet
  80. 80. Endoskopische Operation: im Servlet Probleme mit der Datenbank Verbindung? def ds = Config.dataSource ds.connection = new DebugConnection(ds.connection)
  81. 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. 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. 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. 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. 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. 86. Weitere Informationen • http://groovy.codehaus.org/ • http://grails.codehaus.org/ • Dierk König et al: „Groovy in Action“
  87. 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. 88. Fragen und Anmerkungen? http://www.slideshare.net/jlink/ mehr-dynamik-mit-groovy/

×