Getting Started with RX

Was ist RX?

RX Steht für Reactive Extensions. In RX geht alles um Streams.  Wenn wir uns ansehen wie Daten zur Verfügung stehen, merken wir schnell, dass Streams und Events auch die natürlichste aller Datenquellen sind.

Fast nie sind Daten auf einmal wie ein Fact da. Da entstehen, sie wandeln sich, werden aggregiert und auswertet. Dabei steht in der Regel meist ein Strom an Daten als Ausgang zur Verfügung und eine statische unveränderliche Datenbank.

Das hängt auch damit zusammen, dass die zuerfassenden Datenmengen stetig wachsen und es immer aufwendiger wird diese zu analysieren.

Auch aus diesem Grund erfreuen sich Reaktive Sprachen und EventProcessing Technologien wie Spark immer größerer Beliebtheit. Man schaue nur mal auf den Microsoft Eventhub.

Für RX gibt es für eine Vielzahl von Sprachen Libraries. So z.B.: C# , Java, JavaScript ,…

Die Unterschiede zwischen den Sprachen sind nur marginal und lassen sich sehr leicht adoptieren.

Die Projektseite findet sich unter: Rx_Icon http://reactivex.io/ das github repo für die C# Libraries findet ihr unter: https://github.com/Reactive-Extensions/Rx.NET

Der Primäre Punkt für RX ist dass man sich zunächst einmal auf alles subscriben kann umd EventStreams zu consumieren. Und ja das geht wirklich auf alles.

Schauen wir uns das im Detail an.

 

IObservable

Um RX in einem Projekt verwenden zu können binden wir zunächst System.Reactive via nuget ein.

Nun gibt es sehr viele vorgefertigte Methoden die es uns ermöglichen auf Elemente subscriben zu könne.

Folgender Code kann in einer Consolen Anwendung ausgeführt werden

List<string> items = new List<string>{"a","b","c"};

var observable = items.ToObservable();

observable.Subscribe(i => Console.WriteLine(i));

 

Auf der Console erscheint:

a
b
c

ToObservable liefert ein Instanz des Types IObservable zurück. Dessen zweck ist es dem User eine Schnittstelle zugeben auf die er sich subscriben kann. Also die Stelle von der man Daten bekommen kann.

Hierbei spielt es für den Subscriber keine Rolle mehr von wo die Daten ursprünglich kamen.

Man kann übrigens auch jeden Observable wieder in eine Liste oder ein Enumerable wandeln

var items = observable.ToList();
var items = observable.ToEnumerable();

 

Operationen

Nun ist es eine Idee die Konsequent verfolgt wird, dass man diese ströme in einem FluentSyntax erweitern kann. Man kann sich das so vorstellen, als das man an diesen Daten strom nun Operation um Operation anhängen kann und am Ende sein aufbereites Ergebnis bekommt

Daten eines IObservables können nun beliebig durch weitere „Haltepunkte“ in einem Datenstrom laufen.

Z.b. können die Daten batchweise Übertragen werden. Dies macht bei einer statischen Liste wenig Sinn. Wenn wir aber nun an Scenarien denken bei denen sehr viele Daten entstehen ist das aber ein sehr wünschens wertes verhalten. So können Datenpakete in Batches gepackt und als batch gespeichert werden.

observable.Buffer(5).Subscribe(SaveToDataBase)

man kann übrigens auch über Zeit buffern

observable.Buffer(TimeSpan.FromSeconds(2)).Subscribe(SaveToDataBase)

Die Dokumentation unter http://reactivex.io/ ist übrigens immer sehr hilfreich und liefert u.a. diese Schaubild für Buffer .

Buffer

 

Ich habe auch schon IDE’s gesehen bei denne diese Schaubilder beim verwenden der Operationen eingeblendet wurden.

 

Eine weitere sehr hilfreiche seite ist RX Marbels. Dort man kan man die Datenpunkte in Diagrammen wie obigen verschieben und sieht live die geänderten outputs.

http://rxmarbles.com/

