Werken werken werken

Het is een algemeen geweten. Het is eigenlijk niet echt nodig van in een scrum team over te werken. Dat is niet echt een goed idee. Toch wordt het vaker gedaan dan we denken. Het process is zo gemaakt dat je zelf je target zet, elke 2 of 3 weken, afhankelijk van hoe lang de sprint duurt. De belangrijkste zaken staan bovenaan de takenlijst of backlog. Daarom als het project zonder budget of tijd zou vallen, zijn de belangrijkste zaken van het project toch af.

Toch als men ziet dat het project begint te vertragen, wordt er door sommige teamleden overgegaan naar een overdrive mode, en beginnen ze thuis ook zaken te doen. En dit enkel en alleen maar om die target te halen.

Het zou niet mogen zijn. Het team zou als iets dreigt niet af te geraken, moeten proberen te begrijpen waarom het niet afgeraakt is. Daarvoor zijn de retrospectives belangrijk. En de reden waarom iets niet afgeraakt kan vele oorzaken hebben. Dat is dus aan de teamleden om dat uit te zoeken, en om er oplossingen voor te vinden.

Overwerken, want na de uren nog blijven doorgaan is overwerken, leidt tot vermindering van kwaliteit. Men begint moe te worden, en begint daardoor snellere oplossingen te bedenken die later toch slecht blijken te zijn. Daardoor worden er weer extra bugs geïntroduceerd. Waardoor dan de deadline weer niet gehaald wordt, en uiteindelijk, …..  is een burn-out niet ver meer af.

Het is nog voor een andere reden geen goed idee. Voor de sfeer in het team. Als er anderen zijn die merken dat enkele teamleden aan het overwerken zijn, dan krijgen ze misschien wel schuldgevoelens. En het gevolg gaat zijn dat het team in groepjes verdeeld wordt. Dat mag niet de bedoeling zijn, want als de moraal naar beneden gaat, dan daalt ook de kwaliteit. En als de kwaliteit naar beneden gaat, voelen de mensen zich niet meer gelukkig.

En is dat net nu wat de meeste bedrijven proberen te doen. Hun werknemers gelukkig maken tijdens hun arbeidstijd. Great Place To Work is dat concept.

Moeten testers gemeen zijn?

April 1961, een groep van 1400 bannelingen van Cuba was bij het Amerikaanse leger gegaan om de dictator die in Cuba aan de macht was, van de troon te stoten. Ze waren geen professionelen, en Amerika stuurden hun om Cuba binnen te vallen. Een paar dagen later echter, waren de grote overwinnaars niet de Verenigde Staten, maar wel het Cubaanse leger. Dit was een zeer domme zet van Amerika. Nadien is men gaan bekijken hoe het komt dat men zo een dom plan heeft kunnen uitvoeren.

Groepsdenken is een fenomeen, waarbij een groep zodanig wordt beïnvloed door groepsprocessen, dat de kwaliteit van groepsbesluiten vermindert.

De oorzaak was groepsdenken.Door dit process gaat de kwaliteit en besluiten van hetgeen een groep beslist drastisch naar beneden. Hoe komt dat toch? Het valt voor in groepen waarbij de mensen nauw met elkaar samenwerken. Als de groep dan veel belang hecht aan een unanieme mening, kan deze belangrijker worden zodat de groepsleden vergeten kritisch en ook rationeel te denken.

Dit komt zelfs meer voor als er een persoon in de groep zit met macht. Macht om iemand te ontslaan of te evalueren elk jaar is zulk een macht. Als deze “baas” dan aanwezig is, dan is iedereen wat nerveus. Men begint onbewust de andere leden van de groep te observeren. Zijn er mensen bij die tegen de mening van de leider durven in te gaan? Ja? Dan is het veilig om dit ook te doen. Elk lid doet dit onbewust. Als dan iedereen op zich beslist dat het een slecht idee is om tegen de leider in te gaan, omdat ze dan misschien hun werk verliezen, dan komt er een consensus waar zelfs de meerderheid van de groep tegen is. En niemand doet daar iets aan.

