Elegantie van oplossingen
Wanneer je in de IT werkt, is het heel gemakkelijk om je te richten op grote, complexe oplossingen. Het lijkt alsof daar de goede oplossingen moeten liggen – grote oplossingen, veel software, alle nieuwste gadgets. Wat wij doen is spannend en het is heel gemakkelijk om meegesleept te raken in het momentum. Het is leuk om uitdagende, grote projecten te doen. Horen wat andere IT-professionals doen, hoe andere bedrijven uitdagingen oplossen en praten met leveranciers die grote systemen aan ons allen willen verkopen, draagt allemaal bij aan de opwinding, en het is heel gemakkelijk om het gevoel voor reikwijdte en doel te verliezen. Het is zo gangbaar om grote, buitensporige oplossingen voor eenvoudige problemen te zien dat het lijkt alsof dit nu eenmaal is hoe IT in elkaar zit.
Maar dat hoeft niet zo te zijn. Complexiteit is de vijand van zowel betrouwbaarheid als beveiliging. Onnodig complexe oplossingen verhogen de kosten, zowel bij aanschaf als bij implementatie en onderhoud, terwijl ze over het algemeen trager en kwetsbaarder zijn en een groot aanvalsoppervlak hebben dat moeilijker te bevatten en te beschermen is. Eenvoudige, of beter gezegd, elegante oplossingen vormen de beste aanpak. Dit betekent niet dat alle ontwerpen eenvoudig zullen zijn, helemaal niet. Complexe ontwerpen zijn vaak vereist. IT is bepaald geen vakgebied dat enig gebrek aan complexiteit kent. Sterker nog, vaak wordt aangenomen dat softwareontwikkeling wellicht de meest complexe van alle menselijke ondernemingen is, althans van die welke op enige schaal worden uitgevoerd. Een typische IT-installatie omvat miljoenen regels code, honderden of duizenden protocollen, grote aantallen onderling verbonden systemen, lagen van unieke softwareconfiguraties, meer instellingen dan welk team ook ooit zou kunnen kennen, en pas daarna voegen we de complexiteit toe van honderden of duizenden of honderdduizenden onvoorspelbare, irrationele mensen die deze systemen proberen te gebruiken, elk op een unieke manier. IT is, zonder enige twijfel, complex.
Wat belangrijk is, is te erkennen dat IT complex is, dat dit niet volledig kan worden vermeden, maar om je te richten op het ontwerpen en ontwikkelen van oplossingen die zo eenvoudig, zo sierlijk… zo elegant mogelijk zijn. Dit ontwerpidee komt, in mijn beleving althans, voort uit de software-engineering, waar complexe code als een fout wordt gezien en eenvoudige, mooie code die gemakkelijk te lezen en gemakkelijk te begrijpen is als geslaagd wordt beschouwd. Een van de hoogste lofbetuigingen die een software-engineer ten deel kan vallen, is dat haar code als elegant wordt bestempeld. Hoe toepasselijk dat dit beroemde citaat (slecht vertaald uit het Frans) wordt toegeschreven aan Blaise Pascal, naar wie een van de populairste programmeertalen van de jaren zeventig en tachtig werd vernoemd: “Het spijt me dat ik u zo'n lange brief heb moeten schrijven, maar ik had geen tijd om u een korte te schrijven.”
Het is vaak veel gemakkelijker om complexe, ingewikkelde oplossingen te ontwerpen dan om te bepalen welke eenvoudige aanpak zou volstaan. Of we nu haast hebben of niet weten waar we een onderzoek moeten beginnen, elegantie is altijd een uitdaging. Het momentum van de branche is om het moeilijkere pad te bevorderen. Het is in het belang van leveranciers om meer apparatuur te verkopen, niet alleen om de initiële verkoop te realiseren, maar ze weten dat met meer apparatuur meer supportgeld gemoeid is, en als er voldoende nieuwe, complexe apparatuur wordt verkocht, neemt de supportbehoefte niet langer lineair toe maar gaat ze geometrisch toenemen, omdat er aanvullende ondersteuning nodig is, niet alleen voor de apparatuur of software zelf, maar ook voor de configuratie en ondersteuning van systeeminteracties of aanvullende maatwerkaanpassingen. De financiële invloeden achter complexiteit zijn groot, en die houden niet op bij de leveranciers. IT-professionals verwerven veel baanzekerheid, of de illusie daarvan, door het beheer van grote verzamelingen hardware en software die moeilijk naadloos aan een andere IT-professional zijn over te dragen.
Vaak wordt complexiteit zozeer als vanzelfsprekend aangenomen, zozeer verwacht, dat het proces van het selecteren van een oplossing begint met grote complexiteit als een uitgemaakte zaak, zonder enige overweging van de mogelijkheid dat een minder complexe oplossing zou kunnen volstaan, of zelfs superieur zou kunnen zijn, los van de kwestie van complexiteit en kosten zelf. Complexiteit is soms zelfs volledig verbonden aan bepaalde concepten, in een mate dat ik daadwerkelijk ongeloof heb ondervonden bij het idee dat een eenvoudige oplossing een complexe zou kunnen overtreffen op het gebied van prijs, prestaties en betrouwbaarheid.
Retoriek is gemakkelijk, maar wat is een voorbeeld uit de praktijk? De beste voorbeelden die ik tegenwoordig zie, hebben voornamelijk te maken met virtualisatie, of het nu gaat om opslag of een cloudbeheerlaag of software of gewoon virtualisatie zelf. Ik zie vrij vaak dat een gesprek over louter virtualisatie bij sommige mensen onmiddellijk de connotatie oproept dat genetwerkte, gedeelde blokopslag, dure virtualisatiebeheersoftware, vele redundante virtualisatieknooppunten en complexe hoge-beschikbaarheidssoftware vereist zijn – geen van alle intrinsiek aan virtualisatie en de meeste zelden ten behoeve van de ondersteuning van, of zelfs maar in het belang van, het bedrijf waarvoor ze zullen worden geïmplementeerd. In plaats van vanuit bedrijfsvereisten te werken, komen deze concepten overwegend voort uit technologische vooronderstellingen. Het is eenvoudig om naar complexiteit te wijzen en de schijn te wekken een probleem op te lossen – complexiteit creëert een gevoel van comfort. Filter veel argumenten uit en je hoort “Hoe kan het niet werken, het is complex?” Complexiteit verschaft een illusie van volledigheid, of van het opgelost hebben van een probleem, maar dit kan vaak het feit verhullen dat een oplossing in werkelijkheid misschien niet volledig of zelfs maar functioneel is, terwijl de mate van complexiteit dit moeilijk zichtbaar maakt. Onze geest zal dan niet gemakkelijk accepteren dat een eenvoudigere aanpak vollediger is en een probleem oplost waar een complexe dat niet doet, omdat dit zo contra-intuïtief aanvoelt.
Een goed voorbeeld hiervan is dat we onze toevlucht nemen tot het bespreken van redundantie in plaats van betrouwbaarheid. Betrouwbaarheid is moeilijk te meten, redundantie is eenvoudig te kwantificeren. Een baksteen is uiterst betrouwbaar, zelfs als enkeling. Er is geen redundantie voor nodig om een baksteen stabiel en robuust te laten zijn. Het ontwerp ervan is eenvoudig. Je zou een draagconstructie kunnen maken van vele redundante stokjes die lang niet zo betrouwbaar zou zijn als één enkele baksteen. Als je het hebt over betrouwbaarheid – de kans dat de constructie niet bezwijkt – is het duidelijk dat de baksteen een superieure keuze is boven meerdere stokjes. Maar als je zegt “maar er is geen redundantie, de baksteen zou kunnen bezwijken en er is niets dat zijn plaats inneemt” klink je dwaas. Maar wanneer we het hebben over computers en computersystemen, treffen we systemen aan die zo complex zijn dat mensen zelden zien wanneer ze een baksteen of een stokje hebben, en dus richten ze zich, omdat ze de betrouwbaarheid die er werkelijk toe doet niet kunnen bepalen, op de eenvoudig te kwantificeren redundantie, die er niet toe doet. Het hele systeem is te complex, maar het zoeken naar de eenvoudige oplossing, degene die rechtstreeks de kern van het op te lossen probleem aanpakt, kan de complexiteit verminderen en ons uiteindelijk een veel beter antwoord geven.
Dit is zelfs te zien bij RAID. Mirrored RAID is eenvoudig, gewoon één schijf of een set schijven die een exacte kopie is van een andere set. Het is zo eenvoudig. Parity RAID is complex, met berekeningen over een variabele stripe verdeeld over vele apparaten die bij het schrijven gecodeerd moeten worden en gedecodeerd mochten een apparaat uitvallen. Mirrored RAID mist deze complexiteit en lost het probleem van schijfbetrouwbaarheid op door eenvoudige, elegante kopieerbewerkingen die uiterst betrouwbaar en zeer goed begrepen zijn. Parity RAID is onnodig complex, waardoor het kwetsbaar wordt. Maar door dit te doen, en door zijn eigen vermogen om het probleem op te lossen waarvoor het is ontworpen te ondermijnen, wordt het ook tegelijkertijd ogenschijnlijk betrouwbaarder, op grond van geen andere factor dan zijn eigen complexiteit. De menselijke geest springt onmiddellijk naar “het is complex, dus het is geavanceerder, dus het is betrouwbaarder” maar geen van beide gedachtesprongen is logisch. Complexiteit duidt er niet op dat iets geavanceerder is, en geavanceerd zijn duidt er niet op dat iets betrouwbaar is, maar de menselijke geest zelf is complex en gemakkelijk te misleiden.
Er is geen eenvoudig antwoord voor het vinden van eenvoud. Weten dat complexiteit naar haar aard slecht is, maar soms onvermijdelijk, leert ons om oplettend te zijn, maar het leert ons niet wanneer we over-complexiteit moeten vermoeden. We moeten waakzaam zijn en altijd proberen te bepalen of er een eleganter antwoord bestaat en complexiteit niet als het juiste antwoord accepteren louter omdat het complex is. We moeten voorgestelde oplossingen ter discussie stellen en onszelf ter discussie stellen. “Is deze oplossing werkelijk zo eenvoudig als ze zou moeten zijn?” “Is deze complexiteit noodzakelijk?” “Vereist dit de complexiteit die ik had aangenomen?”
Bij de meeste aanbevelingen voor systeemontwerp die ik geef, is de eerste technische bepalingsstap die ik gewoonlijk neem, na de stap van het navragen van de bedrijfsbehoefte die opgelost moet worden, het ter discussie stellen van complexiteit. Als complexiteit niet verdedigd kan worden, is ze waarschijnlijk onnodig en werkt ze actief het doel tegen waarvoor ze gekozen werd.
“Is het werkelijk noodzakelijk om die schijven op te splitsen in vele afzonderlijke arrays? Zo ja, wat is de technische rechtvaardiging om dat te doen?”
“Is gedeelde opslag werkelijk noodzakelijk voor de taak waarvoor je het voorstelt?”
“Rechtvaardigt het bedrijf werkelijk het gebruik van gedistribueerde hoge-beschikbaarheidstechnologieën?”
“Waarom vervangen we een eenvoudig systeem dat gisteren toereikend was door een drastisch complexer systeem morgen? Wat is er veranderd waardoor een grote verbetering, met behoud van eenvoud, niet ruim voldoende is maar ordes van grootte meer complexiteit en meer uitgaven vereist die voorheen niet gerechtvaardigd waren?”
Dit zijn slechts gangbare voorbeelden; complexiteit bestaat in elk aspect van onze branche. Zoek naar eenvoud. Streef naar elegantie. Accepteer complexiteit niet zonder ze rigoureus te toetsen. Leg ze door de spreekwoordelijke wringer. Sta niet toe dat complexiteit binnensluipt waar ze niet gerechtvaardigd is. Dwaal niet af naar de kant van complexiteit – bij twijfel, faal eenvoudig. Een oplossing te veel vereenvoudigen resulteert doorgaans in een kleine storing, terwijl ze te complex maken een veel grotere mate van falen mogelijk maakt. De veiligere gok ligt bij de eenvoudigere oplossing. En als een eenvoudige oplossing wordt gekozen en ontoereikend blijkt, is het veel gemakkelijker om complexiteit toe te voegen dan om ze te verwijderen.
