wk voetbalpool webapp: dag 15

 
22 april 2010

Soms is het wel ironisch. Rikkert wou zich eigenlijk in Scala verdiepen, om zijn blik wat te verruimen voorbij het POOOP-schap (Plain Old Object Oriented Programmer-schap). Omdat wij al met dit project bezig waren, leek het een goed idee om hem bij ons te laten aanschuiven. Hij kon dan in Scala proberen om de database aan te spreken. Het leek hem goed om eerst een prototype te schrijven in Java zolang hij nog niet echt goed in Java was – maar geheel volgens de tweede mythe is die eerste versie nooit weggegooid, en heeft hij dus nog 1 dag om iets met Scala te doen – want ook vandaag waren er nog database-aanpassingen nodig.

Gisteren heeft Rikkert zijn driver nog zodanig aangepast dat oude revisies van data automatisch als ‘verwijderd’ werden aangemerkt, en dat als dat met meer dan 75% van de documenten het geval was, de DB automatisch gecomprimeerd zou worden. Dat verkleint hem van tientallen megabytes naar tientallen kilobytes – niet onaardig. Maar vandaag blijkt bij ons ‘front-end team’ dat hoe meer functionaliteit aangesproken wordt, hoe slechter de DB presteert onder Windows. Dus een groot deel van de dag is opgegaan aan het configureren van een VM waar de CouchDB in draait, die met een virtuele ethernet bridge naar het moeder-OS openstaat – en waarvan de DB luistert op de juiste poorten, naar requests van het juiste IP-adres van het moeder-OS luistert, en waarbij de firewall niks afvangt van dataverkeer van en naar de beide kanten.

Christa is verder gegaan met een rich-text-editor voor het kunnen invoeren van een netjes geformatteerde commentaartekst van de administrator. Gelukkig blijkt het resulterende RTF-documentje geen probleem te zijn voor de JSON-structuur die we verwachten. Verder is ze bezig geweest met de status updates, en ze vraagt nog eens om een view waarin een gebruiker de status updates kan zien van alle leden van alle groepen waar hij zelf lid van is. Anatoly heeft de toto-voorspellingen wat gebruiksvriendelijker gemaakt en is nu bezig met het login/logout-gedeelte. Hiervoor moet aan het back-end ook nog wat gebeuren. Jan-Willem wil dat graag op zich nemen omdat hij wel wil weten hoe ik dat met de login heb gedaan – dat moest ook een synchrone afhandeling krijgen – en halverwege de middag is dat gefixt.

Verder meldt Anatoly dat hij bezig is met het acceptatie-proces van nieuwe deelnemers binnen een pool. Er ontstaat een discussie over de opzet van de UI: de indruk ontstaat dat het nu in de richting van een heel ingewikkeld scherm lijkt te lopen met een master-detail-subdetail-subsubdetail-structuur. Het voorstel is om hier een aantal aparte panelen voor te bouwen, eventueel ondersteund door een aantal nieuwe server-side views. Daarnaast moet er nog wat aandacht komen voor de terugkoppeling van validatieberichten, zodat niet nu eens een rood label wordt gebruikt, dan weer een popup, en dan weer nog iets anders. Verder lijkt het gebruik van JSON inconsequent te zijn in hoe getallen over de lijn gaan: soms worden die ingepakt als string, terwijl op andere momenten er een ‘puur’ getal wordt verwacht of wordt teruggegeven. Dit bezorgt Jan-Willem nog de nodige hoofdbrekens, omdat tot nog toe alle testcases alleen maar met de String-variant te maken hadden, en de ‘algemene’ variant dus nooit getest blijkt te zijn. En dan blijkt dat de datastructuren net even onhandig getypeerd zijn, wat de nodige refactoring vergt.

Zelf is hij gisteren nog bezig geweest met de persistentie. Voordat ik gisteren wegging hebben we nog even overlegd hoe de volgorde moet zijn van het inladen van de verschillende actoren en de daarvan afhankelijke views, en hij heeft dat idee verder uitgewerkt in een handige trait die de benodigde functionaliteit voor initialisatie en persistentie makkelijk beschikbaar maakt. Dit lijkt nu goed te werken. We hebben een test-javascriptje (hoewel – inmiddels ook al 11kB en >500 regels code) dat de REST-interface eens flink aanzwengelt, en als die heeft gedraaid en we de applicatie herstarten dan blijken direct na de ‘initialisatiefase’ al meteen 38 actoren actief te zijn – en dat met 2 gebruikers, 2 groepen, 1 wedstrijd met een enkele voorspelling, en meer van dat soort lage getallen.