Waarom doen mensen dit? Eigenlijk zit dit gedrag in onze genen. Vroeger, als primaten, leefden we ook al in groepen. We hadden dit nodig om te kunnen overleven. Als er een andere groep aankwam om ons aan te vallen, dan moesten we een samenhangende groep zijn. Daar zijn dissidenten niet op hun plaats. Dat is waarom elk lid van de groep dan ook hun leider volgt.

Maar onderzoek heeft ook aangetoond dat als in de groep een dissident zit, en als de groep dat ook toelaat, zonder dat nadien de vriendschap in gevaar komt, dat dan heel het process anders gaat. Dan durven de meeste leden van de groep wel hun visie te uiten. Hierdoor komt er een dynamiek, die de besluitvorming van de groep veel beter maakt. Dit gelt ook als de leider niet aanwezig is.

Daarom, misschien moeten we de volgende keer in een vergadering eens lastig doen, de slechterik spelen. Het komt de besluitvorming zeker ten goede.

Dynamische properties

Python is een leuke taal. Je kan een klasse hebben die dat properties heeft.

Nu zien we dat de width en de height property eigenlijk de zelfde functie is, uitgezonderd van 1 waarde, namelijk de key in de self.fields dictionary. Zou het niet mogelijk zijn om de properties dynamisch aan te maken? Aangezien het python is, is het antwoord positief.

De oplossing ligt ook verborgen in een vorige post. Het gebruik van descriptors die we dynamisch gaan aanmaken kunnen hier voor dienen.

Als er nu een klasse gemaakt wordt die een get heeft en die dat de hardware oproept, en deze dan dynamisch in de Rechthoek klasse wordt aangemaakt, is het probleem opgelost.

De laatste regels code kunnen nog anders geschreven worden, zodat we ook hier geen code wijzigingen meer moeten doen, indien onze fields zouden wijzigen.

Nu is een nieuwe property eenvoudig aangemaakt door enkel de self.fields aan te passen. Eenvoudig en simpel.

Gebruiksvriendelijk of niet ?

Als we denken aan gebruiksvriendelijkheid, dan botsen we al snel op een probleem dat vele projecten hebben. De projecten focussen voornamelijk op functionaliteit. Werkt het systeem wel zoals we verwachten? Dit is goed, maar (er is meestal een maar) focussen we wel op de gebruiker? Voor de gebruiker is duidelijkheid en gebruiksvriendelijkheid van de applicatie minstens even belangrijk.

Je kent het wel, een applicatie die je niet begrijpt, of die zo moeilijk is dat je er eerst een cursus voor moet volgen. Is dat de fout van de gebruiker dat het zo ingewikkeld is gemaakt? Neen, het ligt aan de applicatie. Die is dan gewoon fout gemaakt. En hier kunnen wij als testers meehelpen. Meedragen zodat onze applicatie die we testen wel duidelijk is om te gebruiken. Zodat een gebruiker onze applicatie met plezier gebruikt, dat is ook een van de doelen van een project. Want gelukkige gebruikers of klanten komen terug, is dat niet een van de gouden regels van de verkoop? Waarom kan dat dan niet doorgetrokken worden naar software?

Testen die naar gebruiksvriendelijkheid kijken, worden meestal overgeslagen of zelfs niet eens aan gedacht. We mogen immers geen tijd spenderen aan mindere risico’s. Tijd is immers geld. Maar is klanttevredenheid dat ook niet? Daarom pleitte Peter Roozendaal in zijn presentatie op de voorjaarsconferentie van Testnet om ook naar het gebruikersgemak te kijken. En meer, als er nog niets bestaat in het project, neem dan als tester zelf het initiatief. Neem zelf de verantwoordelijkheid om specificaties te maken voor gebruiksvriendelijkheid. Dat is niet simpel, maar samen met de product owner en de steakholders.

Er is al heel wat geschreven op het internet, gebruik het en zorg ervoor dat de interface waar jij als tester verantwoordelijk voor bent, veel vriendelijker wordt voor de gebruiker. Het loont.

