Agile, Programming

Nieuwe features in software: hoe beslis je welke je bouwt? #Agile

Nichtje had zichzelf getekend in de brief

Ik heb een site gebouwd, en ik bouw daar nog aan, waarin ik de brieven van de familie Schwartze archiveer en documenteer. Vooralsnog ben ik zelf de enige gebruiker van de site. Ik had kunnen beginnen met een site en een API en een database met alle functionaliteit die ik kon bedenken. Dat was veel werk, en dan had ik in de loop van de tijd veel moeten veranderen wegens voortschrijdend inzicht.

Dus ben ik minimaal begonnen: met alleen een database waarin ik data heb ingevoerd met SQL. Die database heb ik geconverteerd naar een netjes gestructureerde database, op basis van wat ik inmiddels over de content had geleerd. Toen wilde ik een overzicht van alle brieven, dat heb ik gemaakt met ReactJS. Brieven hebben afzenders en ontvangers, die wil ik documenteren, dus heb ik daar features voor gemaakt. Minimalistisch, maar wel functioneel.

Nu ben ik in het stadium dat ik de toekomstige bezoekers van mijn site in het vizier heb, en ik kan allerlei functies en features bedenken die ze misschien handig vinden. Maar dan ben ik daarmee maanden aan het programmeren terwijl ik ook de content nog compleet moet maken. Ik kan ook niets meer bijprogrammeren en me concentreren op de content, maar dan maak ik steeds meer work-arounds wegens missende features. Wat ik dus doe is het volgende: iedere keer als ik een nieuwe feature bedenk, dan programmeer ik die niet, maar verzin een work-around met de bestaande software. Pas als ik voor de derde keer die feature zou willen gebruiken, bouw ik ‘m erbij. Dan weet ik inmiddels ook meer in detail wat die feature moet doen.

Als voorbeeld: een brief heeft één afzender, degene die de brief schrijft. Maar soms is er een briefje van tante waar een nichtje een velletje heeft bijgevoegd: dan zijn er twee afzenders. Dat hoeft niet per se zichtbaar te zijn in de database, als tante de afzender is, is het duidelijk genoeg. Totdat ik voor de derde keer twee brieven in één envelop had, toen heb ik alles zo gemaakt dat je meerdere afzenders kunt hebben voor één brief. Hetzelfde gebeurde voor de ontvangers: tante schrijft een brief aan de drie nichtjes.

Ik wilde kunnen zoeken in de brieven, dus heb ik met Apache Lucene een zoekfunctie gemaakt op de content van de brieven. Wat ik nog niet heb is een zoekfunctie op afzenders of ontvangers in de database. Ik blader alfabetisch door de brieven om iemand te zoeken. Dat wordt nu hinderlijk, dus ik ben nu op het punt een zoekfunctie te maken voor afzenders en ontvangers en locaties en dergelijke.

Ik werk dus efficient: ik besteed minimale tijd aan het bouwen van de web site en de API en wat daarbij hoort zodat ik maximaal tijd heb voor de inhoud, waar het tenslotte om gaat. Als ik inhoud af is, en ik er een boek over heb geschreven, dan heb ik tijd om de features toe te voegen die ik zelf nu niet nodig heb maar die voor bezoekers van de site handig zijn. Zodat als het boek verschijnt, ook de site optimaal is.

Deze aanpak klinkt simplistisch, maar ik denk wel dat je ieder project zo zou moeten doen. Je verzint met z’n allen de absolute bare bones structuur van je applicatie of web site, en je bouwt dat. Dan gaan gebruikers aan de slag en pas als ze een feature echt missen, dan bouw je die erbij. Je backlog krijgt dus een extra column: “aantal verzoeken”. Pas als tien gebruikers een feature in de praktijk node missen, bouw je die erbij. Niet met toeters en bellen, maar alleen de minimale feature waar gebruikers of klanten om hebben gevraagd. Is er dan een toeter of een bel die ze nog missen, dan gaan ze vanzelf piepen en bouw je de toeter of bel erbij.

Programming

Dependency injection in Android

I am a great fan of dependency injection in Java. I have used Guice in the past, I have used Apache Tapestry that has a great implementation of dependency injection, but Spring Boot makes DI so easy to use that it surprises me that there are still projects that don’t use it.

