event-getriebene programmierung in der praxis - … programmierung in der praxis ... domain driven...
TRANSCRIPT
Event-getriebene Programmierung in der PraxisDipl.-Inf. (FH) Marco Emrich Oct. 2014 @ XP-Days
Wo?Wozu?Wer?
GUIhttps://www.flickr.com/photos/joris/2410290034
https://www.flickr.com/photos/11319126@N00/8270409318/in/photostream
Architektur
Evented-SOA
Microservices
http://martinfowler.com/articles/microservices.html
GenerallesProgrammier-Modell
Method vs.
Event https://www.flickr.com/photos/gen/325927418
Sender ReceiverMessage
Method Call
Sender ReceiverListen
Raise Event
Event
Sender
ReceiverListen
Event
Raise Event Receiver
Listen
Receiver
Listen
https://www.flickr.com/photos/caroslines/547184477
Wiring
Sender
Receiver
Listen
Raise Event
Receiver
Listen
Receiver
Listen
Event-BUS
Pub/Sub
Sender
Receiver
Listen
EventRaise Event
Receiver
Listen
ReceiverListen
Sender
Raise Event
Event vs. Method
Method
Sender tells Receiver
Sync
Fixed Coupling
New Receiver: change to Sender
Event
Receiver listens to Sender
(Pseudo-) Async
Loose Coupling
New Receiver: no change to Sender
Sometimes: Hard to Test/Debug
Testing?
Isolationhttps://www.flickr.com/photos/loufi/3500076/
Winner?https://www.flickr.com/photos/48424574@N07/5096035675
Domain Driven Design
Hexagonal Architecture
Vaughn Vernon
Alistair Cokburn
Hexagonal Architecture
DomainModel
Hexagonal Architecture
DomainModel
Adapter Adapter
Adapte
rAdapter
Adapte
r
Adapter
Adapter
Adapter
Hexagonal Architecture
DomainModel
Adapter Adapter
Adapte
rAdapter
Adapte
r
Adapter
Adapter
Persistance
Adapter
Hexagonal Architecture
DomainModel
Adapter Adapter
Adapte
rAdapter
Adapte
r
Adapter
Adapter
Persistance
Adapter
GUI
Hexagonal Architecture
DomainModel
Adapter Adapter
Adapte
rAdapter
Adapte
r
Adapter
Adapter
Persistance
Adapter
GUI
Events
Events
Events
Events
CQRSEven Sourcing
Domain Eventsvs.
Commandshttps://www.flickr.com/photos/stevedave/3566325269
Event Storming
We want you for Kata
Code Retreat
Practice
http://udoncrew.deviantart.com/art/UFS-Impossible-Contortion-109860059
Try Extremes
TDD
Pair-Programming
2 x 35 min
+ Retrospective
Callcenter Kata
0911/123499040/456780171/3456789….
Phone Number / Caller ID
0911/123499040/456780171/3456789….
Phone Number / Caller ID
0911 Nürnberg
040 Hamburg
0911/123499….
040/45678….
0911/123499040/456780171/3456789….
Phone Number / Caller ID
0911 Nürnberg
0911/123499….
040/45678….
Statistik
040 Hamburg
Constraints
no Method-communication, Events only
Constraints
no Method-communication, Events only
Small Classes (SRP) max. 20-30 LOC / (Java: 50) max. 5 Methods
http://nodejs.org/api/events.html#events_emitter_addlistener_event_listener
JavaScript / Node.JS
https://github.com/asyncly/EventEmitter2
JavaScript / Browser
JavaScript / Node.JS
var EventEmitter = require('events').EventEmitter
var PhoneNumberGenerator = function(numbers) { this.numbers = numbers; this.currentNumber = 0;};
PhoneNumberGenerator.prototype = new EventEmitter();
PhoneNumberGenerator.prototype.sendNextNumber = function() { this.emit('NewPhoneNumberCreated', this.numbers[this.currentNumber]);}
var sleep = require('sleep');
PhoneNumberGenerator.prototype.start = function() { while(1) { sleep.sleep(n); this.sendNextNumber(); }}
JavaScript / Node.JS
JavaScript / Node.JSdescribe('PhoneNumberGenerator', function() { it('should emit numbers', function(done) { var generator = new PhoneNumberGenerator(['012345678']); generator.on('NewPhoneNumberCreated', function(payload) { expect(payload).toEqual('012345678') done(); }); generator.sendNextNumber();
});});
JavaScript / Node.JS
describe('PhoneNumberCounter', function() { it('should increase count on Number Events', function() { var emitterDummy = new EventEmitter; var counter = new PhoneNumberCounter(emitterDummy, 'NewPhoneNumberCreated'); emitterDummy.emit('NewPhoneNumberCreated', '1234'); emitterDummy.emit('NewPhoneNumberCreated', '4567'); expect(counter.value).toEqual(2); });});
class Watcher include Eventfulend
w = Watcher.new
w.on(:filechange) { |watcher, path| puts path }
w.fire(:filechange, '/path/to/file.txt')
Ruby - Eventful
Ticino - Eventdefinition
public class IncomingXmlEvent {
private String xml;
public IncomingXmlEvent(String xml) { this.xml = xml; }
public String getXml() { return xml; }}
Ticino - Receiver
public class Receiver { public void doSomethingWithThisEvent( IncomingXmlEvent incomingXml) { System.out.println("incoming: " + incomingXml.getXml()); }}
Ticino - Wiring
import net.micwin.ticino.Ticino;
public class Main { public static void main(String[] args) { Receiver rec = new Receiver(); Ticino.register(IncomingXmlEvent.class, rec); }}
Ticino.dispatch(new IncomingXmlEvent(newXml));
JUnit Hint
@Test(timeout=1000)public void mytest() { callAsyncTask(); waitForAsyncTask(); AssertAsyncTaskResult();}
www.webmasters.de
https://www.flickr.com/photos/eilonwy77/6270262038/in/photostream/