Eine liste dieser Operationen findet man unter: http://reactivex.io/documentation/operators.html#transforming

Subscriben von Events

Es gibt eine ganze reihe von Extension Methods die es einem ermöglichen sich an verschiedenste Datenquellen zu binden.

Hier exemplarisch das Binden an Events erklärt:

Observable.FromEventPattern<PropertyChangedEventArgs>(this.textBox, "PropertyChanged")
.         .Select(_ => this.TextBoxText)

So kann man sich auf das PropertyChanged Event einer Textbox (z.b. in WPF oder windows forms) binden.
Wenn man nun dieses event auf den Text einschränkt bekommt man einen Stream von Chars die sich geändert haben. Dies kann man z.b. verwenden um auf Usereingaben zu reagieren.

Observable.FromEventPattern<PropertyChangedEventArgs>(this.textBox, "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "Text")
          .Select(_ => this.TextBoxText)

 

Ein typisches Scenario hierfür ist die sucheingabe in google die „As-You-Type“ sucht.

Hier ist man es gewohnt dass erst gesucht wird wenn man zwischen zwei buchstaben „zögert“ dies können wir mit dem Throttle Operator erreichen:

Observable.FromEventPattern<PropertyChangedEventArgs>(this.textBox, "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "Text")
          .Select(_ => this.TextBoxText)
          .Throttle(TimeSpan.FromSeconds(1))

 

Wenn wir nun noch mindestens 3 Zeichen erwarten können wir das ganze noch mit einer Where filtern

Observable.FromEventPattern<PropertyChangedEventArgs>(this.textBox, "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "Text")
          .Select(_ => this.TextBoxText)
          .Where(text => text.Length > 3)
          .Throttle(TimeSpan.FromSeconds(1))

 

Wie man sieht haben wir nun mit sehr lesbaren und einfachen Code ein Feature Implementiert, dass sonst einige if’s, und einige zielen mehr Code beihaltet hätte.

Aus einer abstrakteren Sicht ist somit die Cyclomatischen Complexität deutlich geringer als bei einem nicht reaktiven Ansatz.

IObserver

IObserver ist das gegenstück zu IObservable

Erstes Fazit

RX bietet Möglichkeiten um Code der sich auf das verarbeiten von Abläufen und Streamdaten einfacher zu gestalten. Allerdings benötigt dies etwas Einarbeitung.

In diesem Artikel haben wir erstmal nur die Spitze des Eisbergs angekratzt und in den nächsten Blog Artikel werden w.ir uns  weitere Details und anspruchsvollere Scenarien ansehen

 

 

Roslyn – Syntax Walker

Roslyn ist die Compiler und CodeParser Library von Microsoft.

Um Sie verwenden zu können werden diese Nuget Pakete  des Roslyn Teams angeboten.

Ein Element  aus diesem Framework sind die so genannten SyntaxWalker. Diese sind teil des Microsoft.CodeAnalysis Nuget Packages. Die C# spezifische ableitung befindet sich in Microsoft.CodeAnalysis.CSharp.

Mit einem SyntaxWalker , der eine Visitor implementierung darstellt, kann man in Roslyn über eine CodeUnit Iterieren.

Hier nun der Code für einen SyntaxWalker, der die Methoden in einem Code zählt.

internal class MyWalker : CSharpSyntaxWalker
{
    public int MethodCount { get; private set; }

    public MyWalker() : base(Microsoft.CodeAnalysis.SyntaxWalkerDepth.Trivia)
    { }

    public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
         MethodCount ++;
         base.VisitMethodDeclaration(node);
    }
}

 

Um den Walker aufzurufen benötigt man zunächst eine SyntaxNode instanz, welche einfach aus einem String erstellt werden kann.

 SyntaxTree node = CSharpSyntaxTree.ParseText(source);
  var root = node.GetRoot();

  var walker = new MyWalker();
  walker.Visit(root);

Und schon steht dem Analysieren von Codes nichts mehr im Weg!

 

 

 

 

CQRS Basics

CQRS ist ein Schlagwort das man im Moment überall  hört. Doch was verbirgt sich eigentlich unter dieser Abkürzung. Und wieso wird EventSourcing meistens im gleichen Atemzug genannt ?

Wir schauen es uns an. Um das Thema besser erklären zu können,werde ich bewusst einige Themen zunächst ignorieren. Diese Themen werden dann in den nächsten Posts näher angeschaut.

Zuerst schauen wir uns an, was CQRS entgegen mancher Mythen nicht ist:

  • CQRS ist kein Tool oder Werkzeug
  • Kein Framework
  • Kein Applikations Pattern
  • Nicht EventSourcing
  • Nicht für alle Software geeignet
  • Nicht die Lösung für alle Probleme

CQRS steht für  Command Query Responsibility Segregation und ist zunächst einmal nur ein Pattern.

Der Fokus liegt auf dem Trennen von Commands und Queries. Das bedeutet zunächst nicht mehr, als dass das Lesen und Schreiben  von Daten zwei verschiedene Belange sind.

Dies drückt sich zunächst einmal darin aus das die Modelle für das Schreiben ein anderes ist als das für das Lesen.

In klassischen Anwendungen gibt es für jede Entität aus der Domaine eine Implementierung. In einem CRM System gibt so z.B. einen Kunden. Der kann dann aus der Datenbank gelesen und geschrieben und gelöscht wierden  = CRUD.

Es stellt sich nun immer wieder heraus das ein einziges Modell bei komplexen Systemen Probleme mit sich bringt.

Unter anderem hängt das damit zusammen, dass eine komplexe Anwendung aus mehreren Bereichen besteht.  Ein CRM könnte aus folgenden Bereichen bestehen.

  • Stammdaten-Verwaltung
  • Fremdsystem-Synchronisation (z.b. mit Outlook)
  • Compliance Management
  • Terminplanung

Sehen wir uns nun an wie ein Kunde in den verschiedenen Bereichen geschaffen sein muss.

Stammdaten-Verwaltung

Hier haben wir ein sehr vollständiges Bild des Kundens, mit all seinen Daten die er im echten Leben hat. Man kann ihn sehr gut mit einer CRUD Strategie handeln. Man kann die Daten in Relationen oder Dokument basierten Datenbanken speichern . (SqlServer,MongoDb). Der Focus liegt hier bei auf den eigentlichen Datenfeldern.

Outlook-Synchronisation

Hier gibt es unterumständen weniger Businessdaten, pot. auch keine Historie, dafür aber viele technische werde, wie correlation ids, outlook ids usw.. Auch können nicht unbedingt alle Daten aus dem CRM hier im gleichen Format gespeichert werden, da das Format vorgegeben ist. Die Speicherung erfolgt in der Outlook / Exchange Datenbank. Hier liegt der Focus auf Id’s und flags ob und wann der Kunde zuletzt übertragen wurde.

Compliance Management

Hier kommt es weniger auf die Daten des Kundens als auf seine Verbindungen zu anderen an. Möchte man eine effiziente Lösung so können GraphDatenbanken wie neo4j oder Orientdb eine gute Lösugn sein.

Zusammengefasst

Nun bekommt man bei einer einzigen Entitäten eine riesige Anzahl von Datenfeldern. Von denen immer nur Teile in den einzelnen Bereichen interessant sind. Schlimmer noch teilweise sind Daten doppelt aber anders Belegt. Z.b. eine Hat eine Relations Id zu einem Ansprechpartner in Outlook eine andere Id als in unserem  entwickelten System.

Daraus folgende technologische Hürden:

Es könnte notwendig werden den Kunden in verschiedenen Systemen speichern zu können. in der SQL Datenbank brauchen wir den Kunden mit seinen angehängten Entitäten normalisiert, in MongoDb wäre eine denormalisierte Struktuir vorteilhaft. Outlook hard sehr harte Anforderung wie genau der Kunde gespeichert werden muss.

Dafür bekommt die Kunden Entität u.U. aber einige werte die nur für den Sync interessant sind wie die OutlookId. Kein Endanwender möchte eine Outlook id sehen…

GraphDatenbanken benötigen gar nicht die Informationsvielfalt die wir an den anderen Stellen haben.

Für  relationale Datenbanken brauchen wir tendenziell einzelne Entitäten, die über Relationen verbunden sind. Während wir für Dokumentenorientierte Datenbanken wir eher denormalisierte pot. redundante Dokument Strukturen  designen würden.

Diese Varianzen bestehen primär für das Lesen und interpretieren von Daten.Bei CRUD findet das Lesen und schreiben aber immer mit dem gleichen Modell statt.
Deswegen haben wir automatisch diese Komplexität auf beiden Seiten.

Man spürt schon wie unangenehm kompliziert das werden kann.

Der CQRS Ansatz

Schreiben

Hier bietet CQRS folgenden Ansatz.Man hat ein Schreibmodell und ein oder mehrere LeseModelle.

In der Regel ist das Schreiben nur eine Aneinanderreihung von Events. Hier kommt EventSourcing ins Spiel.

Wenn ein Kunde neu angelegt wird, so  wird ein „CustomerCreatedEvent“ persistiert.
Bekommt ein Kunde einen neuen Ansprechpartner so gibts ein „ContractAddedToCustomer“ Event.

Die Events sollen so nahe am UseCase sein wie möglcih. Kann man einen Kunden zum beispiel auf verschiedene Weisen anlegen, so gibt es auch verschiedene Events.

Es kann also auch ein „CustomerCreatedByOutlookImportEvent“ geben.

Lesen

Das ist nun der interessante Teil. Niemand möchte in einer Anzeige eine Liste von Events sehen! Also was machen wir ?

Aus diesen Events werden sogenannte Facts erzeugt. Hierfür arbeitet ein Hintergrundprozess diese Events ab. Kommt ein CustomerCreated Event an, so wird z.B. in der Kunden Tabelle ein Insert gemacht.

Kommt ein CustomerRemoved event wird in der Tabelle ein Delete gemacht. usw..

Der Interessante punkt ist dass aus einem Customer nun mehrere Facts generiert werden können.

Der Hintergrund prozess kann sowohl in in eine SQL Datenbank, als auch in eine Graph Datebank , in outlook oder was auch immer wir wollen schreiben. Und das simultan !

Aus den Events erzeugen wir also eine Vielzahl von Abbildungen die genau Passend für unsere Views sind.

So können wir auch viele Werte im Hintergrund voraggregieren oder formatieren. Häufig sind die Queries für eine Anzeige nur noch ein einzelnes Statement. Das Joinen von Daten aus mehreren Quellen wird erstmal nicht mehr benötigt.

Das Bringt aber auch ein Themen auf unseren Zettel den wir bei simplen CRUD anwendung nicht hatten.

Was sind Hürden beim CQRS?

  1. Eventual Consistency
    Geschriebene Daten sind u.U. nicht direkt für das Lesen vorhanden
  2. Komplexität
    Bereiche die mit CQRS implementiert werden sind zumindest anfänglich komplexer

Warum also könnte CQRS trotzdem interessant sein?

1.Skalierung
Man kann besser Skalieren, da read und write getrennte Prozesse sind die man getrennt skalieren kann.

2. Performance

Generell profiteirt die Performance stark von den Gretrennten prozessen. Es müssen nicht mehr viele WErte on Demand ermittelt und aufbereitet werden. Es wird i.d.R. angezeigt was da ist. Die Modelle sind falch und in ihrer Datenhaltung passend vor indiziert.

Ausserdem kann man für jede Anforderung die beste passende Datenhaltung nehmen uind pot. einfach austauschen.

3. Audit Log

Alle sichtbaren Daten / Facts wurdenb aus dem EventLog generiert. Dieses Eventlog ist append only. Es kann also zu jedem Wert jeder Entität genau geagt werden wie er zustande kam.

Manipuliert jemand einen Wert in der Datenbank. Wird er mit dem nächstne Event oder der nächsten Generiung behoben.  Das ist übrigens ein System das sehr an Banken erinnert…

4. Busines Orientierung

Das Schreiben nur aus Events besteht. Sind diese Events sehr nach an dem was aus Businesssicht passiert. Man kann diese Events Businessentscheinder einfach vorlesen. „Kunde ist Verzogen“, „Kunde wurde angelegt“ usw..

Daraus entwickelten sich z.b. Ideen wie das EventStorming

5. Konflikt Management

Entstehen Änderungskonflikte (z.B. in hierarchischen Systemen ) kann man gezielter reagieren. Man erkennt dass nicht nur 2 Felder sich wiedersprechende Änderungen haben sondern man erkennt die Intention hinter der Änderung..

Man hat nur nur die Information dass 2 Bearbeiter das Feld Straße wiedersprüchlcih geändert haben. Würde zum beispiel folgendes sehen:

„Kunden-AusHandschrift-Notiz-erfasst“ event vs. „Kunden-Daten-Aus-Meldebehörde“ und kann nun business rules für genau diesen Fall erstellen und einen Teil der Konflikte automatisch handeln.

 

Resume

Es gibt noch viel mehr zu sagen. Zum Beispiel das in einem Eventlog niemals etwas geändert oder gelöscht werden darf. Es ist Appendonly.

Oder das die Eventual Consistency meist gar kein Problem ist.

Oder das CQRS sich sehr gut mit DDD , insbeosndere mit den BoundContextes vereinen lässt

Oder das man mit einem Entsprechenden CommonDomain Model eine sehr hohe und sehr einfache Testbarkeit bekommt. usw usw….

Doch für jetzt soll es erstmal genug sein und wirken können.

Wer sich mal im EventSourcen direkt probieren möchte dem möchte ich GregYoungs EventStore ans Herz legen. Man kann mit allem EventSourcing betreiben, selbst mit einer reihe von JsonFiles😉 Aber man hat einen wesentlcih leichteen und besseren Einstieg wenn man sich bestehende Lösungen ansieht.

In diesem Zusammenhang möchte ich zum Abschluss noch einen inspirierenden Webcast von Greg Young sehr empfehlen:

 

Und hier einen Rückblick auf 10 Jahre CQRS

See also

5 Schritte zum Hello World mit TypeScript & VS2015

Nachfolgend der einfachste Weg um mit TypeScript zu einem schnellen Hello World zu gelangen.

Es sei noch angemerkt dass es durchaus streitbar ist ob man die TypeScript Compile Optionen der IDE nutzen sollte oder ob eigene Tasks (z.b. mit Gulp o.ä. ) in einer produktiven Umgebung nicht mehr Sinn machen.

  1. VS 2015 Installations Package Installieren > https://www.typescriptlang.org/#download-links
  2. Nach der Installation kann man für ein einfaches HelloWorld Programm das TypeScript Project Template wählenTypeScriptProject
  3. Auf den Projekt Eigenschaften findet man nun einen TypeScript reiter mit diversen Einstellmöglichkeiten. Für einen einfachen Start kann man die „Compile on Save“ Option aktivieren damit aus aus den TypeScript (*.ts) JavaScript Files (*.js) erzeugt werdenTypeScriptProjectOptions.png
  4. In dem angelegten Projekt findet man nun die app.ts welche einen einfachen TypeScript Code für das Ermitteln der Uhrzeit beinhaltet.

app_ts_starter

 

5. Wenn man nun das Projekt ausführt sieht man die Seite mit der aktuellen forlaufenden Uhrzeit über JavaScript

TypeScriptHelloWorld

 

Greg Young about Over-Engeneering

Bei Youtube bin ich über eine Keynote von Greg Young gestoßen. Link findet ihr darunter.

Die Session trifft einen der wichtigsten Punkte der Softwareentwicklung.

Nachfolgend einige Gedanken aufgegriffen, die mich schon länger beschäftigen und in dieser Session zur Sprache kamen.

Software ist Teil eines Ökosystems. Software wird implementiert um Problem lösen, aber nicht jedes!

90% Aufwand für ein 0,1% Feature ist Ineffizient. Software wird entwickelt um produktive Ergebnisse zu haben, und nicht zuletzt um Geld zu verdienen.

Nur allzu leicht wird vergessen, dass der Motivator eines SoftwareProjektes ein Business Case ist. Und Business bedeutet Riskmanagement. Kein Business ohne Risiko. Business bedeutet auch das man mehr Braucht als eine laufende Software. Wenn eine Software für Edge Cases manuelle  Eingriffe braucht ist das richtig, wenn sie wirtschaftlich sind.

Wenn der CEO einmalig Daten in einem bestimmten Format aus der Datenbank braucht und unsere Standardtools das Format zu   95% erfüllen ist es ok, wenn jemand diese Daten nachbearbeitet.

Es wird nicht in Tagelangen Aufwand ein Tool entwickelt, dasss nur  die restlichen 5 Minuten Arbeit automatisiert.

Das bedeutet nicht dass wir unsichere instabile Software schreiben sollen, sondern viel mehr dass  es Fälle geben kann und darf bei denen ein User , Administrator… eingreifen darf.

Hätten die GitEntwickler versucht ein MergeConflict freies DVCS zu entwickeln, dann hätten wir heute noch keins. So schön so ein System auch wäre, dieser anspruch hätte im Ergebnis nur zum Scheitern geführt.

Eine große Veränderung die stillschweigend passierte ist, dass wir SoftwareEntwickler, Architekten, CTO’s, CEOS,…. miteinander reden müssen.
Die besten Lösungen sind manchmal außerhalb der Softwareentwicklung.

Hieraus erfolgt auch die Verantwortung bewusst und nicht leichtfertig Features und Bugs auch mal zu streichen. Es ist verführerisch unliebsame Bugs oder Anforderungen als Ineffizient abzustempeln.

Erfolgreiche Firmen gehen bewusst und rational überlegt Risiken ein. Es werden bewusst ineffiziente Features und Probleme gestrichen und auch Lösungen ausserhalb der SoftwareEntwicklung gesucht.

Frei nach dem Zitat:

Perfektion ist nicht dann erreicht, wenn es nichts mehr hinzu zu fügen gibt, sondern wenn man nichts mehr weglassen kann.– Antoine de Saint-Exupéry, Terre des Hommes

 

 

Cancelation Token in ASP Core Middleware

In klassischen ASP MVC / Web Api Projekte konnte man als Parameter ein CancellationToken definierne, welches dann beim Aufruf automatisch injiziiert wurde.

Das Token wurde dann in den CancelState versetzt falls der Request abgebrochen wurde.

In ASP Core hat das nicht funktioniert . Bei StackOverflow wurde mir geholfen.

Über context.RequestAborted kann man sich ein Token ableiten.

CancellationToken CancellationToken => context?.RequestAborted ?? CancellationToken.None;

 

RX geänderte NuGet Pakete

Wer bereits Rx genutzt hat und sich wundert, kann sich gerade wundern, dass die Pakete nicht mehr verfügbar sind:

Auf der Nuget Seite steht:

The owner has unlisted this package. This could mean that the package is deprecated or shouldn’t be used anymore.

Allerdings gibt das Github repo Aufschluss. Das Paket ist nun als System.Reactive verfügbar.

The NuGet packages have changed their package naming in the move from v2.x.x to v3.0.0

  • Rx-Main is now System.Reactive
  • Rx-Core is now System.Reactive.Core
  • Rx-Interfaces is now System.Reactive.Interfaces
  • Rx-Linq is now System.Reactive.Linq
  • Rx-PlatformServices is now System.Reactive.PlatformServices
  • Rx-Testing is now Microsoft.Reactive.Testing

Lt. Dokumentation sind keine Breaking changes bekannnt.

Die Projekte werden wegen des entfernten NugetListings nicht mehr im VS NugetPackageManager angezeigt.

Allerdings kann man sie immer noch über die NugetPackage Console installieren:

Install-Package Rx-Core