Het is mogelijk om een applicatie op elk willekeurig platform te draaien. Veel gebruikers verwachten dat je applicatie altijd beschikbaar is en grote hoeveelheden data in een oogwenk verwerkt. Om aan deze wensen te voldoen, staan tegenwoordig termen als ‘reactive programming’ of ‘reactive applications’ centraal. Maar wat wordt er nu eigenlijk bedoeld met deze termen? Is het een trend, de zoveelste popcultuur in de Java-wereld of al gemeengoed? Dit artikel behandelt de achterliggende principes om zo zelf een oordeel te vellen.
Als we over 'reactive applications' spreken, dan bedoelen we vaak applicaties die ontworpen zijn met een nieuwe architectuurstijl. Reactive applications voldoen aan vier kenmerken: event-driven, scalable, resilient, en responsive. Het denken in events ligt ten grondslag aan deze stijl. De andere karakteristieken vloeien voort uit het opbouwen van je applicatie in autonome services, die events afhandelen. Zo’n service wordt ook wel een actor genoemd.
Stel, je wilt een businessproces implementeren dat twee services gebruikt, waarbij Service A een afhankelijkheid heeft op service B. Als ontwikkelaar van een 'traditionele' applicatie koppel je service B expliciet aan service A door een referentie op te nemen van service B in de implementatie van service A. Dit kun je dan via dependency injection weer ontkoppelen.
In een event-driven applicatie werkt het iets anders. Service A stuurt een event uit, zodra hij klaar is met zijn deel van het proces. Service B acteert op het event van service A. Zodra hij het event binnenkrijgt, dan vervolgt deze service de implementatie van het businessproces. Service A weet dus niet expliciet dat service B onderdeel is van het te implementeren businessproces.
Er is dus een subtiel verschil in de ontwikkeling tussen een event-driven applicatie en de meer traditionele service-georiënteerde applicaties. In een traditionele applicatie ben je vaak bezig de toekomstige state te controleren door de verschillende afhankelijke services te orkestreren, terwijl je in een event-driven applicatie referenties van de huidige state meestuurt in het event; het is aan de individuele service om een event op te pikken en te verwerken.
Dit verschil opent een geheel nieuwe wereld van mogelijkheden. De uit te voeren taken in een event-driven applicatie zijn gegroepeerd in autonome, asynchrone en non-blocking services. Zodra er een taak is uitgevoerd, wordt deze meteen weer vrijgegeven, omdat er geen expliciete afhankelijkheden zijn met andere services. Er kunnen meerdere services luisteren naar hetzelfde event. Hierdoor wordt het hergebruik sterk vereenvoudigd. Het asynchrone karakter van een event-driven applicatie maakt het makkelijker taken parallel uit te voeren.
De geïsoleerde services zijn niet alleen makkelijker te testen, maar zijn ook gemakkelijker individueel te optimaliseren. Je kunt denken aan het gebruik van JDBC in plaats van JPA, het opschalen van resources of dat je geavanceerde mechanismen inbouwt voor foutafhandelingen. Hierdoor reageert je applicatie beter op de te verwachte load. Je applicatie wordt waarschijnlijk sneller en weerbaarder tegen onverwachte gebeurtenissen.
Je kunt er zelfs over denken om events op te slaan. Hierdoor heb je naast een persistente state gelijk een soort flight recorder van je gehele applicatie. CQRS is een veelgebruikt principe om dit te implementeren.
Het lijkt heel natuurlijk om in events te denken. Dit is immers wat je dagelijks doet, omdat je handelt naar gebeurtenissen om je heen. Als mensen echter functionaliteit voor een applicatie beschrijven, dan praten ze over dingen die moeten gebeuren. Het is verleidelijk om deze procedurele gedachtegang één-op-één over te nemen in je software. Deze 'reactive' architectuurstijl laat deze werkwijze niet toe.
De beweging naar reactieve applicaties bevat zeer krachtige principes, die voortborduren op de basisprincipes van software design. Deze principes, zoals SOLID, zijn essentieel om een goede balans te vinden in het aantal actoren en mogelijk ondersteunende services binnen je applicatie.
Het is zeker de moeite waard deze ontwikkelingen te volgen en waar mogelijk toe te passen in je oplossing. Ongeacht welke architectuurstijl je uiteindelijk adopteert, simpele en correct geschreven code leidt altijd tot goedwerkende applicaties.