Reactive hoe doe je dat dan?

Een reactive applicatie is gebaseerd op drie pijlers.

  • Messaging en events, actors en eventsourcing
  • Functioneel programmeren
  • Domain modelleren

Dit alles gebaseerd op een fundament van BigData.

En dat hangt nauw met elkaar samen.

Events en het Actor model

In een reactive applicatie worden events verwerkt door Actors. Het actor model is een alternatief computing model. Berekeningen worden uitgevoerd door een bericht te sturen naar een actor. De actor heeft een input queue, en handelt de berichten in volgorde een voor een af. De actor heeft state, en na ieder bericht is de state aangepast. De actor kan natuurlijk ook weer berichten naar andere actors sturen. Het staat in contrast met het van Neumann model, waarin imperatief programmeren, middels een processor die stap voor stap instructies uitvoer. Actors zijn bedacht door Carl Hewitt (Actor Model of Computation).

Je kunt het zien als een logische volgende stap van TP-monitor (processen) naar Appserver (threads) naar Actor (Reactive). We krijgen als het ware steeds kleinere eenheden.

Events hebben ook te maken met Event Sourcing. Zie de bliki van Martin Fowler (Event Sourcing). Een bekende grap is dat de database eigenlijk niet meer is dan een optimalisatie om snel de laatste stand van data uit de journals te kunnen lezen. Journals kunnen natuurlijk worden gebruikt om de database te reconstrueren bij een calamiteit. In eventsourcing is het geen grap meer, maar de normale gang van zaken. Van een gegeven slaan we de begintoestand op en de mutatie events. Als iemand zijn saldo wil weten, dan berekenen we dat uit de beginstand en de mutaties. En uiteraard is het goed om dat af en toe bij te werken, zodat de log kort blijft, maar dat is een optimalisatie.

Domain modelleren

Domain Driven Development beschrijft het domein model in termen van de business, het kennis-domein. In een domein model worden verschillende soorten objecten onderscheiden. Value objecten bevatten een value, logisch natuurlijk, en die kun je dus niet muteren. Een waarde bijvoorbeeld drie, blijft altijd drie, en als je er eentje bij krijgt, dan heb je er vier, maar drie is nog altijd drie. Drie en vier zijn dus verschillende values. Het is in het algemeen een object met een alleen een constructor en getters. Entiteiten hebben een lifecycle, en die kunnen tijdens de lifecycle gemuteerd worden. Daarom is er ook een identiteit nodig, om het aan te kunnen duiden. Repositories regelen de administatie en persistentie van de entiteiten. Een Student zou een entiteit kunnen zijn en een adres een value object. Als de student verhuist, dan krijgt hij een ander adres, en iemand ander gaat wellicht op het oude adres wonen.

Een aggregate is een Entiteit op een wat groffer niveau. Het bestaat in het algemeen uit een entiteit, met wat andere entiteiten die daar bijhoren. Een order en order regels en betalingen zou een voorbeeld kunnen zijn.

Er zijn nog veel meer begrippen zie bijvoorbeeld Implementing Domain Driven Design.

Functioneel programmeren

De derde pijler is functioneel programmeren. Functionele programmeertalen doen eigenlijk niks anders dan expressies uitrekenen. een functie krijgt input argumenten mee, en berekent een antwoord als output, en dan is het klaar. Er zijn geen zij-effecten, er wordt niet ondertussen even iets van het netwerk of uit een bestand gehaald, of weggeschreven. De output is een functie van de input. Precies zoals wiskundigen dat graag zien.

Dat klinkt simpel, maar er zit een wereld onder. Functies zijn ook gewoon values, en je hebt functies, waarmee je functies kunt samenstellen (hogere orde functies).  En zo kun je complexe berekeningen op een hoog abstractie niveau uitvoeren. Het is wel even wennen als je imperatieve talen gewend bent.

En dit tezamen

Dit werkt mooi samen. Een functioneel domein model beschrijft het domein op een hoog abstractie niveau, waardoor ontkoppeling en meerdere implementatie vormen beschikbaar zijn. Je moet het domein model zien als een soort abstracte syntax, die op verschillende manieren als concrete syntax kunt weergeven.

Functioneel programmeren helpt niet alleen om het domein model als algebra te beschrijven, het werkt ook mooi in een actor. De actor verwerkt een bericht uit de queue, en update zijn state. Het uitrekenen van de nieuwe state is dus een functie van de oude state en een bericht. Hiervoor is een functionele taal dus prima geschikt.

Er is ook een relatie tussen het domein model en het actor model. We brengen een aggregate root onder in een actor. De oude ACID transacties kunnen we vergeten. De synchronisatie vindt plaats op actor niveau, en op actor niveau is alles vanzelf serializable. En het is makkelijk te controleren en na te rekenen.

Conclusie

Het drietal Domain modelling, Functioneel programmeren, en het Actor model vormen een uitstekende combinatie van technieken om applicaties mee te bouwen.

Door in een actor functies te gebruiken, die een aggregate van de ene consistente toestand in de andere brengen kunnen we een bepaalde integriteit garanderen. Synchronisatie tussen actors is er niet. Als er geld wordt overgemaakt van de ene naar de andere actor dan zijn ze niet op hetzelfde moment consistent. We noemen dat eventual consistency, en dat is de opvolger van het de ACID transacties.

Dat is anders denken. En dat maakt het juist interessant.