Property decorator

Python heeft een leuk concept, namelijk dat van een property. Dit concept is enkel beschikbaar bij klassen die overerven van object.

Stel dat we een klasse hebben die alle interactie met een auto maken. We noemen de Klasse Car. Als je met de auto rijdt, druk je op het gaspedaal en een snelheid (speed) te verkrijgen. Dus dit zetten we in de klasse.

Het resultaat van car.speed is dus 6. Wat als we nu een maximumwaarde willen invoeren, want op onze wegen mag je toch niet sneller dan 120 rijden. Dan moeten we getters of setters gebruiken:

Deze update voegt deze beperking perfect in. Maar er is een probleem. Nu moeten de gebruikers van deze code al hun code updaten, en dat is niet altijd de bedoeling. Om de compatibiliteit te vrijwaren, kunnen we het property concept gebruiken.

In Python is de property functie een ingebouwde functie die dat een property object voor ons aanmaakt.

Nu kunnen we gelukkig terug car.speed gebruiken. Als we een waarde toekennen aan car.speed, dan wordt de setter set_speed uitgevoerd en als we er van lezen de get_speed. Zo moet dat.

Maar omdat python ook van leesbare code houdt, is er een decorator gemaakt die @property heet. Dit verbergt onze property functie voor ons en maakt van de functie een property object met dezelfde naam.

Maar we hadden hiervoor ook een setter. Ook dat bestaat, want de speed functie is nu een property en die heeft een setter.

Nu hebben we met deze code exact dezelfde functionaliteit als we willen zonder dat de oorspronkelijke interface gewijzigd is. En bovendien makkelijker te lezen als met de property functie.

List comprehensions

Ik ontdekte dat er mensen zijn die niet weten wat sommige syntax is van de python code die ik geschreven heb in mijn test framework. Een van de zaken die nog niet algemeen geweten is, zijn list comprehensions.

Als ik even zoek naar de python website zelf, dan zie ik daar wat zij beschouwen als list comprehension. Het is een bondige manier om lijsten aan te maken. Met een list comprehension moet je als programmeur dus niet altijd een for loop maken in een functie om een lijst aan te maken.

Een list comprehensions is een bondige manier om lijsten aan te maken.

Een voorbeeld zegt meer dan duizend woorden. Stel dat we een lijst willen hebben met getallen die met een vaste waarde worden verhoogd. We kunnen dit maken door de volgende functie:

Als we deze functie oproepen, krijgen we als resultaat een lijst:

Dit zelfde kunnen we vervangen door deze code:

Simpel, niet? Eens je de basis syntax van een list comprehension door hebt, is dit helemaal niet moeilijk meer.

Model Based Testing

De laatste maanden hoor ik veel over model based testing. Het idee vind ik alvast zeer goed. Maak een model en genereer al je testen met een druk op een knop. Modellen kunnen figuren zijn, en dat is dus makkelijker om te interpreteren, want een mens is toch visueel aangelegd, niet ?

Helaas zijn er nog geen goede tools die dat zoiets op een makkelijke manier kunnen doen. Er zijn al wel zogenaamde runners, die dat zoals een soort robot framework, door je figuur stappen en dan proberen alle pijlen uit te voeren.

Ook het aanmaken van de modellen, of graphs is niet zo simpel. Er zijn nog niet echt goede tools om deze graphs op een eenvoudige manier te maken. dotEditor is er eentje, maar de tools ondersteunen dan meestal het graphiz formaat nog niet.

In de open source wereld bestaat het alvast nog niet, en om aan de tools nu veel geld te geven doen we ook niet, het is echt nog veel te vroeg.

start_stop_graphAls we nu even naar die graphs zelf kijken. Niet simpel om een model te maken dat voldoet aan alles. De vraag is, moet dat, maar laten we eens iets proberen.

Stel, we hebben een knop in onze user interface met het woordje START op. Als we erop drukken, dan wijzigt de tekst op de knop naar STOP. Als we dan erop klikken is er terug START te zien, en zo verder.