On Android, it’s a different story. In the old days, there was Roboguice. Roboguice was based on Google’s Guice, with additions and changes to accomodate Activity and Service classes. I loved Roboguice, but changes in Android made it harder for its developers to maintain it, until they came to the point that they stopped supporting it. I switched to using Toothpick, which I like, but as so few projects use it, I abandoned it.

I also used Robolectric, a testing framework that allows you to integrate DI into your testing.

Dagger is now the DI tool of choice on Android. Dagger requires you to explicitely inject members into activities and other classes. This is a consequence of the architecture of Android that requires extending Activity and Fragment classes. Roboguice had classes like “RoboActivity”, which became cumbersome after we had FragmentActivity, AppCompatActivity and others. Also Dagger requires module classes for configuration, which are similar to Spring Boot configuration classes. Also, you need Component interfaces to allow for DI in activities etc.

The amount of boilerplate code you need for Dagger makes me think that the old Factory pattern is easier to use than Dagger. Also, Dagger comes in versions, when you read a tutorial you need to be careful if the tutorial is actually applicable for the version of Dagger that you use.

The main trouble with DI in Android is a design flaw in Android: your activities extend the Android Activity class, rather than implement an Android Activity interface. Same for Service, Fragment, etc. Activity being an interface would make life easier for DI and for developers. It would also make testing less complicated: if you use DI in tests you need a context object that you don’t have. A few years ago you could use Robolectric that creates a fake context object for you, today you can test on a device, using the device’s context.  I use DaggerMockRule to provide an application context to a test, I have different DaggerMockRules for different types of test.

If only Android had made Activity an Interface rather than a class, we could  have used a simplified version of Spring Boot DI on Android….

Programming

Experiment met nabijheid-app

Screenshot_20200503-112146In de discussies over “corona apps” heb ik een voorbeeld Android app gemaakt waarmee ik kan zien hoe gemakkelijk twee smartphones elkaar met Bluetooth (meer specifiek, met “Bluetooth Low Energy”) kunnen detecteren en bijvoorbeeld hoe goed je de afstand en de tijdsduur van de ontmoeting kunt afleiden.

Op github heb ik de source staan van die app. De app kan twee dingen: de omgeving scannen, met Bluetooth LE, op andere telefoons met deze app, en ook zichzelf zichtbaar maken voor zo’n scan. Je kunt beide functies in de app aan en uit zetten.

Verder kun je een aantal parameters zetten:

  • signaalsterkte waarmee de app zichzelf aan anderen adverteert
  • advertise mode
  • time window, dat is de tijd dat de app een aantal detecties als één contact beschouwt

Je ziet op het scherm de gedetecteerde andere telefoons, met een uniek ID per telefoon dat de app random genereert. Je kunt dat random ID zelf opnieuw genereren zodat je een nieuwe telefoon, een nieuw contact, simuleert. In een tweede scherm (swipe) zie je de verzameling ID’s die de app heeft verzameld. Je hebt dus twee telefoons nodig om dit te testen: de app detecteert alleen telefoons die dezelfde app draaien.Screenshot_20200503-112453

Je kunt aan de ontvangende kant instellen wat de drempel is voor een “detectie”:

  • hoe sterk het ontvangen signaal moet zijn en
  • hoeveel keer je de betreffende zendende telefoon hebt gedetecteerd.

Zo kun je instellen dat je een contact pas “ziet” als je het drie keer hebt gedetecteerd met minimaal -50dB. Zo’n contact wordt dan rood. Met deze app kun je experimenteren wat de juiste waarden zijn zou je de techniek willen inzetten voor detectie van “corona contacten”.

Je kunt de app hier downloaden (als je al een eerdere versie had geïnstalleerd, dan eerst de app verwijderen. Ik had een foutje gemaakt in de eerste versie waardoor een upgrade niet goed werkt). Ik geef geen garanties voor de app, het is een hulpmiddel om te experimenteren met Bluetooth LE. In het derde scherm (swipe) vind je een help scherm.

De app dient niet om “mogelijke besmettingen” op te slaan of te rapporteren. De app heeft geen verbinding met een server. Wat de app alleen doet is aangeven wanneer iemand anders met dezelfde app bij jou in de buurt is.