Qua domein-functionaliteit zijn we vandaag met de laatste puntjes op de i bezig. Ook gele kaarten kunnen nu in het domein worden ingevoerd, en worden nu bijgehouden in een view. Ik zorg ervoor dat een pool-eigenaar meteen ook lid is van zijn eigen pool. Er ontstaat nog discussie over of een eigenaar uit zijn eigen pool moet kunnen stappen. Het lijkt misschien een beetje raar, maar er is wel wat voor te zeggen: bijvoorbeeld een afdelingshoofd die drie verschillende pools aanmaakt, één voor de die-hard supporters, één voor gewone zaterdagavond-beeldbuiskijkers, en één voor de totale voetbalnitwits. Uiteindelijk besluiten we dat dit dus voordelen biedt, en dat scheelt mij meteen een hoop extra validatie voor de ‘unjoin pool’-functionaliteit die ik anders had moeten schrijven. Verder kan een groepseigenaar nu mensen uit zijn pool gooien – dat was een erg simpel stukje functionaliteit: gewoon toestaan dat de functionaliteit achter /groups/<poolnaam>/members/<naam>/unjoin niet alleen door de gebruiker zelf, maar ook door de groepseigenaar mag worden aangesproken. Sommige bugs zijn makkelijk te fixen :-)

Tenslotte stort ik me nog op de aanvraag van Christa voor een status update overzichtsview. Maar als ik er even over nadenk dan blijkt dat nog helemaal niet makkelijk. Sowieso moet dus de Everyone-groep niet meegenomen worden en kan je niet de leden van alle groepen bij elkaar optellen. Maar er moet ook op ingewikkelde manieren op events worden gereageerd. Een van de vragen is: waar haalt deze view zijn data vandaan? We hebben al een aantal andere views die ook gegevens bijhouden die relevant is voor deze view, zoals van welke groepen deze gebruiker lid is, welke (andere) gebruikers er in een groep zitten, en wat de status van de verschillende gebruikers is. Maar ja, eigenlijk is het niet zo netjes om deze views van elkaar afhankelijk te maken. Bovendien moet dan een datawijziging in een van de andere views gepropageerd worden naar deze nieuwe, buiten het Event-mechanisme om: als een event ‘hier’ binnenkomt, is niet gegarandeerd dat het bij de andere views al verwerkt is zodat we de nieuwe data zouden kunnen uitlezen. En om die views dan weer een apart ‘data updated event’ te laten versturen gaat ook weer voorbij aan het verschil tussen domein en reporting.

Dus moet deze view zijn eigen boontjes doppen. Het gevolg is wel dat ik eerst nog wat extra ‘info request events’ moet definieren en gaan gebruiken, en dat er heel veel events heen en weer geschoten gaan worden om alle nodige informatie te verzamelen. Bijvoorbeeld als ik een nieuwe groep binnentreed dan moet dat opgeslagen worden in de view; vervolgens komt er een info-aanvraag wie er allemaal lid van die groep is; en dan moet alle leden gevraagd worden wat hun huidige status is. …En als er een ‘unjoin pool’ event binnenkomt, moet ik ook nog onderscheiden of dat komt doordat ikzelf uit een pool stap of iemand anders; en dan de gebruiker uit de lijst met te volgen mensen halen – tenzij die nog voorkomt in een andere pool waar ik lid van ben. Oftewel de hele lijst leeggooien, al mijn huidige pools vragen wie hun leden zijn, en die weer vragen wat hun status is. Omslachtig, maar wel ‘zoals het hoort’.

Toch is een van de lessen van deze benadering dat er wel veel dataduplicatie plaatsvindt: er zijn veel verschillende views die dezelfde stukjes informatie bijhouden. Ik vraag me af of dat niet efficienter kan – bijvoorbeeld door een soort ‘interne’ views/viewactors te bouwen die eenmalig de data in het domein bijhouden, en die door de ‘externe’ views maar ook door het domein synchroon aangesproken kunnen worden zodra er gegevens nodig zijn. De externe views zouden dan een soort geaggregeerde view zijn op deze interne views, die op hun beurt weer directer op de domein-data aansluiten. Misschien is dat een interessante opzet voor een vervolgproject…?

Daarnaast blijkt nu ook vaak het verschil tussen puur ‘informatieve’ events die info aanvragen of verschaffen, en de meer ‘bedrijfsmatige’ events die meer op commando’s lijken en/of nodig zijn voor het specifiek afhandelen van domeinfunctionaliteit. Hiervoor had ik in eerste instantie de UserStoryPhase van dag 7 in mijn hoofd – maar bijvoorbeeld een RequestStatusReport-event heeft eigenlijk alleen maar een ‘starting’-fase, en de ‘UserStatusReport’-events alleen maar een ‘success’-fase. Misschien is hier ook duidelijker onderscheid tussen te maken – nu moet ik elke keer checken met welke fase hij verstuurd wordt, en houden we dus per conventie het voorgaande aan voor deze gevallen, omdat de info request altijd het begin van een actie initieert, en views eigenlijk alleen naar ‘success’-events zouden moeten luisteren.

Maar aan het eind van de dag compileert ook Christa’dr nieuwe view, dus die kan ik morgen uitgebreid gaan testen. Ik voel nog een stevig stuk javascript aankomen…

En daarmee wordt het half zes, en alles is wel.


Werken met ?
Kijk dan bij onze mogelijkheden voor zowel starters als ervaren engineers.


Categorieën: Development