5 kända Programmeringscitat, förklarade
att vara programmerare är att registrera dig för ett liv med konstant lärande. Fontänen av nya-nya funktioner, nya språk, nya verktyg, nya ramar—slutar aldrig Forsa. Men datavetenskap är också ett överraskande traditionellt fält som är grundat i tidtestade principer. Vi har lagt till objektorienterad programmering, modern hårdvara och artificiell intelligens. Men trots dessa förändringar är många av de insikter som först formulerades för en generation sedan fortfarande sanna idag.
i den här artikeln har jag dissekerat några av mina favoritcitat om datavetenskap. Det enda villkoret jag ställer är att varje citat måste vara minst tjugo år gammalt. För medan gammal teknik snabbt blir värdelös, har de gamla buden från våra programmeringsförfäder mycket mer uppehållskraft.
“alla problem inom datavetenskap kan lösas med en annan nivå av indirektion.”- David Wheeler
här är ett ofta upprepat compsci-citat som få utvecklare vill förklara. Men det är en av mina favoritprogrammeringsanningar, för det slår i hjärtat av vad kodning handlar om.
det enklaste sättet att börja tänka på indirektion är att föreställa sig lager. Säg till exempel att du har ett litet projekt som måste passa komponent A i komponent B:
båda komponenterna är standardiserade, så du kan inte bryta dem öppna och ändra hur de fungerar. Du kan bygga en helt ny komponent (PlugTwoProngVariant
) men det är mycket arbete och onödigt dubbelarbete. Ett bättre tillvägagångssätt är att lägga till ett lager mellan de två delarna-en adapter som passar in i båda komponenterna och översätter mellan dem.
nu, om indirection bara handlade om att lägga till ett nytt lager för att passa inkompatibla bitar tillsammans, skulle det vara trevligt men snävt användbart. Men tanken på att lösa problem genom att bygga runt dem är ett koncept som sträcker sig från botten till toppen av datorn. Du ser det när du försöker anpassa en ny datamodell till ett gammalt användargränssnitt. Du ser det när du försöker anpassa ett äldre program till ett nytt webbtjänstgränssnitt. Du ser det när du behöver spänna på funktioner på högre nivå som loggning och caching, eller samordna tjänster på högre nivå som meddelanden och transaktioner. Och högst upp i pyramiden kommer du till sällsynta ämnen som maskininlärning (när du inte kan koda det beteende du behöver, skriv ett annat lager kod som kommer att räkna ut det för dig).
många människor kommer att berätta att kodning handlar om att skriva explicita instruktioner på ett språk som även idiotdatorer kan förstå. Men David wheelers citat avslöjar en bättre insikt. Bra programmering handlar om att klättra på abstraktionsstegen för att komma till de mest allmänna lösningarna.
Bonusrelaterad citat:
Indirection är kraftfull, men det kostar komplexitet. Människor citerar mycket sällan wheelers omedelbara uppföljningsanmärkning om indirection:
“men det kommer vanligtvis att skapa ett annat problem.”- David Wheeler
den sanningen har hållit programmerare i affärer sedan dess.
om enkelhet
“enkelhet är en förutsättning för tillförlitlighet.”- Edsger Dijkstra
det finns ingen brist på kloka programmerare som varnar oss för att inte komplicera vår kod. Men få sätter kostnaden för komplexitet tydligare än den nederländska datavetenskapspionjären Edsger Dijkstra.
här är insikten: du väljer inte enkelhet som en gåva till framtiden. Du gör det inte för att du förutser chansen att återanvända din kod, eller för att du vill att den ska se renare ut vid en kodgranskning eller för att du vill göra det lättare att ändra. (Även om alla dessa fördelar är värdefulla!) Du gör det eftersom enkelhet är en förutsättning. Utan enkelhet kan du aldrig ha tillförlitlig kod som du kan lita på för att driva ett företag eller hantera dina data.
för att acceptera Dijkstras punkt måste vi omdefiniera vad “bra kod” betyder. Det är inte den kortaste koden. Det är inte nödvändigtvis den snabbaste koden. Det är definitivt inte den smartaste koden. Det är kod som man kan lita på.
Bonusrelaterat citat:
ett av de bästa sätten att hålla koden enkel är att komma ihåg att mindre är mer. Dijkstra erbjuder ett mått som hjälper oss att hålla det i åtanke:
“om vi vill räkna kodrader bör vi inte betrakta dem som’ producerade linjer ‘utan som’ förbrukade linjer.'”- Edsger Dijkstra
om läsbarhet och omskrivningar
“det är svårare att läsa koden än att skriva den.”- Joel Spolsky
vid första anblicken verkar detta citat av software legend och StackOverflow medskapare Joel Spolsky sant men bedrägligt Grunt. Ja, koden kan vara tät, kortfattad och tråkigt lång. Och det är inte bara andras kod. Om du tittar på ditt eget arbete från ett år sedan, behöver du förmodligen lite tid att sortera igenom den logik du en gång visste intimt.
men Spolskys insikt kommer med en twist. Risken för kod du inte kan läsa är inte bara det uppenbara (det är svårt att ändra det och förbättra det). Istället är den större faran att komplex kod verkar vara värre än den faktiskt är. Faktum är att bördan att försöka förstå någon annans redan skrivna kod är så stor att du kan bli frestad att göra vad Spolsky kallar det värsta möjliga misstaget—beslutar att skriva om den koden från början.
det är inte så att omskrivningar inte kan förbättra arkitekturen i ett system. De kan definitivt. Men dessa förbättringar kommer till stora kostnader. De återställer klockan vid testning och buggfixning, två aktiviteter som tar mycket längre tid än bara kodning. Omskrivningar är frestande eftersom de spelar på en av de vanligaste fördomarna i mjukvaruutveckling: vi underskattar ansträngningen att göra saker som är konceptuellt enkla. Det är därför de sista 5% av ett projekt tar 50% av tiden. Enkla saker kan vara förvånansvärt tidskrävande! Och ingenting verkar lättare än att lösa ett problem du redan har löst.
så om du inte ska skriva om allt för att göra det perfekt, vad är den bättre lösningen? Svaret är att få varje utvecklare involverad i konstant bite-sized refactoring. Detta ger dig liten, kontinuerlig kodförbättring-verkliga belöningar med minimala risker. Du kan förbättra läsbarheten på vägen.
Bonusrelaterat citat:
om du fortfarande är osäker på vikten av läsbarhet hjälper Martin Fowler att sätta det i perspektiv:
“varje dåre kan skriva kod som en dator kan förstå. Bra programmerare skriver kod som människor kan förstå.”- Martin Fowler
med andra ord är en programmerares jobb inte bara att få saker att fungera, utan att göra saker vettiga.
om upprepning
“upprepa inte dig själv. Varje kunskap måste ha en enda, entydig, auktoritativ representation inom ett system.”- Andy Hunt och Dave Thomas
varje självrespektande programmerare vet att upprepning är hjärtat av mycket ont. Om du skriver samma sak på olika platser gör du extra arbete med att skriva, testa och felsöka. Ännu värre, du introducerar möjligheten till inkonsekvenser — till exempel om en del av koden uppdateras men andra liknande rutiner inte kommer överens. Ett inkonsekvent program är ett program du inte kan lita på, och ett program du inte kan lita på är inte längre en hållbar lösning.
koden är dock inte den enda platsen där repetition orsakar kaos. Denna version av den berömda “upprepa inte dig själv” (torr) regeln utvidgar principen om ingen duplicering för att täcka de andra platserna där inkonsekvenser kan gömma sig. Vi pratar inte längre om koddubblering. Vi pratar också om upprepning i ett system – och ett system har många olika sätt att koda kunskap. De inkluderar:
- kodsatser
- kodkommentarer
- utvecklar-eller klientdokumentation
- datascheman (till exempel databastabeller)
- andra specifikationer, som testplaner, arbetsflödesdokument och byggregler
alla dessa nivåer kan överlappa varandra. Och när de gör det riskerar de att introducera olika versioner av samma verklighet. Till exempel, vad händer om dokumentationen beskriver ett sätt att arbeta men applikationen följer en annan? Vem äger sanningen? Vad händer om databastabellerna inte matchar datamodellen i koden? Eller kommentarerna beskriver driften av en algoritm som inte matchar dess faktiska implementering? Varje system behöver en enda, auktoritativ representation från vilken allt annat härrör.
för övrigt är konkurrerande versioner av sanningen inte bara ett problem i småskaliga projekt eller dåligt utformad kod. Ett av de bästa exemplen bröt ut i allmänheten med striden mellan XHTML och HTML5. Ett läger hävdade att specifikationen var den officiella sanningen, och webbläsare behövde korrigeras för att följa den. Den andra fraktionen hävdade att webbläsarens beteende var de facto-standarden, för det var vad designers hade i åtanke när de skrev webbsidor. I slutändan vann webbläsarversionen av sanningen. Från och med den tiden var HTML5 vad webbläsare gjorde — inklusive genvägarna de tillät och de fel de accepterade.
Bonus relaterad offert:
möjligheten för kod och kommentarer att motsäga varandra har öppnat en het debatt om huruvida kommentarer gör mer skada än nytta. Förespråkarna för extrem programmering behandlar dem med öppen misstanke:
“kod ljuger aldrig; kommentarer gör det ibland.”- Ron Jeffries
på hårda problem
“det finns bara två svåra saker i datavetenskap: cache-ogiltigförklaring och namngivning av saker.”- Phil Karlton
vid första anblicken verkar detta citat som ett underhållande men vanligt programmeringskämt. Kontrasten mellan en något som låter svårt (cache invalidation) och något som låter smärtfritt (namnge saker) är omedelbart relatable. Varje programmerare har investerat timmar av arbete som fixar en löjligt trivial fråga, som ett par parametrar som passerat i fel ordning eller en inkonsekvent aktiverad variabel (tack JavaScript). Så länge människor behöver samarbeta med maskiner för att få saker gjorda, kommer programmering att bli en mashup av systemplanering på hög nivå och triviala skrivfel.
men om du tittar på Phil Karltons citat finns det mer att packa upp. Att namnge saker är inte svårt bara för att en programmerares liv regelbundet förstörs av små huvudvärk. Det beror också på att frågan om namngivning faktiskt är kanten på varje programmerares viktigaste jobb: mjukvarudesign. Med andra ord, Hur skriver du kod som är tydlig, ren och konsekvent?
det finns många sätt att få fel namn. Vi har alla sett variabler uppkallade efter datatyper (myString
, obj
), förkortningar (pc
för produktkatalog), några triviala implementeringsdetaljer (swappable_name
, formUserInput
), eller till och med ingenting alls (ret_value
, tempArray
). Det är lätt att falla i fällan att namnge en variabel baserat på vad du gör med den just nu snarare än vad den innehåller. Och booleska värden är särskilt knepiga-anger progress
när framsteg startar, indikerar att du måste visa framstegsinformation i användargränssnittet eller flagga något helt annat?
men variabla namn är bara början. Namnklasser väcker frågan om hur du delar upp kod i oberoende delar. Namngivning av offentliga medlemmar formar hur du presenterar gränssnittet som gör att en del av din applikation kan interagera med en annan. Att låsa ner dessa namn beskriver inte bara vad en kod kan göra, den bestämmer vad den ska göra.
Bonus relaterad offert:
“det finns två svåra saker i datavetenskap: cache-ogiltigförklaring, namngivning av saker och off-by-one-fel.”- Leon Bambrick