5 Citate celebre de programare, explicate
a fi programator înseamnă a te înscrie pentru o viață de învățare constantă. Fântâna de noi-noi caracteristici, noi limbi, noi instrumente, noi cadre—nu se oprește niciodată țâșnește. Dar informatica este, de asemenea, un domeniu surprinzător de tradițional, care se bazează pe principii testate în timp. Am adăugat programare orientată pe obiecte, hardware modern și inteligență artificială. Dar, în ciuda acestor schimbări, multe dintre ideile care au fost articulate pentru prima dată cu o generație în urmă sunt valabile și astăzi.
în acest articol, am disecat câteva dintre citatele mele preferate despre informatică. Singura condiție pe care am stabilit-o este ca fiecare Citat să aibă cel puțin douăzeci de ani. Pentru că, în timp ce tehnologia veche devine rapid inutilă, poruncile antice ale strămoșilor noștri de programare au mult mai multă putere de ședere.
“toate problemele din Informatică pot fi rezolvate printr-un alt nivel de indirecție.”- David Wheeler
Iată un citat compsci adesea repetat pe care puțini dezvoltatori vor să-l explice. Dar este unul dintre adevărurile mele preferate de programare, pentru că lovește în centrul a ceea ce înseamnă codificarea.
cel mai simplu mod de a începe să te gândești la indirecție este să-ți imaginezi straturi. De exemplu, să presupunem că aveți un proiect mic care trebuie să încadreze componenta A în componenta B:
ambele componente sunt standardizate, deci nu le puteți deschide și schimba modul în care funcționează. Ai putea construi o componentă cu totul nouă (PlugTwoProngVariant
), dar asta e o mulțime de muncă și duplicarea inutile. O abordare mai bună este să adăugați un strat între cele două piese — un adaptor care se potrivește în ambele componente și se traduce între ele.
acum, dacă indirection a fost doar despre adăugarea unui nou strat pentru a se potrivi piese incompatibile împreună, ar fi frumos, dar restrictiv util. Dar ideea de a rezolva problemele construind în jurul lor este un concept care se întinde de jos în sus de calcul. O vedeți când încercați să potriviți un nou model de date cu o interfață de utilizator veche. Îl vedeți atunci când încercați să potriviți o aplicație veche într-un nou backend de servicii web. Îl vedeți atunci când trebuie să vă conectați la funcții de nivel superior, cum ar fi înregistrarea în jurnal și memorarea în cache sau să coordonați servicii de nivel superior, cum ar fi mesageria și tranzacțiile. Și în partea de sus a piramidei, veți ajunge la subiecte rarefiate, cum ar fi învățarea automată (când nu puteți codifica comportamentul de care aveți nevoie, scrieți un alt strat de cod care vă va da seama).
o mulțime de oameni vă vor spune că codificarea înseamnă să scrieți instrucțiuni explicite într-un limbaj pe care chiar și computerele idioate îl pot înțelege. Dar citatul lui David Wheeler dezvăluie o perspectivă mai bună. O programare bună se referă la urcarea scării abstractizării pentru a ajunge la cele mai generale soluții.
Bonus citat legate:
Indirection este puternic, dar există un cost pentru complexitate. Oamenii foarte rar citează remarca imediată de urmărire a lui Wheeler despre indirectare:
“dar asta de obicei va crea o altă problemă.”- David Wheeler
acest adevăr a ținut programatorii în afaceri de atunci.
despre simplitate
“simplitatea este o condiție prealabilă pentru fiabilitate.”- Edsger Dijkstra
nu există lipsă de programatori înțelepți care să ne avertizeze să nu ne complicăm prea mult Codul. Dar puțini pun costul complexității mai clar decât pionierul olandez al informaticii Edsger Dijkstra.
iată înțelegerea: nu alegeți simplitatea ca dar pentru viitor. Nu o faceți pentru că anticipați șansa de a vă reutiliza codul sau pentru că doriți să pară mai curat la o revizuire a codului sau pentru că doriți să o modificați mai ușor. (Deși toate aceste beneficii sunt valoroase!) O faci pentru că simplitatea este o condiție prealabilă. Fără simplitate, nu puteți avea niciodată un cod de încredere în care să aveți încredere pentru a conduce o afacere sau pentru a vă gestiona datele.
pentru a accepta punctul lui Dijkstra, trebuie să redefinim ce înseamnă “cod bun”. Nu e cel mai scurt cod. Nu este neapărat cel mai rapid Cod. Cu siguranță nu este cel mai inteligent cod. Este un cod care poate fi de încredere.
Bonus citat legate:
una dintre cele mai bune moduri de a păstra codul simplu este să ne amintim că mai puțin este mai mult. Dijkstra oferă o valoare care să ne ajute să ținem cont de asta:
“dacă vrem să numărăm linii de cod, nu ar trebui să le considerăm linii produse, ci linii cheltuite.'”- Edsger Dijkstra
despre lizibilitate și rescriere
“este mai greu să citești codul decât să-l scrii.”- Joel Spolsky
la prima vedere, acest citat al legendei software și al co-creatorului Stackoverflow Joel Spolsky pare adevărat, dar înșelător de superficial. Da, codul poate fi dens, concis și obositor de lung. Și nu este doar codul altor persoane. Dacă vă uitați la propria lucrare de acum un an, probabil că veți avea nevoie de ceva timp pentru a sorta logica pe care ați cunoscut-o odată intim.
dar intuiția lui Spolsky vine cu o întorsătură. Pericolul codului pe care nu îl puteți citi nu este doar evident (este greu să îl schimbați și să îl îmbunătățiți). În schimb, pericolul mai mare este că codul complex pare să fie mai rău decât este de fapt. De fapt, sarcina de a încerca să înțelegi codul deja scris al altcuiva este atât de mare încât ai putea fi tentat să faci ceea ce Spolsky numește cea mai gravă greșeală posibilă—decizia de a rescrie codul de la zero.
nu este faptul că rescrierile nu pot îmbunătăți arhitectura unui sistem. Cu siguranță pot. Dar aceste îmbunătățiri vin cu mari cheltuieli. Ei resetează ceasul la testare și remedierea erorilor, două activități care durează mult mai mult decât simpla codificare. Rescrierile sunt tentante, deoarece se joacă pe una dintre cele mai frecvente prejudecăți în dezvoltarea de software: subestimăm efortul de a face lucruri care sunt conceptual simple. Acesta este motivul pentru care ultimul 5% al unui proiect durează 50% din timp. Lucrurile ușoare pot fi surprinzător de consumatoare de timp! Și nimic nu pare mai ușor decât rezolvarea unei probleme pe care ați rezolvat-o deja.
deci, dacă nu ar trebui să rescrieți totul pentru a-l face perfect, care este soluția mai bună? Răspunsul este de a atrage fiecare dezvoltator implicat în refactorizarea constantă a dimensiunilor mușcăturii. Acest lucru vă oferă o îmbunătățire continuă a codului – recompense reale cu riscuri minime. Puteți îmbunătăți lizibilitatea pe drum.
Bonus citat legate:
dacă sunteți încă în dubiu cu privire la importanța lizibilitate, Martin Fowler ajută să-l pună în perspectivă:
“orice prost poate scrie cod pe care un computer îl poate înțelege. Programatorii buni scriu cod pe care oamenii îl pot înțelege.”- Martin Fowler
cu alte cuvinte, treaba unui programator nu este doar să facă lucrurile să funcționeze, ci să facă lucrurile să aibă sens.
despre repetiție
“nu te repeta. Fiecare bucată de cunoaștere trebuie să aibă o reprezentare unică, lipsită de ambiguitate, autoritară în cadrul unui sistem.”- Andy Hunt și Dave Thomas
fiecare programator care se respectă știe că repetarea este inima multor rele. Dacă scrieți același lucru în locuri diferite, faceți lucrări suplimentare de scriere, testare și depanare. Și mai rău, introduceți posibilitatea unor inconsecvențe — de exemplu, dacă o parte a codului este actualizată, dar alte rutine similare nu sunt aduse în acord. Un program inconsistent este un program în care nu poți avea încredere, iar un program în care nu poți avea încredere nu mai este o soluție viabilă.
cu toate acestea, codul nu este singurul loc în care repetarea face ravagii. Această versiune a celebrei reguli “nu te repeta” (uscată) extinde principiul fără duplicare pentru a acoperi celelalte locuri în care se pot ascunde inconsecvențele. Nu mai vorbim despre duplicarea codului. Vorbim, de asemenea, despre repetiție într — un sistem-și un sistem are multe moduri diferite de a codifica cunoștințele. Acestea includ:
- instrucțiuni de cod
- Comentarii Cod
- documentație pentru dezvoltatori sau clienți
- scheme de date (de exemplu, tabele de baze de date)
- alte specificații, cum ar fi planurile de testare, documentele fluxului de lucru și regulile de construire
toate aceste niveluri se pot suprapune între ele. Și când o fac, riscă să introducă versiuni diferite ale aceleiași realități. De exemplu, ce se întâmplă dacă documentația descrie un mod de lucru, dar aplicația urmează altul? Cine deține adevărul? Ce se întâmplă dacă tabelele bazei de date nu se potrivesc cu modelul de date din cod? Sau comentariile descriu funcționarea unui algoritm care nu se potrivește cu implementarea sa reală? Fiecare sistem are nevoie de o reprezentare unică, autoritară, din care derivă orice altceva.
de altfel, versiuni concurente ale adevărului nu este doar o problemă în proiecte la scară mică sau cod prost concepute. Unul dintre cele mai bune exemple a izbucnit în public odată cu bătălia dintre XHTML și HTML5. O tabără a susținut că specificația era adevărul oficial, iar browserele trebuiau corectate pentru a o urma. Cealaltă fracțiune a susținut că comportamentul browserului a fost standardul de facto, deoarece asta au avut în vedere designerii atunci când au scris pagini web. În cele din urmă, versiunea de browser a adevărului a câștigat. Din acel moment, HTML5 a fost ceea ce au făcut browserele — inclusiv comenzile rapide pe care le-au permis și erorile pe care le-au acceptat.
cotație aferentă bonusului:
posibilitatea ca codurile și comentariile să se contrazică reciproc a deschis o dezbatere aprinsă cu privire la faptul dacă comentariile fac mai mult rău decât bine. Susținătorii programării Extreme îi tratează cu suspiciune deschisă:
“codul nu minte niciodată; comentariile fac uneori.”- Ron Jeffries
pe probleme grele
“există doar două lucruri grele în informatică: invalidarea cache – ului și denumirea lucrurilor.”- Phil Karlton
la prima vedere, acest citat pare o glumă amuzantă, dar obișnuită de programare. Contrastul dintre un lucru care sună dificil (invalidarea cache-ului) și ceva care sună nedureros (denumirea lucrurilor) este instantaneu relatabil. Fiecare programator a investit ore de lucru rezolvând o problemă ridicol de banală, cum ar fi o pereche de parametri trecuți în ordine greșită sau o variabilă cu majuscule inconsecvente (mulțumesc JavaScript). Atâta timp cât oamenii trebuie să se asocieze cu mașinile pentru a face lucrurile, programarea va fi un mashup de planificare a sistemului la nivel înalt și greșeli banale.
dar dacă aruncați o a doua privire la citatul lui Phil Karlton, mai sunt multe de despachetat. Numirea lucrurilor nu este greu doar pentru că viața unui programator este ruinată în mod regulat de mici dureri de cap. Este, de asemenea, pentru că problema numirii este de fapt marginea celei mai importante sarcini a fiecărui programator: proiectarea software-ului. Cu alte cuvinte, cum scrieți un cod clar, curat și consecvent?
există o mulțime de modalități de a obține denumirea greșită. Cu toții am văzut variabile numite după tipuri de date(myString
, obj
), abrevieri (pc
pentru catalogul de produse) , câteva detalii banale de implementare(swappable_name
, formUserInput
), sau chiar nimic deloc (ret_value
, tempArray
). Este ușor să cazi în capcana numirii unei variabile pe baza a ceea ce faci cu ea în acel moment, mai degrabă decât a ceea ce conține. Și valorile booleene sunt deosebit de dificile — progress
stabilește când începe progresul, indică faptul că trebuie să afișați informații despre progres în interfața de utilizare sau să semnalizați ceva complet diferit?
dar numele variabilelor sunt doar începutul. Numirea claselor ridică problema modului în care împărțiți codul în părți independente. Denumirea membrilor publici modelează modul în care prezentați interfața care permite unei părți a aplicației dvs. să interacționeze cu alta. Blocarea acestor nume nu descrie doar ce poate face o bucată de cod, ci determină ce va face.
cotație aferentă bonusului:
“există două lucruri grele în informatică: invalidarea cache-ului, denumirea lucrurilor și erorile off-by-one.”- Leon Bambrick