Hoe modelleren we dit? De figuur hier toont hoe het zou kunnen. Maar wat gebeurd er nu als we met 2 user interfaces zitten die allebei naar dezelfde backend kijken? Moet dan de START van de andere browser ook mee wijzigen? Of niet? Wat als we te samen duwen op de knop?

Dus het is niet simpel om dat allemaal te modelleren. Toch is het concept een goed idee, om zeker te blijven naar te kijken.

Communicatie en Cultuur in Technologie

Woensdag 11 mei 2016, het is weer zover. Het voorjaarsevent van Testnet met als thema “Verbreed je basis, nieuwe vaardigheden voor Testers” is begonnen. Na het woordje van de voorzitter, was het tijd voor de eerste Keynote. De keynote kwam deze keer van Kristoffer Nortström. Communicatie en Cultuur was het thema.

Software Development is a social Activity
J. Weinberg

Het grootste probleem dat we als technische mensen hebben, is volgens Kristoffer niet het technologische. Dat kunnen we immers wel oplossen, hoe moeilijk het ook is. Neen, volgens hem is de interactie met andere mensen een van de moeilijkste zaken. Moeten we wel communiceren met anderen, is dan een vraag. Natuurlijk, want Software Ontwikkeling is eigenlijk een sociale activiteit. Waarom is dat? Omdat software ontwikkeling problemen van mensen moet oplossen. Als er geen probleem was, zou er ook niets te maken zijn. En omdat er problemen bij mensen zijn, moet er ook mee gecommuniceerd worden. Vragen zoals “Wat gaan we maken” of “Zijn we het juiste aan het maken” zijn dan ook enkele van de meest gestelde vragen bij het ontwikkelproces.

Maar als we even naar de prioriteiten gaan kijken bij de meeste projecten, zien we dat de zaken die te maken hebben met menselijke interactie meestal de laagste prioriteiten krijgen. Dat komt volgens Kristoffer omdat dat het moeilijkste is van software projecten, of van projecten in het algemeen. Menselijk gedrag is namelijk moeilijk te doorgronden.

In vele bedrijven hebben we nog andere problemen. Dat is kennisoverdracht. Als je naar de pure kennis kijkt, dat kan je opschrijven, maar de niet verbale kennis (tacit knowledge in het Engels), dat is een ander paar mouwen. Hoe moet je die overdragen? Hoe draag je over dat een collega op een maandagochtend niet aanspreekbaar is? Zulke zaken, dat zijn ook zaken die in elk project voorkomen en er ook toe doen, want die dragen bij aan de sfeer van een bedrijf, of van een project. Agile kan volgens Kristoffer dit oplossen omdat je er elke dag met elkaar moet communiceren, via de stand-ups. Maar persoonlijk denk ik dat dat toch niet zo simpel is als hij het stelt. Dit omdat je enkel over de vooruitgang praat. Wat deed je? Wat ga je doen? Welke struikelblokken ervaar je? Dat zijn de vragen tijdens een stand-up.

Dat de sfeer goed moet zitten in een bedrijf of project is een feit. De kwaliteit wordt dan beter. Meer zelfs, als de kwaliteit die mensen afleveren niet zo hoog is, dan gaat je eigenwaarde naar beneden. Daarom is het niet technische  veel belangrijker dan het technische.

Wijzigen van de cultuur in een organisatie is een van de moeilijkste zaken die er zijn.

Wat ook nog fnuikend is voor de sfeer in organisaties is het “Ons versus Wij” verhaal. Dit komt meestal voor als we met verschillende teams zitten. En daar moet je voor oppassen. De mens is nu eenmaal geprogrammeerd dat ze in groepen willen leven. En mensen die niet tot de groep behoren zijn dan concurrenten en behoren dan tot het slechte kamp. Dit is evolutionair zo gekomen en dat krijgen we er niet uit. Maar zulk gedrag is wel nefast voor de sfeer in een organisatie. Daarom is communicatie ook tussen teams noodzakelijk. Als je dat in een organisatie voorhebt, moet je proberen de cultuur te wijzigen. Maar dat is niet eenvoudig, het is eigenlijk bijna onmogelijk omdat dit afhangt van de mensen, managers, het product, ja eigenlijk van alles waar je mee te maken hebt.

