2.0 Introduktion till del 2: Programmering
Del 2 handlar om det dagliga hantverket att skriva programvara som många människor kan läsa, ändra och lita på under ett långt liv. Del 1 lade grunden för hur team organiserar sig och fattar beslut. Den här delen vänder sig till själva koden: de konventioner du följer, hur du formar design och gränssnitt, hur du testar och granskar ditt arbete, hur du hanterar källkodens historik och hur du skriver ner saker. Det är de arbetssätt som skiljer en kodbas som snabbar på leveransen från en som kämpar mot varje ändring.
I ett stort team är hantverk inte en fråga om personlig smak. Det är hur ni samordnar er. När hundratals eller tusentals ingenjörer, konsulter och efterföljare rör vid samma system är det gemensamma konventioner och tydliga kontrakt som låter alla arbeta parallellt utan ständiga krockar. Kom ihåg att kod läses mycket oftare än den skrivs, och att mycket av den läsningen sker år senare, av människor du aldrig kommer att träffa.
I företags- och myndighetsmiljöer höjs insatserna ytterligare. System överlever rutinmässigt sina upphovspersoner med ett decennium eller mer. Reglering och revision kräver dokumenterade belägg för kontroll. Kunskap måste överföras över personalomsättning och avtalsgränser. Kapitlen här behandlar därför kvalitet inte som hjältedåd utan som en konstruerad, till stor del automatiserad egenskap hos hur hela teamet arbetar.
Kapitel i den här delen
2.1 Kodstandarder och kodstil: Gemensamma, automatiskt upprätthållna konventioner för namngivning, formatering och idiom som låter många författare skriva som om en noggrann författare skrivit det, så att granskare lägger sin uppmärksamhet på design snarare än stil.
2.2 Principer för programvarudesign: Tumregler som SOLID (fem objektorienterade designprinciper), DRY (upprepa inte dig själv), koppling och sammanhållning och domändriven design (att modellera programvara på affärsdomänens språk), behandlade som verktyg med ett tillämpningsområde och kända felmönster snarare än lagar att lyda.
2.3 API:er och gränssnittsdesign: Att utforma de kontrakt genom vilka system och team möts, så att oberoende team kan ändra sitt inre utan att bryta konsumenter eller tvinga fram synkroniserade driftsättningar.
2.4 Teststrategi: Medvetna val om vad som ska testas, på vilken nivå och med vilken tillförsikt, för att bygga ett snabbt och pålitligt skyddsnät som låter en stor organisation driftsätta ofta och säkert.
2.5 Kodgranskning och samarbete: Att granska ändringar innan de slås ihop för att fånga defekter, sprida kunskap, upprätthålla standarder och uppfylla regelefterlevnadskontroller, samtidigt som granskningen hålls snabb och konstruktiv snarare än ceremoniell.
2.6 Versionshantering och källkodshantering: Systemet som är register över varje ändring, och den förgrenings-, repositorie- och commit-disciplin som håller huvudgrenen releasbar, historiken läsbar och revisionsspåret intakt.
2.7 Dokumentation: Den skrivna kunskapen, från kom-igång-guider till körböcker (steg-för-steg-driftsprocedurer) och beslutsloggar, som skyddar mot nyckelpersonsrisk, påskyndar introduktion och överför förståelse över år och avtalsgränser.
2.8 Programvarukrav: Att ta fram, specificera, validera och hantera vad programvaran måste göra och hur väl, med den spårbarhet som reglerat och offentligt arbete kräver.
2.9 Programvarukonstruktion: Hantverket att bygga fungerande programvara: att minimera komplexitet, konstruera för verifiering och förändring, defensiv programmering och disciplinerad återanvändning.
2.10 Konfigurationshantering: Att identifiera, kontrollera och granska varje konfigurationsobjekt (varje artefakt vars versioner måste spåras och kontrolleras) och ändring, så att releaser är reproducerbara och revisionsspåret intakt.
2.11 Programvarukvalitet: Kvalitet som en hanterad egenskap bredare än testning: kvalitetsmodeller, säkring mot kontroll, mätning, defekthantering och kostnaden för kvalitet.
2.12 Programvarumodeller och metoder: När och hur man modellerar, med strukturella och beteendemodeller, formella metoder (matematiskt baserad specifikation och verifiering), prototyper och agila metoder, och när modellering är slöseri.
2.13 Grunder i datavetenskap, matematik och teknik: De bestående grunderna under praktiken: algoritmer och datastrukturer, logik och sannolikhet och den empiriska ingenjörsmetoden.
2.14 Projekt och repositoriestruktur: Konsekventa konventioner för att organisera en lösning och dess repositorie, inklusive standardmappar, en README som ingång och gemensam konfiguration, så att vilken ingenjör som helst kan navigera i vilken kodbas som helst.
2.15 Felsökning och problemlösning: Att hitta och åtgärda defekter som en disciplinerad, lärbar praktik av att reproducera, isolera med binärsökning, formulera och testa hypoteser och fånga varje rättelse som ett regressionstest, snarare än gissningar och ändringar med hagelbössa.
2.16 Prestandateknik: Att göra programvara tillräckligt snabb med avsikt genom att sätta prestandabudgetar, mäta och profilera före optimering, förstå algoritmisk kostnad och svanslatens och skydda mot regressioner, allt på kod- och komponentnivå.
2.17 Samtidighet och parallellism: Att skriva korrekt samtidig kod genom att som standard välja oföränderlighet och meddelandeförmedling, förstå kapplöpningstillstånd, baklås och minnessynlighet, välja rätt synkronisering och modeller på högre nivå och testa icke-deterministiskt beteende medvetet.
2.18 Beroende- och leveranskedjehantering: Att hantera den tredjepartskod som utgör det mesta av ett modernt system genom versionsdisciplin och låsfiler, en jämn uppdateringstakt, ett minimalt och granskat beroendeavtryck samt ursprung och en programvarumaterialförteckning för en pålitlig leveranskedja.
2.19 Omstrukturering och teknisk skuld: Att förbättra den inre designen hos fungerande kod bakom en pålitlig testsvit, känna igen kodlukter och tillämpa små namngivna omstruktureringar, använda kvävarfikonet för större förändringar och hantera teknisk skuld som en synlig, finansierad portfölj snarare än ett moraliskt fel.
2.20 Felhantering och motståndskraftsmönster: Att medvetet besluta hur kod fallerar och återhämtar sig, genom tydliga felkontrakt, val mellan att falla snabbt och att falla säkert, omförsök med fördröjning och idempotens, kretsbrytare och graciös nedgradering, och att aldrig i tysthet svälja ett fel.
2.21 Typsystem och statisk analys: Att fånga hela klasser av defekter innan koden körs, genom statisk och gradvis typning som gör otillåtna tillstånd orepresenterbara, samt linters, typkontrollanter och analysverktyg inkopplade i editorn och pipelinen.
Hur kapitlen hänger ihop
Den röda tråden i del 2 är förändringsbarhet i stor skala. Varje praxis här finns för att låta många människor ändra ett delat, långlivat system med tillförsikt. Kodstandarder (2.1) och designprinciper (2.2) formar koden så att du kan förstå och ändra den. Gränssnittsdesign (2.3) drar de gränser som låter team ändra sitt inre oberoende. Testning (2.4) ger skyddsnätet som gör förändring säker. Kodgranskning (2.5) är där individuellt arbete möter kollektivt ägarskap, och där standarder faktiskt upprätthålls. Versionshantering (2.6) är grunden som granskning, integration och revision alla vilar på. Och dokumentation (2.7) bevarar avsikten bakom allt detta för dem som kommer senare.
Kapitlen matar också resten av guideboken. Gränssnitten och designprinciperna här blir byggstenar i systemen i del 3, särskilt arkitekturens grunder (kapitel 3.1). Teststrategi (2.4) och versionshantering (2.6) är råmaterialet för de automatiserade leveranspipelines i kapitel 8.1. Dokumentationspraxis (2.7) hänger direkt ihop med körböckerna och observerbarheten i driften, till exempel kapitel 9.2. Och hela delen bygger på värderingarna och beslutsgrunderna från del 1 och förvandlar gemensamma principer till konkret dagligt hantverk.