Cum devine software-ul umflat de la telefonie la Bitcoin

Fiecare programator este familiarizat cu bloat. Este peste tot: software pentru întreprinderi care solicită întreprinderii să-și schimbe procesele (alias „de ce cursurile de la Cornell au numere din 4 cifre?”), Software pentru finanțe (de orice fel cu excepția HFT), cadre javascript (cu toate acestea, eforturile de reutilizare a stânga-pad ), backend-uri web (hello there middleware django), RDBMS-uri, sisteme de operare, drivere USB, browsere, plug-in-uri pentru browser, vizualizatoare PDF care sunt de fapt sisteme de publicare a documentelor, aplicații pentru telefon, îl numiți.

Dar echipele de dezvoltatori nu au „panouri de sarcini scrum” cu post-its atașate, pe care scrie „ADD BLOAT”. Celulele dormitoare iraniene nu depun cereri de tragere împotriva proiectelor open source (atunci când serviciile secrete adaugă ușile din spate, așa cum au făcut cu Juniper, par să o facă foarte elegant modificând ușile din spate anterioare - fără balonare!). Deci, cum se umflă software-ul? Cine se află în spatele ei? Ce proces este de vină?

Cine nu este în spatele balonării

umflat

Am găsit vinovatul.

O viziune naivă este că balonarea provine de la dezvoltatori fără idei, care nu prea știu ce fac. Am scris cu toții un cod complicat, mai ales când nu am înțeles destul de bine primitivele care stau la baza lor.

Dar balonarea într-un proiect software important, bine finanțat, semnificativ nu este de obicei rezultatul unei lipsuri de idei. Cred că acest lucru provine din simpla observație că productivitatea software-ului urmează unei distribuții Zipf: o mare parte a codului este de obicei contribuită doar de câțiva programatori competenți, astfel încât cei neclintiți nu au atât de multe oportunități de a face ravagii.

Atunci cine este?

Din experiența mea, software-ul umflă aproape întotdeauna provine de la dezvoltatori inteligenți, adesea cei mai deștepți, care sunt din punct de vedere tehnic cei mai competenți. Cuplați-le abilitățile cu câteva constrângeri interpretate îngust, un efort bine intenționat de a salva ziua (în special, pentru a salva azi în detrimentul zilei de mâine) și voila, avem următoarea poveste.

Povestea structurilor extinse

Poate că cel mai bun exemplu de balonare, care mi-a fost transmis când lucram la o telco mare, implică un comutator de telefon emblematic. Acesta a fost un comutator monstru, capabil să conducă o mare regiune de metrou cu milioane de abonați. Acesta a rulat Unix în centrul său, dar sistemul de operare a fost doar un pic sidehow în comparație cu implementarea monstruoasă a protocolului de semnalizare, zvonindu-se, dacă îmi amintesc bine, că ar avea aproximativ 15 milioane de linii de cod.

Să presupunem că operați pe o bază de cod atât de mare și doriți să adăugați un câmp la o structură. Spuneți, doriți să adăugați un câmp la structura de înregistrare a apelurilor (CDR) pentru a indica dacă persoana apelată se află pe o listă scurtă de prieteni și familie. Lucrul sensibil de făcut ar fi să mergeți la definiția struct și să inserați „uint is_friend_fam: 1;” Asta ar adăuga un pic suplimentar structurii, iar apoi puteți face orice doriți în cod.

Dar când codul este atât de mare și când limita ta de nefuncționare este de 2 ore în 40 de ani, și un tehnician de teren care înlocuia o sursă de alimentare de rezervă în 1987 a apăsat întrerupătorul greșit și a suflat jumătate din bugetul tău de nefuncționare în zona Chicago cu degetele lui grase, nu poți schimba doar dimensiunea structurii. Deoarece acest lucru s-ar putea schimba în cazul în care sunt alocate structurile CDR, cât spațiu suplimentar există în jurul obiectului CDR și ce se întâmplă cu codul care scrie greșit trecutul struct. Acest lucru ar avea consecințe nespuse, imprevizibile, niciuna dintre ele bune.

Așadar, dezvoltatorii de switch-uri au venit cu o idee absolut strălucitoare. Îți dau un moment să te gândești la ce ai face într-o situație similară. Puteți presupune că codul urmează o arhitectură stratificată, tipică codului de rețea.

Ok, vezi dacă soluția ta urmează următoarea soluție strălucitoare:

Calea spre iad este pavată cu bune intenții și trucuri inteligente.

Deci, intrați în definiția struct CDR. Găsiți câmpul care pare a fi cel mai puțin important și cel mai puțin utilizat în general și asigurați-vă că nu este utilizat deloc sub stratul dvs. din stiva de apeluri. Să presupunem că CDR conține ceva numit "uint inap_ain23" care este utilizat doar deasupra stratului dvs. Nu trebuie să aveți nicio idee despre ce este sau ce face inap_ain23. Ceea ce faceți este să salvați valoarea stocată în inap_ain23 când fluxul de control trece prin stratul dvs. Deci, sub stratul dvs., „inap_ain23” nu mai este. Tocmai l-ai „refăcut”. Acum este „is_friend_fam”. S-ar putea să-l aliasă astfel „#define is_friend_fam inap_ain23” pentru a vă ușura lucrurile. Și, în plus, ai niște biți în plus! Primă!