Tot slot vermelde Kristoffer nog het principe van de “Open Kimono“. Daarmee bedoelde hij dat je open moet zijn met de communicatie, zeker als manager. Vertel de mensen wat ze niet zo goed doen, maar vertel hun ook wat ze goed doen. En dan het allerbelangrijkste. Behandel ze niet als kinderen, want dan gaan ze zich als kinderen gedragen.

Als je even over deze keynote nadenkt, dan merk je dat eigenlijk je met meer vragen zit na dan voor de keynote. Maar dat is de bedoeling denk ik. De oplossing voor al deze mogelijke problemen bestaat immers niet, want dat hangt af van situatie tot situatie.

Lijst met alle gemergde branches

remove_checkboxOnze repositories hebben vele branches, wat niet slecht is, goed zelfs, vind ik. Omdat elke branch het resultaat is van een nieuwe feature of bugfix zijn er nogal veel te vinden in onze repository. Als zulk een branch klaar is om gemerged te worden, dan moet iemand deze zaken reviewen. Dit reviewen gebeurd op gitlab. En als het allemaal klaar is, dan is 1 druk op de knop genoeg om alles automatisch te mergen naar onze master branch.

Na het mergen zou de oorspronkelijke branch gewist moeten worden, anders blijf je met vele branches zitten. Gitlab heeft hiervoor een check box. De default waarde is echter dat deze niet geselecteerd is, dus vergeten sommige team leden dit aan te vinken, met als gevolg dat deze branch niet weg is.

Om de branch te wissen kan je de volgende commando’s uitvoeren :

Als dit echter niet onmiddellijk na de merge gedaan wordt, dan is dat vergeten werk. Vandaar dat er vele branches overblijven, en na maanden werk is het niet echt zichtbaar meer welke branches nu gemerged zijn, en welke niet. Gelukkig heeft git hier ook een oplossing voor in de vorm van een commando:

Het bovenstaande commando toont welke remote branches er reeds gemerged zijn in de master branch. Het omgekeerde lukt ook, tonen welke branches er nog niet gemerged zijn in de master:

Runtime Descriptors

In python kan je een klasse hebben met variablen. Dat is een van de basiszaken in een programmeertaal trouwens. Achter deze variablen kan je echter logica steken in python. Daarom is de property decorator uitgevonden.

Met deze properties, kan je dus in plaats van gewoon 1 waarde te geven, een actie doen of nakijken of de waardes voldoet aan de vereisten. Dit volstond voor mij niet, omdat ik de code voor deze properties graag in een andere klasse stak. Gelukkig hebben de ontwikkelaars van python daar al aan gedacht. De Descriptor heeft het ding. De syntax is:

Dit is dus de syntax van een property. Als we nu de property willen aanspreken, dan wordt de logica in de MyProperty classe opgeroepen. Dat is simpel, maar ik wou meer.

Ik wou dat deze properties dynamisch werden aangemaakt. Waarom? Omdat ik een beschrijvende file had gekregen waarin de API staat beschreven om onze backend aan te sturen. Als hieruit zelf code kon worden gegenereerd, moest ik niet al die functies uitschrijven en die gewoon gebruiken met een python achtige syntax. Daarom wou ik tijdens het runnen van mijn testen, die file inlezen en zo code genereren, die ik dan nadien zou kunnen oproepen.

Na lang zoeken, vond ik de manier om deze properties dynamisch te krijgen. Python heeft een functie setattr. Deze zit standaard in de taal en is de oplossing voor mijn probleem:

Op deze manier bevat de Container klasse properties die dynamisch aangemaakt kunnen worden en kan de backend op een manier aangesproken worden zonder er nog bij na te hoeven denken.

Mocht ooit een descriptor of property worden gedelete, dan is delattr ook te bekijken waard.