Lösningens elegans
Det är mycket lätt att, när man arbetar inom IT, bli fokuserad på stora, komplexa lösningar. Det verkar som att det är här de goda lösningarna måste finnas – stora lösningar, mängder av programvara, alla de senaste prylarna. Det vi gör är spännande och det är mycket lätt att ryckas med i farten. Det är roligt att genomföra utmanande, stora projekt. Att höra vad andra IT-proffs gör, hur andra företag löser utmaningar och att tala med leverantörer som har stora system att sälja till oss bidrar allt till spänningen, och det är mycket lätt att förlora känslan för omfattning och mål. Det är så vanligt att se stora, överdrivna lösningar på enkla problem att det verkar som att det helt enkelt måste vara så här IT är.
Men så behöver det inte vara. Komplexitet är fienden till både tillförlitlighet och säkerhet. Onödigt komplexa lösningar ökar kostnaden både vid anskaffning och vid implementering samt i underhåll, samtidigt som de generellt är långsammare, mer ömtåliga och har en stor attackyta som är svårare att överblicka och skydda. Enkla, eller mer passande uttryckt, eleganta lösningar är det bästa tillvägagångssättet. Detta betyder inte att alla konstruktioner kommer att vara enkla, inte alls. Komplexa konstruktioner krävs ofta. IT är knappast ett fält som lider av någon brist på komplexitet. Faktum är att man ofta anser att mjukvaruutveckling kan vara det mest komplexa av alla mänskliga företag, åtminstone bland dem som bedrivs i någon större skala. En typisk IT-installation omfattar miljontals kodrader, hundratals eller tusentals protokoll, ett stort antal sammankopplade system, lager av unika programvarukonfigurationer, fler inställningar än något team möjligen skulle kunna känna till, och först därefter lägger vi till komplexiteten av hundratals eller tusentals eller hundratusentals oförutsägbara, irrationella människor som försöker använda dessa system, var och en på sitt eget unika sätt. IT är, utan tvekan, komplext.
Det som är viktigt är att inse att IT är komplext, att detta inte helt kan undvikas, men att fokusera på att designa och konstruera lösningar så enkelt, så graciöst… så elegant som möjligt. Denna designidé härstammar, åtminstone i mitt sinne, från mjukvaruutveckling där komplex kod ses som ett misstag och enkel, vacker kod som är lätt att läsa, lätt att förstå anses framgångsrik. En av de högsta utmärkelserna som kan tilldelas en mjukvaruingenjör är att hennes kod bedöms vara elegant. Hur passande att detta berömda citat tillskrivs Blaise Pascal, efter vilken ett av de mest populära programmeringsspråken under 1970- och 1980-talen uppkallades (här illa översatt från franska): “Jag är ledsen att jag har varit tvungen att skriva ett så långt brev till dig, men jag hade inte tid att skriva ett kort.”
Det är ofta långt enklare att designa komplexa, krångliga lösningar än det är att fastställa vilket enkelt tillvägagångssätt som skulle räcka. Oavsett om vi har bråttom eller inte vet var vi ska börja en utredning, är elegans alltid en utmaning. Branschens fart är att främja den svårare vägen. Det ligger i leverantörernas intresse att sälja mer utrustning, inte bara för att göra den initiala försäljningen, utan de vet att med mer utrustning kommer mer supportintäkter, och om tillräckligt mycket ny, komplex utrustning säljs slutar supportbehoven öka linjärt och börjar öka geometriskt, eftersom ytterligare support behövs inte bara för själva utrustningen eller programvaran utan även för konfigurationen och supporten av systeminteraktioner eller ytterligare anpassning. De ekonomiska drivkrafterna bakom komplexitet är stora, och de stannar inte vid leverantörerna. IT-proffs vinner mycket anställningstrygghet, eller illusionen av den, genom att hantera stora uppsättningar av hårdvara och programvara som är svåra att sömlöst överlämna till en annan IT-yrkesman.
Ofta är komplexitet så antagen, så förväntad, att processen att välja en lösning börjar med stor komplexitet som en självklar slutsats utan någon hänsyn till möjligheten att en mindre komplex lösning kanske skulle räcka, eller till och med vara överlägsen bortsett från frågan om komplexitet och kostnad i sig. Komplexitet är ibland till och med helt knuten till vissa koncept i en sådan grad att jag faktiskt har mött otrolighet inför tanken att en enkel lösning skulle kunna överträffa en komplex i pris, prestanda och tillförlitlighet.
Retorik är enkelt, men vad är ett verkligt exempel? De bästa exemplen jag ser idag är mestadels relaterade till virtualisering, vare sig det gäller lagring eller ett molnhanteringslager eller programvara eller bara virtualisering i sig. Jag ser ganska ofta att en konversation som bara handlar om virtualisering för en person väcker en omedelbar association till att det krävs nätverksansluten, delad blocklagring, dyr programvara för virtualiseringshantering, många redundanta virtualiseringsnoder och komplex programvara för hög tillgänglighet – varav inget är inneboende i virtualisering och varav det mesta sällan är till för att stödja eller, egentligen, ens i intresset av det företag för vilket de ska implementeras. I stället för att utgå från affärskrav uppstår dessa koncept övervägande från teknologiska förutfattade meningar. Det är enkelt att peka på komplexitet och framstå som om man löser ett problem – komplexitet skapar en känsla av trygghet. Filtrera ner många argument så hör du “Hur kan det inte fungera, det är ju komplext?” Komplexitet ger en illusion av fullständighet, av att ha löst ett problem, men detta kan ofta dölja det faktum att en lösning kanske inte faktiskt är fullständig eller ens funktionell, men graden av komplexitet gör detta svårt att se. Våra sinnen accepterar då inte lätt att ett enklare tillvägagångssätt är mer fullständigt och löser ett problem när ett komplext inte gör det, eftersom det känns så kontraintuitivt.
Ett utmärkt exempel på detta är att vi tar till att diskutera redundans i stället för tillförlitlighet. Tillförlitlighet är svårt att mäta, redundans är enkelt att kvantifiera. En tegelsten är mycket tillförlitlig, även när den är ensam. Det krävs ingen redundans för att en tegelsten ska vara stabil och robust. Dess design är enkel. Du skulle kunna bygga en bärande konstruktion av många redundanta pinnar som inte på långa vägar skulle vara lika tillförlitlig som en enda tegelsten. Om du talar i termer av tillförlitlighet – sannolikheten att konstruktionen inte kommer att fallera – är det tydligt att tegelstenen är ett överlägset val framför flera pinnar. Men om du säger “men det finns ingen redundans, tegelstenen skulle kunna fallera och det finns inget som tar dess plats” låter du dum. Men när vi talar om datorer och datorsystem finner vi system som är så komplexa att människor sällan ser när de har en tegelsten eller en pinne, och eftersom de inte kan fastställa tillförlitlighet, vilket är det som har betydelse, fokuserar de på den lätt kvantifierbara redundansen, vilken inte har det. Hela systemet är för komplext, men att söka den enkla lösningen, den som direkt adresserar kärnan i problemet som ska lösas, kan minska komplexiteten och ge oss ett långt bättre svar till slut.
Detta kan till och med ses i RAID. Speglad RAID är enkel, bara en disk eller uppsättning diskar som är en exakt kopia av en annan uppsättning. Det är så enkelt. Paritets-RAID är komplext med beräkningar över en varierande stripe spridd över många enheter som måste kodas vid skrivning och avkodas om en enhet skulle fallera. Speglad RAID saknar denna komplexitet och löser problemet med disktillförlitlighet genom enkla, eleganta kopieringsoperationer som är mycket tillförlitliga och väl förstådda. Paritets-RAID är onödigt komplext vilket gör det ömtåligt. Ändå, genom att göra detta och genom att underminera sin egen förmåga att lösa det problem för vilket det konstruerades, blir det samtidigt skenbart mer tillförlitligt baserat på ingen annan faktor än sin egen komplexitet. Det mänskliga sinnet hoppar omedelbart till “det är komplext, alltså är det mer avancerat, alltså är det mer tillförlitligt” men ingen av dessa slutledningar är logisk. Komplexitet antyder inte att något är mer avancerat, och att vara avancerad antyder inte att det är tillförlitligt, men det mänskliga sinnet är självt komplext och lätt att vilseleda.
Det finns inget enkelt svar på hur man finner enkelhet. Att veta att komplexitet är dålig till sin natur men ibland oundviklig lär oss att vara uppmärksamma, men det lär oss inte när vi ska misstänka överdriven komplexitet. Vi måste vara vaksamma, alltid söka avgöra om ett mer elegant svar existerar och inte acceptera komplexitet som det rätta svaret enbart för att det är komplext. Vi behöver ifrågasätta föreslagna lösningar och ifrågasätta oss själva. “Är denna lösning verkligen så enkel som den borde vara?” “Är denna komplexitet nödvändig?” “Kräver detta den komplexitet jag hade antagit?”
I de flesta rekommendationer om systemdesign som jag ger, är det första tekniska bedömningssteget jag normalt tar, efter steget att förhöra mig om det affärsbehov som behöver lösas, att ifrågasätta komplexiteten. Om komplexiteten inte kan försvaras är den troligen onödig och motverkar aktivt det syfte för vilket den valdes.
“Är det verkligen nödvändigt att dela upp dessa diskar i många separata arrayer? Om så är fallet, vad är den tekniska motiveringen för att göra det?”
“Är delad lagring verkligen nödvändig för den uppgift du föreslår den för?”
“Motiverar verksamheten verkligen användningen av distribuerade tekniker för hög tillgänglighet?”
“Varför ersätter vi ett enkelt system som var tillräckligt igår med ett dramatiskt mer komplext system imorgon? Vad har förändrats som gör att en stor förbättring, samtidigt som den förblir enkel, inte är mer än tillräcklig utan kräver storleksordningar mer komplexitet och mer utgifter som inte var motiverade tidigare?”
Detta är bara vanliga exempel, komplexitet existerar i varje aspekt av vår bransch. Sök efter enkelhet. Sträva efter elegans. Acceptera inte komplexitet utan att rigoröst granska den. Sätt den genom den ordspråksmässiga vridmaskinen. Tillåt inte komplexitet att smyga sig in där den inte är befogad. Fela inte på komplexitetens sida – vid tvivel, fallera enkelt. Att överförenkla en lösning resulterar vanligen i ett mindre misslyckande, medan att göra den alltför komplex tillåter en långt större grad av misslyckande. Det säkrare alternativet är den enklare lösningen. Och om en enkel lösning väljs och visar sig otillräcklig är det långt enklare att lägga till komplexitet än det är att ta bort den.
