Hoe de Planning Poker Tool onze devs helpt met thuiswerken

1 juli 2020

Na dik vier maanden COVID19-pandemie is het misschien wel de meest gestelde vraag: “Bevalt het thuiswerken een beetje?”. Nergens ontkom je er aan. En de antwoorden zijn vaak even talrijk als belegen. Van cliche grappen over Zoom-sessies in de onderbroek en strategisch overleg via de Call of Duty-server tot veel te serieuze discussies over etherdiscipline en het nut en de noodzaak van eindeloze updates over de actuele situatie thuis. Awkward…

Improvisatie

Wat we in ieder geval kunnen vaststellen is dat thuiswerken een hoop improvisatie vergt. Van iedereen. En dus ook van ons als developers. Natuurlijk verlopen sommige processen sneller nu we thuis in alle rust code kunnen schrijven. De Bose Noise Canceling is onze grootste vriend, nietwaar? Maar andere zaken zijn weer ineens een grotere uitdaging geworden nu we niet fysiek op kantoor zitten. Zo wil je soms graag een collega recht in de ogen kunnen kijken. Of direct aanspreken. Bijvoorbeeld bij het maken van inschattingen van onze projecten.

Pokeren kan ook online!

Hiervoor ontwikkelden we in 2018 een kaartspel dat we Planning Poker noemden. Dit kaartspel speelt nog elke dag een belangrijke rol in onze prognoses. Maar omdat we in het huidige corona-tijdperk onmogelijk samen een kaartje kunnen leggen, hebben we een online variant ontwikkeld: de Planning Poker Tool. In deze blogpost doen we een deep dive in de onderliggende techniek van de applicatie. Tevens leggen we uit waarom we zijn afgestapt van onze klassieke event driven benadering (m.b.v. WebSockets) naar een data polling implementatie met behulp van Laravel Livewire.

Enrise Planning Poker Carddeck

Wat is de Planning Poker Tool?

Het doel van de applicatie is eenvoudig: een Product Owner in staat stellen samen met developers en testers een redelijke inschatting te maken voor een specifieke story. Op kantoor – pre-corona – gebruikten we als gezegd een fysiek kaartspel met getallen die de ingeschatte tijd aangeven. De Product Owner introduceert het onderwerp en de rest legt een kaart bij met zijn of haar inschatting. De achterliggende boodschap: Accepteer dat inschattingen inschattingen zijn. Het worden binnen de agile methodiek niet voor niets story points genoemd; inschattingen horen niet in tijd gedaan te worden, want een story bestaat ook uit complexiteit, onzekerheid en moeite. Story points zijn relatief. Een story met 2 punten is niet 2x zo groot als een story met 1 punt.

Werking van de Planning Poker applicatie

Hoe weerspiegelt de online applicatie het analoge proces van het kaartspel? In de basis werkt het als volgt:

  1. Een gebruiker maakt een nieuwe virtuele ruimte aan en nodigt de mensen uit die gaan inschatten via een uitnodigingslink.
  2. Degene die de kamer heeft aangemaakt (product owner) kan dan vervolgens een nieuw onderwerp instellen en de inschatting starten.
  3. De andere gebruikers kiezen nu een kaart en slaan hun inschatting op
  4. Nadat de product owner de inschatting stopzet, krijgt iedereen van elkaar de ingeschatte uren te zien. De product owner ziet – te allen tijde – de inschatting gemaakt door andere gebruikers (realtime).
Planning Poker tool, zo werkt het

Om dit mogelijk te maken hebben we drie Livewire componenten nodig, namelijk voor:

  1. Het weergeven en instellen van het onderwerp
  2. Het weergeven van de deelnemers en hun inschattingen
  3. Het weergeven van de poker kaarten

Ter illustratie laten we hieronder zien hoe we Livewire component #3 van bovenstaand lijstje hebben herschreven.

​Klassieke event-driven benadering (m.b.v. WebSockets)

Om in realtime de actuele status te kunnen updaten voor alle deelnemers, hebben we in onze initiële aanpak gekozen voor een event-driven approach, waarbij de gebruikers via WebSocket verbindingen van updates worden voorzien zodra er een `Event` wordt uitgezonden.

