Mehr Dynamik Durch Skriptsprachen

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Favorites, Groups & Events

    Mehr Dynamik Durch Skriptsprachen - Presentation Transcript

    1. Mehr Dynamik bei der Softwareentwicklung Skriptsprachen im Vergleich
    2. Wer ich bin... Mein eigener Chef (Extremer) Softwareentwickler (Agiler) Coach Testgetrieben http://johanneslink.net
    3. 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; }
    4. 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; }
    5. 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; }
    6. 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 • Unvorhergesehene Veränderung => Neukompilierung
    7. Die Rettung naht: Dynamische Skriptsprachen • Scripting • Dynamik
    8. 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(\"Dierk\")); ... List<Person> sorted = (List<Person>) Eval.x(people, \"x.sort {it.name}\" );
    9. Dynamik • Dynamische Typisierung • Closures • Meta-Programmierung
    10. Dynamische Typisierung aka „Duck Typing“ def sortByName(unsorted) { unsorted.sort {it.name} } def people = [ new Student(\"Johannes\"), new Person(\"Dierk\") ] def sorted = sortByName(people) assert sorted[0].name == \"Dierk\" assert sorted[1].name == \"Johannes\"
    11. Closures (1) Programmlogik als vollwertiges Objekt def sorter = { unsorted -> unsorted.sort {it.name} } def sorted = sorter(people) //oder so: def sorted = sorter.call(people)
    12. Closures (2) • Iteration als typischer Anwendungsfall def namen = [\"Johannes\", \"Frank\", \"Dierk\"] def auswahl = namen.findAll {name -> name.contains \"n\"} assert auswahl == [\"Johannes\", \"Frank\"] List<String> auswahl = new ArrayList<String>(); for (String name : namen) { if (name.contains(\"n\")) { auswahl.add(name); } } Äquivalenter Java Code
    13. Meta-Programmierung • Erweiterung existierender Klassen • Hinzufügen von Methoden zur Laufzeit • Erweiterung / Veränderung der Sprache durch Eingriff Verwendung eines „Meta Object Protocol“
    14. 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 -> class MyObject { def prop delegate.metaClass.invokeConstructor(*args) } void setProperty(String name, value) { prop = value assert }new ArrayList() == ArrayList.create() def getProperty(String name) { assert new HashMap() == HashMap.create() prop assert new Integer(42) == Integer.create(42) } assert new Dimension(1,1) == Dimension.create(1,1) } def obj = new MyObject() obj.firstName = \"Johannes\" obj.lastName = \"Link\" assert obj.firstName == \"Link\"
    15. Vorteile / Nachteile dynamischer Skriptsprachen • Vorteile: • Weniger Code • Weniger Duplikation • Verständlichere Abstraktionen • Mehr Deployment-Optionen • Nachteile: • Erschwerte statische Codeanalyse • Schlechtere Performance
    16. 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 ... • Heute im Visier: JavaScript, Ruby und Groovy
    17. 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
    18. Groovy - Vereinfachte Syntax System.out.println(\"Hello World!\"); //Java style println 'Hello, World!' def vorname = 'Stefan' println \"$vorname, ich hol' den Wagen.\" String lang = \"\"\"Du, ${vorname}, der Wagen steht eine Zeile weiter.\"\"\" assert 0.5 == 1/2 class Person { def name } def johannes = new Person(name: \"Johannes\") assert johannes.name == \"Johannes\"
    19. Groovy -Closures def to = \"JUGS\" def say = { msg -> msg + \", $to\" } assert say(\"Hallo\") == \"Hallo, JUGS\" to = \"JUG Cologne\" assert say(\"Hallo\") == \"Hallo, JUG Cologne\" (1..10).each { println it } [a:1, b:2].each { key, value -> println \"key: $key, value: $value\" }
    20. JavaScript • Objektorientiert - aber nicht klassenbasiert • Keine statische Typisierung • Syntax und ein paar Basis-Objekte an Java angelehnt • Läuft (interpretiert) in jedem Browser - im Detail unterschiedlich • Enge Verknüpfung mit DOM • Rhino-JS-Engine in Java SE 6 enthalten • Standardisiert als ECMAScript
    21. JavaScript - Basistypen var name = 'Johannes'; assertEqual('Johannes Link', name + ' Link'); var eins = 1 assertEqual(2, eins + 1) assertEqual('11', eins + '1') var liste = [1, 2, 'drei'] assertEqual('drei', liste[2]) var isBig = eins > 1000 if (isBig) fail()
    22. JavaScript - Objekte var johannes = new Object(); johannes.firstName = \"Johannes\" johannes.lastName = \"Link\" johannes.name = function() { return this.firstName + ' ' + this.lastName } assertEqual('Johannes Link', johannes.name()); var johannes = { firstName: 'Johannes', lastName: 'Link', name: function() { return this.firstName + ' ' + this.lastName } }
    23. JavaScript - Prototypen (1) function Person(firstName, lastName) { this.firstName = firstName this.lastName = lastName } Person.prototype.name = function() { return this.firstName + ' ' + this.lastName } var johannes = new Person('Johannes', 'Link') assertEqual('Johannes Link', johannes.name()) assertEqual(true, johannes instanceof Person)
    24. JavaScript - Prototypen (2) johannes.name = function() { return 'Joe Cartwright' } assertEqual('Joe Cartwright', johannes.name()) function Student(firstName, lastName) { Person.call(this, firstName, lastName); } Student.prototype = new Person(); Student.prototype.name = function() { return this.firstName; } var jannek = new Student('Jannek', 'Link'); assertEqual('Jannek', jannek.name()); assertEqual('Link', jannek.lastName);
    25. Ruby • Sprachumfang und Mächtigkeit ähnlich wie bei Groovy • C-Implementierung als Interpreter • „Berühmt“ durch Ruby on Rails • Ausschließlich dynamische Typen • JRuby: Byte-Code und Java- Integration
    26. Ruby - Code class Person attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end end class Person def name() first_name + \" \" + last_name end end johannes = Person.new(\"Johannes\", \"Link\") assert_equal \"Johannes Link\", johannes.name
    27. Ruby - Blocks def three_times(arg) yield arg yield arg yield arg end three_times (\"JUGS\") { |name| puts \"Hello, \" + name } def twice(arg, action) action.call(arg) action.call(arg) end print_ciao = proc { |name| puts \"Ciao, \" + name } twice \"JUGS\", print_ciao
    28. Ruby - Mixins module Debug def who_am_i \"#{self.class.name}\" end end class Person include Debug end johannes = Person.new(\"Johannes\", \"Link\") assert_equal \"Person\", johannes.who_am_i s = \"Ein String\" class Array s.extend Debug include Debug assert_equal \"String\", s.who_am_i end assert_equal \"Array\", [1, 2, 3].who_am_i
    29. Ruby Classes are Objects johannes = Person.new(\"Johannes\", \"Link\") assert_equal Person, johannes.class assert_equal Class, Person.class assert_equal Class, Class.class assert_equal Module, Class.superclass assert_equal Object, Module.superclass class Class alias_method :old_new, :new def new(*args) puts \"Objekt wird erzeugt...\" old_new(*args) end end
    30. Ruby Events Event Hook Methodenaufruf Kernel::system Methode hinzufügen Module#method_added Unterklasse erzeugen Class#inherited ...
    31. Vergleich (1) Groovy JavaScript Ruby / JRuby gering, deutlich groß, Verbreitung mittel, wachsend wachsend gleichbleibend wenig eingebaut, Bibliotheken J2EE + GDK zahlreich /+J2EE viele externe Libs dynamisch, Typisierung dynamisch dynamisch optional statisch Objektorien- Objekte + vollständig vollständig tierung primitive Typen Vererbung klassenbasiert Prototyp-basiert klassenbasiert sehr mächtig MOP gering sehr mächtig++ (ab 1.5)
    32. Vergleich (2) Groovy JavaScript Ruby / JRuby gut, aber mit Java-Integration optimal gering prinzp. Problemen Laufzeit- kompilierter interpretiert / interpretiert umgebung Bytecode auf JVM JVM Bytecode Tool- mäßig bis gut mäßig mäßig bis gut Unterstützung (IDEA) Typisches Scripting in Java- Ajax im Browser Ruby on Rails Anwendungsfeld Applikationen langsam, besser Performance langsam meist ausreichend werdend http://shootout.alioth.debian.org/
    33. Strack Trace Java Thread [main] (Suspended (breakpoint at line 22 in JavaPerson)) JavaPerson.doubleName() line: 22 JavaTester.run() line: 7 Tester.test(Class<Runnable>) line: 16 Tester.main(String[]) line: 6
    34. Stack Trace Groovy Thread [main] (Suspended (breakpoint at line 18 in GroovyPerson)) GroovyPerson.doubleName() line: 18 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 585 CachedMethod.invoke(Object, Object[]) line: 95 MetaClassHelper.doMethodInvoke(Object, MetaMethod, Object[]) line: 599 MetaClassImpl.invokeMethod(Class, Object, String, Object[], boolean, boolean) line: 904 MetaClassImpl.invokeMethod(Object, String, Object[]) line: 740 InvokerHelper.invokePogoMethod(Object, String, Object) line: 773 InvokerHelper.invokeMethod(Object, String, Object) line: 753 ScriptBytecodeAdapter.invokeMethodN(Class, Object, String, Object[]) line: 167 ScriptBytecodeAdapter.invokeMethod0(Class, Object, String) line: 195 GroovyTester.run() line: 7 Tester.test(Class<Runnable>) line: 16 Tester.main(String[]) line: 7
    35. Warum gerade jetzt? • Normale Pendelschwingung zwischen dynamischer und statischer Typisierung • Frust über Redundanz und wachsende Komplexität von Java • Domänen-spezifische Sprachen sind auf dem Vormarsch • Multi-Sprachen-Systeme werden hoffähig • Mehr Wissen über sinnvolle Einsatzszenarien der unterschiedlichen Programmiersprachen
    36. Einsatzmuster für Scripting (von Dierk König) • Alleskleber • Weiches Herz • Kluge Anpassung • Endoskopische Operation • Grenzenlose Offenheit • Heinzelmännchen • Prototyp
    37. Einsatzmuster: Alleskleber • Applikationen aus bestehenden Komponenten zusammenbauen • Java und .NET sind 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)
    38. Alleskleber Demo: RSS Reader • Zusammenbau von XML Parser, Java Networking und Swing Widget Bibliothek, um einen Standard-RSS Feed darzustellen
    39. 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
    40. 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(\"mitarbeiter\", mitarbeiter); binding.setVariable(\"bonusClub\", bonusClub); GroovyShell shell = new GroovyShell(binding); File script = new File(filename); BigDecimal bonus = (BigDecimal) shell.evaluate(script);
    41. 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
    42. DSL-Beispiel (Bernd Schiffer): Entfernungsberechnung assert 5001.m == 2000.m + 3.km + 1.m class Distance { def meter assert werteAus('5002 m == 2000 m + 3 km + 2 m') def plus(other) { new Distance(meter: meter + other.meter) def werteAus(String ausdruck) { } boolean equals(other) { Eval.me( this.meter == other.meter } ausdruck.replaceAll(\" (m|km)\", { } alle, einheit -> \".${einheit}\" })) class DistanceCategory { } static def getM(distance) { new Distance(meter: distance) } static def getKm(distance) { new Distance(meter: distance * 1000) } }
    43. Einsatzmuster: Endoskopische Operation • Minimal-invasive Eingriffe \"in vivo\" • 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
    44. 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)
    45. 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
    46. 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.
    47. Heinzelmännchen: Mail schicken def users = [ [name:'Johannes', email:'jux@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: \"$mailUser\", password: \"$password\", subject: 'Vortrag ist bald fertig') { from(address: 'johannes.link@googlemail.com') to(address: user.email) message( \"\"\" Hallo ${user.name}, Der Vortrag ist fast fertig: ${new Date().toGMTString()} \"\"\" ) } }
    48. Einsatzmuster: Prototyp • Machbarkeitsstudien auf der Zielplattform • \"Spikes\" 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#
    49. Weitere Informationen • Groovy: • http://groovy.codehaus.org/ • Dierk König et al: „Groovy in Action“ • JavaScript: • http://developer.mozilla.org/en/docs/JavaScript • David Flanagan: „JavaScript: The Definitive Guide“ • Microsoft: „ JScript Deviations from ES3“ • Ruby: • http://www.ruby-lang.org • Dave Thomas et al.: „Programming Ruby: The Pragmatic Programmers' Guide“ • http://www.nealford.com/downloads/conferences/ Neal_Ford-Comparing_Groovy_and_JRuby-slides.pdf
    50. Zusammenfassung • Java - und andere Entreprise-Plattformen - haben Einschränkungen: • Anpassungen zur Laufzeit • Präzision im Ausdruck • Erweiterbarkeit der Sprache • Dynamische Skriptsprachen sind in diesen Punkten flexibler und mächtiger • bringen jedoch andere Probleme mit sich • Nicht statisch vs dynamisch, sondern...
    51. Zeremonie versus Essenz

    + jlinkjlink, 2 years ago

    custom

    2646 views, 0 favs, 0 embeds more stats

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2646
      • 2646 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 0
    • Downloads 0
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories