Date post: | 05-Dec-2014 |
Category: |
Technology |
Upload: | arne-burmeister |
View: | 1,012 times |
Download: | 0 times |
digital ergonomics© 2011
Inversion of Flow
Arne Burmeister
Arne Burmeister
Who am I?
■ geboren 1969 in Lübeck
■ Diplom TU-Berlin 1996
■ verheiratet, 2 Kinder
■ Taucher, Motorradfahrer
■ Sun Certified Java Dev
■ Softwarearchitekt
Do you not see the logic of my plan?
Why?
■ Refactoring zum Durchreichen von Inputwerten?
■ Refactoring für Ablaufänderungen durch geänderte Abhängigkeiten?
■ Weniger Refactoring in agiler Entwicklung!
We still got the Mobius Inversion coming up.
What you get!
■ Inversion of Control
■ Dependency Injection
■ Invert the Flow
■ Spaces und Factories
■ Vor- und Nachteile
Begin at the beginningand go on till you come to the end: then stop
Once upon a time …
■ ein monolithisches Programm
■ Ablaufsteuerung legt Was, Wann und Wie fest
■ Abhängigkeiten müssen vorher bekannt sein
■ Implementierungen sind global oder werden im Ablauf instanziiert
■ Zwischenergebnisse müssen gespeichert werden
■ Abhängigkeiten müssen bereitgestellt werden
Monolithisch
Beispiel private static final BigDecimal G = new BigDecimal("6.67384E-11"); private static final BigDecimal AE = new BigDecimal("149597870691");
public static void main(String... args) { Sun sun = new Sun(); PlanetDto erde = new PlanetDto("Earth", new BigDecimal("5.974E24"), 0.983, 1.017); PlanetDto mars = new PlanetDto("Mars", new BigDecimal("6.419E23"), 1.381, 1.666); PlanetDto jupiter = new PlanetDto("Jupiter", new BigDecimal("1.899E27"), 4.95, 5.46); for (Planet planet : new Planet[] { erde, mars, jupiter }) { double period = calculatePeriodInDays(sun, planet); System.out.println(planet.getName() + ": " + period + " Tage"); } }
public static double calculatePeriodInDays(Star sun, Planet planet) { double aInAe = (planet.getApohelInAe() + planet.getPerihelInAe()) / 2.0; BigDecimal a = AE.multiply(new BigDecimal(aInAe)); BigDecimal z = new BigDecimal(Math.PI).pow(2) .multiply(new BigDecimal(4)).multiply(a.pow(3)); BigDecimal n = G.multiply(sun.getMassInKg().add(planet.getMassInKg())); double p = Math.sqrt(z.divide(n, 8, RoundingMode.HALF_UP).doubleValue()); return p / (60 * 60 * 24); }
Don't call us, we'll call you!
Inversion of Control
■ Umkehrung der Ablaufsteuerung, keine zentrale Steuerung des Programmflusses mehr
■ einzelne Funktionen statt einem monolithischem Programm
■ Registrierung von Teilen, Steuerung (Verknüpfung und Aufruf) durch Framework
■ keine Annahmen über das Verhalten des restlichen Systems, Fokus auf die Funktion
A small step for a developer, one giant leap for development
Dependency Injection
■ Dependency Injection ist ein Teil vonInversion of Control
■ Entkopplung der konkreten Implementierungen
■ Teile werden durch Container zum Programmstart miteinander verbunden
■ das Wie wird entkoppelt
■ Komplexität wird reduziert
■ Testbarkeit wird verbessert
dependencies injected
Beispielpublic class Injected implements ApplicationListener<ContextRefreshedEvent>{ private OrbitalCalculator caculator; private SolarSystem system;
public void onApplicationEvent(ContextRefreshedEvent event) { for (Planet planet : system.getPlanets()) { double period = caculator.calculatePeriodInDays( system.getStar(), planet); System.out.println(planet.getName() + ": " + period + " Tage"); } }
<beans xmlns="http://www.springframework.org/schema/beans"> <bean id="caculator" class="OrbitalCalculator"/> <bean class="Injected"> <property name="system" ref="system"/> <property name="caculator" ref="caculator"/> </bean>
The force will be with you
Inversion of Flow
■ keine direkte Ablaufsteuerung
■ Ergebnisse „auf Zuruf“
■ Abhängigkeiten über pull statt push
■ Wann wird entkoppelt
■ es wird nur ausgeführt, was nötig ist
Results at the end of the universe
Space
■ Quelle aller Eingaben
■ Ablage aller Ergebnisse
■ Space enthält Key/Value Paare
■ Associative Memory mit Schlüssel über Typ und Name
■ Kann persistent sein, muss aber nicht
■ „self populating“ durch Factories
Key/Value Paare und Factories
Inversion of Flow
FactorySpace
Value
erzeugt
speichertStore
Key
verwaltet
Where no developer has gone before
Space■ direkte Anfrage eines Ergebnisses
■ Anfrage löst Berechnung aus
■ initiale Befüllung möglich
■ Abhängigkeiten können Zwischenergebnisse sein
■ Abhängigkeiten müssen nicht vorhanden sein
■ Anfrage von Zwischenergebnisse lösen weitere Berechnungen aus
■ Zwischenergebnisse werden automatisch gespeichert
work in space
Beispiel private SolarSystem system;
private ValueSpace space;
private void printOrbits() throws MissingKeyException { space.add(singletonKey(SolarSystem. class), system); for (Orbit orbit : space.getAll(typeMatcher(Orbit.class))) { System.out.println(orbit.getPlanet().getName() + ": " + orbit.getPeriodInDays() + " Tage"); } }
<bean id="caculator" class="OrbitalCalculator" />
<bean class="Inverted"> <property name="space" ref="space" /> <property name="system" ref="system" /> </bean>
<bean id="space" class="DefaultValueSpaceFactoryBean"> <property name="storeFactory"> <bean class="MemoryStoreFactory" /> </property> <property name="valueFactories"> <list> <bean class="OrbitFactory"> <property name="caculator" ref="caculator" /> </bean> …
I need your magic
Value Factories
■ beinhaltete den Rest von Flow
■ berechnet fehlende Ergebnisse
■ kann Abhängigkeiten anfordern
■ minimale lokale Codeänderungen, wenn sich Abhängigkeiten ändern
■ Factory kann Rechner oder externer Service sein
■ fehlende Ergebnisse ohne zuständige Factory führen zu Fehlern
value production
Beispielpublic class OrbitFactory extends AbstractValueFactory<String, Orbit>{ private OrbitalCalculator calculator;
public OrbitFactory() { super(String.class, Orbit.class); }
public Orbit createValue(Key<String, ? super Orbit> key, ValueSource tuples) throws MissingKeyException { Star sun = tuples.get(singletonKey(Star.class)); Planet planet = tuples.get(Matchers.idKey(Planet.class, key.getId())); Orbit orbit = new Orbit(sun, planet); orbit.setPeriodInDays(calculator.calculatePeriodInDays(sun, planet)); return orbit; }
public Set<Key<String, ? extends Orbit>> createValueKeys( Matcher<? super Orbit> key, ValueSource tuples) throws MissingKeyException { Set<Key<String, ? extends Orbit>> keys = new HashSet<...>(); for (Planet planet : tuples.getAll(typeMatcher(Planet.class))) { keys.add(Matchers.idKey(Orbit.class, planet.getName())); } return keys; }}
Time circuits on. Flux Capacitor... fluxxing.
Dependency Control
■ Abhängigkeiten müssen überwacht werden
■ zyklische Abhängigkeiten führen zu Fehlern
■ Überschreiben von Ergebnissen entfernt abhängige Ergebnisse
■ Zyklen können in Einzelfällen erlaubt sein
unlimited technology from the whole universe
Multiple Universe
■ Spaces können aufeinander aufbauen
■ Subspace kann manuell erzeugt werden
■ Value Factory kann Subspaces erzeugen und anfragen
■ Schichten spiegeln sich in Hierarchie wider
Hierarchische Spaces
Beispiel <bean id="system" class="SolarSystem"> … </bean>
<bean class="space" class="DefaultValueSpaceFactoryBean"> <property name="parents"> <list> <bean class="SpringValueSource" /> </list> </property> <property name="storeFactory"> <bean class="MemoryStoreFactory" /> </property> <property name="valueFactories"> <list> <bean class="OrbitFactory"> <property name="caculator" ref="caculator" /> </bean> <bean class="StarFromSystemFactory" /> <bean class="PlanetsFromSystemFactory" /> </list> </property> </bean>
He who controls the space, controls the universe!
Injection of Flow
■ Space und Store über Factory
■ Space bekommt Value Factories injected
■ Space bekommt Store über Factory injected
■ für hierarchische Spaces können Eltern an die Factory gegeben werden
Not the answer to life, the universe and everything
Space erverywhere?
■ nur ein Paradigma, nicht für alle Fälle der sinnvollste Ansatz!
■ Vorteile: Fokus auf Kernaufgabe,wenig Refactoring notwendig, inhärenter Cache
■ Nachteile: Zusammenhänge unsichtbar,mehr Integrationstests notwendig?
■ Ausblick: parallele Factoryaufrufe, verteilter Space mit Cloud Storage
The answer is out there
The Outer Space
■ Robert C. Martin: „The Dependency Inversion Principle“, 1996
■ Martin Fowler: „Inversion of Control Containers and the Dependency Injection“, 2004
■ Jeremy Miller: „The Dependency Injection Pattern – What is it and why do I care?“, 2005
■ „Associative Memory“, Cunningham & Cunningham Wiki, 2005
■ Arne Burmeister: „deVasp“, Java-Net, 2011
http://arne.burmeister-teltow.de/
Danke, Fragen?