Livewire biedt ondersteuning voor het luisteren naar events via Laravel Echo (documentatie). De `EstimationCards` Livewire component (hieronder weergegeven) laat zien hoe binnenkomende events met behulp van Echo worden afgehandeld in de `getListeners()` methode. Daarnaast wordt er ook een `EstimationUpdated` event _uitgezonden_ (broadcast) wanneer een deelnemer zijn inschatting opslaat.

Carbon

Deze component deelt de onderlinge staat via de `public` properties met de bijbehorende Laravel blade view, zoals gedefinieerd in de `render()` methode. In de _listeners_, zie je dat deze Livewire component actief luistert naar inkomende events en daarop de interne staat aanpast. Deze nieuwe staat – bijvoorbeeld het laten zien van de pokerkaarten wanneer het `EstimationCreated` event wordt ontvangen – is op deze manier gesynchroniseerd met alle deelnemers.


Hoewel deze aanpak op zich prima werkt, lijkt er een lichter alternatief te bestaan in de vorm van Livewire polling.

Refactor naar Livewire polling

Livewire beschikt over een `wire:poll` directive, dat gebruikt kan worden om een component te verversen met een specifiek tijdsinterval (standaard 2 seconden). Lees de Livewire documentatie voor een overzicht van alle beschikbare opties.

Carbon

​ De `public` properties die we eerder hebben gedefinieerd in de Livewire component worden hierbij niet automatisch geüpdatet nadat deze initieel zijn ingesteld bij het mounten. Daarom is de truc in dit geval om de variabelen die we delen met de blade view mee te geven als functie. ​

Carbon

Wanneer de component nu wordt ververst (n.a.v. `wire:poll`), zullen de gedeelde variabelen worden herberekend en automatisch worden bijgewerkt aan de kant van alle deelnemers.

Omdat we de variabelen nu delen als functies, kunnen we ook de variabelen die we in onze event-driven benadering hebben gedeclareerd verwijderen: `$estimation``$cardsEnabled` en `$selectedValue`.

De refactor elimineert volledig de noodzaak om naar uitgezonden events te luisteren, zodat de `getListeners()` methode en de respectievelijke `on{Event-Naam}()` methoden ook niet langer nodig zijn.

De blade view voor de betreffende Livewire component ziet er nu als volgt uit:

Carbon

Omdat we geen interval meegeven, zullen alle Livewire componenten nu iedere 2 seconden ververst worden. Als er updates zijn, zal de DOM hierbij automatisch worden geüpdatet, waardoor iedereen de meest recente data ziet.

Conclusie

We hopen dat deze blogpost extra inzicht verschaft in de mogelijkheden van Livewire’s `wire:poll` mechanisme om te voorzien in het automatisch bijwerken van webpagina’s met nieuwe data voor meerdere gebruikers.

  • Een nadeel van deze oplossing is dat het pollen van data met Ajax-verzoeken een grotere belasting is voor de backend en dat er meer queries worden uitgevoerd dan strict noodzakelijk. Voor applicaties met minder dan duizenden en duizenden bezoekers is deze druk echter verwaarloosbaar.
  • Het grote voordeel is dat de code nu een stuk lichter is geworden en gezien het feit dat Livewire het pollen naar nieuwe data pauzeert wanneer de applicatie niet wordt bekeken, is deze refactor naar mijn mening absoluut de moeite waard.

In de refactor van deze applicatie hebben we 3 `Event` classes en bijna 300 (!) regels code kunnen verwijderen, resulterend in een begrijpelijkere en beter te onderhouden codebase. En dat is uiteindelijk waar we het allemaal voor doen. Ook vanuit huis.

Referenties

De volgende artikelen hebben ter inspiratie gediend voor het tot stand komen van deze refactor en blogpost:

Replacing web sockets with Livewire
Freek Van der Herten’s blog on PHP, Laravel and JavaScript
Building a realtime dashboard powered by Laravel, Livewire and Tailwind (2020 edition)
Freek Van der Herten’s blog on PHP, Laravel and JavaScript