News

Soundbyte 145: Do I make myself clear

25 mei 2014

Allereerst vooraf alvast m’n excuses voor alle niet-programmeurs die deze Soundbyte toch gaan lezen. Het zal wellicht iets minder tot de verbeelding spreken, maar hopelijk zijn de frustraties van een programmeur over punten en komma’s toch vermakelijk.

Ik ben een behoorlijk neuroot als het gaat om de stijl en leesbaarheid van code. Je hebt programmeurs die zich hier minder om druk om maken, maar ik ben het type dat hier wel veel waarde aan hecht. Niet zoveel als aan een goede architectuur, maar als het aan mij ligt zijn ook zaken als consequente naamgeving, indentation (tab óf spaties), trailing-spaces-opruimen allemaal piekfijn in orde. De reden is dat ik vind dat het niet voldoende is wanneer een machine je code kan interpreteren. Wanneer je code schrijft zal deze nog vele malen gelezen en begrepen moeten worden door programmeurs. En dat gaat een stuk sneller en prettiger wanneer de boel er verzorgd en netjes uitziet.

Nu had ik een tijdje terug het genoegen een paar weken bij te mogen springen bij ons backend team. Mee ontwikkelen aan een Java codebase, ik vind dit soort klussen altijd ontzettend leerzaam. Want hoewel ik me redelijk verstaanbaar weet te maken in Java, druk ik me altijd nog het makkelijkst uit in C#. Sleutelen aan productiecode in een taal buiten je comfort-zone geeft altijd weer nieuwe inzichten.
Nu waren de punten die ik eerder beschreef in deze codebase best op orde. Toch merkte ik dat iets me stoorde bij het werken in de code: het las niet echt lekker. Ik begrijp dat dit voor niet ontwikkelaars wellicht wat vreemd kan klinken, maar net als bij een boek leest ook code niet prettig wanneer de zinnen (statements) niet lekker lopen. De reden waarom de zinnen vaak niet lekker liepen waren Yoda conditions. Toen ik dit aankaartte binnen het team bleek dat een aantal nog nooit van dit fenomeen gehoord had.

Yoda conditions

Een Yoda condition is een expressie waarbij het onderwerp en het bijvoeglijk naamwoord in onnatuurlijke volgorde staan. De naam is afkomstig van Yoda, een personage uit Star Wars dat op deze manier spreekt. In plaats van “de lucht is blauw”, zou Yoda zeggen: “blauw is de lucht”. Deze stijl wordt vaak door ontwikkelaars onbewust toegpast in if-statements, hierin maakt het technisch niet uit in welke volgorde de twee waarden staan.

if (theSky == “blue”) { }

doet immers hetzelfde als:

if (“blue” == theSky) { }

Maar voor de leesbaarheid maakt het wel degelijk uit.

Nou heeft Java iets wat volgens mij het gebruik van Yoda conditions bevordert: enums zijn in Java reference types, terwijl het in veel andere talen value types zijn. Gevolg hiervan is dat een variabele van een enum type in Java null kan zijn, waardoor je Null-reference excepties kunt krijgen. Hier is allemaal niks mis mee, het kan ook voordelen hebben. Alleen is in de praktijk het gevolg dat het verleidelijk is om in Yoda-conditions te gaan ‘spreken’ om deze Null-reference excepties te voorkomen.

if (theSky.Equals(Colors.Blue)) { }

geeft een Null-reference exceptie wanneer theSky gelijk aan null is. Dit kan eenvoudig voorkomen worden door te schrijven:

if (Colors.Blue.Equals(theSky)) { }

Maar dat leest minder lekker. Je zou natuurlijk ook het volgende kunnen schrijven:

if (theSky != null && theSky.Equals(Colors.Blue)) { }

Het blijft natuurlijk een kwestie van smaak, maar veel ontwikkelaars gebruiken (begrijpelijk) de Yoda-condition variant. Het was wel weer een moment waarop ik besefte dat ontwerpbeslissingen (in een taal in dit geval) verrassende gevolgen kunnen hebben. Iets wat iedere keer weer blijkt bij het ontwerpen van software: het blijft complex.

Een oplossing

Hoe dit nu op te lossen? (als je het al op wilt lossen, een hoop mensen zullen zich op dit moment afvragen waar ik me zo druk om maak)
Laten we eens naar C# kijken. Daar is ongetwijfeld van alles op aan te merken, maar het beschreven probleem speelt er niet omdat ook in C# enums value types zijn. Maar stel dat het wel zou bestaan, dan zou C# best een mooie oplossing hebben: Extension Methods.
Extension methods zijn niets meer dan een beetje syntactic sugar: iets wat je code leesbaarder maakt maar eigenlijk al prima op andere wijze op te lossen is. Het zijn static methods waarbij je als eerste argument een variabele van een bepaald type meegeeft. Hierdoor wordt deze method beschikbaar op iedere instantie van dit type. Onder water wordt runtime natuurlijk een normale static method aangeroepen, maar het geeft je development-time de mogelijkheid leesbaardere code te schrijven. Stel dat Java extension methods had, zou een mogelijk oplossing bijvoorbeeld kunnen zijn:

public static boolean Is(this Color color, Color other) {
    if (color == null) {
        return other == null;
    }
    return color.Equals(other);
}

Waardoor je zou kunnen schrijven:

if (theSky.Is(Colors.Blue)) { }

Zonder het risico op Null-reference excepties.

Dus wie weet… met Java 8 zijn dan eindelijk Lambda expressions en de streaming API beschikbaar gekomen (*kuch*C#*kuch*2007*kuch*), wat naast technische mogelijkheden ongetwijfeld ook de leesbaarheid van de code ten goede zal komen. Wellicht maken extension methods de oversteek ook nog wel.

Tim!

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *