Reguli pentru o bună programare. Criterii pentru un cod bun în programare

05.03.2020 Photoshop 3D

În ultimul timp am văzut puțin cod foarte bun, mult mediocru și Foarte multe lucruri rele. (O mare parte din ceea ce am scris înainte – mai ales când eram la început – se aplică celor din urmă, vai.) Citind articole aleatorii de pe Internet și cărți profesionale, am ajuns la concluzia că a scrie cod bun este ușor. Incredibil de dificil, dar în același timp ușor. De fapt, este atât de simplu încât se rezumă la trei reguli.

  1. Scrieți cod pentru oameni, nu pentru mașini.
  2. Fiecare bucată de cod ar trebui să îndeplinească o sarcină.
Urmându-le în mod constant, vei scrie un cod bun. În orice limbaj de programare și în orice paradigmă. Problema este că este foarte greu. Toate necesită disciplină, iar ultimele două în majoritatea cazurilor necesită și o reflecție lungă.
Scrieți cod pentru oameni, nu pentru mașini.
Aceasta este cea mai importantă dintre cele trei reguli și stă la baza celorlalte două. Scrieți cod ușor de citit pentru oameni; Lăsați munca grea pe seama computerului. Utilizați nume semnificative de variabile și metode. Nu creați lanțuri logice complicate unde pot fi folosite cele simple. Nu încercați să vă potriviți cât mai mult posibil pe o singură linie. Mențineți un stil de codare consecvent care include indentări semnificative. Dacă fișierele dvs. sunt atât de voluminoase încât devin dificil de parcurs, împărțiți-le în câteva mai mici.

Mulți programatori încearcă să scrie ceva care, în opinia lor, funcționează mai repede, reduce dimensiunea aplicației - într-un cuvânt, „facilitează” munca computerului. Este grozav, dar nu uitați că este mai important să scrieți cod ușor de citit și de întreținut pentru alți oameni.

Compilatorul (sau interpretul) poate gestiona stiluri complet diferite de cod. Pentru el nŞi numberOfObjects- este acelasi lucru. Pentru oameni - nu. Citirea codului va dura mult timp, chiar dacă scopul variabilei vi se pare evident.

Imaginează-ți că ai făcut un mic scenariu pentru tine și, după câțiva ani, a trebuit să-l schimbi puțin. Ce ați vedea mai degrabă: un script bine structurat, cu comentarii și un nume clar, sau o funcție fără un singur comentariu și cu variabile al căror scop este aproape imposibil de înțeles?

Dacă faci ceva care nu este evident pentru a optimiza o bucată de cod, descrie într-un comentariu ce face exact. Dar nu uitați că în majoritatea cazurilor nu veți putea optimiza programul mai bine decât compilatorul. Realitatea este că el este mai inteligent decât tine. Este un fapt: compilatorii s-au îmbunătățit de-a lungul deceniilor de muncă grea de către profesioniști. Există excepții, dar ele doar confirmă regula.

Scrieți un cod pe care oamenii îl pot înțelege.

Nu te repeta
Nu pot număra de câte ori am văzut aceeași bucată de cod în diferite părți ale unui program. Chiar azi lucram la o funcție mare în codul moștenit și am văzut aceleași condiții în două părți diferite ale expresiei condiționate. A trebuit să petrec timp asigurându-mă că este doar o eroare a programatorului.

Când repeți același fragment în mai multe locuri, mai devreme sau mai târziu va trebui să te întorci la el pentru a corecta o eroare sau pentru a adăuga ceva nou. Acest lucru face codul dificil de întreținut. În loc să vă repetați, puneți fragmentul într-o clasă sau funcție separată la care puteți apela de îndată ce aveți nevoie. Dacă apelați mai multe metode în locuri diferite în aceeași ordine, includeți-o într-o funcție separată.

Gândiți-vă la ce va fi mai ușor de înțeles când vă uitați la cod: un fragment de 30 de linii care eliberează un bloc de memorie sau un apel de funcție clearMapVariableMemory()?
Poate fi necesar să studiați fragmentul mai târziu, dar chiar și atunci, lucrul cu o funcție separată va fi mai ușor.

Același principiu poate fi aplicat datelor. Dacă utilizați frecvent aceleași variabile, mutați-le într-o clasă sau tip de date separat.

Dacă urmați această regulă, toate modificările vor fi universale - nu va trebui să reluați zeci de locuri pentru a face o mică modificare.

Nu te repeta.

Fiecare bucată de cod ar trebui să îndeplinească o sarcină
Ultima regulă se bazează pe cele două anterioare: fiecare parte din codul tău ar trebui să facă doar un singur lucru. Este adevărat la toate nivelurile: pentru expresii, funcții și metode, clase și obiecte.

Acum câțiva ani, un dezvoltator mi-a arătat o bucată de cod care nu funcționa. I-a luat programatorului câteva ore să-și dea seama. În cele din urmă, problema a fost descoperită în operatorii C post-incrementali (în cazuri speciale, comportamentul acestora variază de la compilator la compilator). Ulterior, în timp ce citeam o carte despre dezvoltare, am observat că adevărata problemă nu au fost afirmațiile, ci faptul că un fragment era responsabil pentru îndeplinirea multor sarcini diferite.

Din câte îmi amintesc, linia care conține eroarea făcea parte dintr-o operație ternară. Acesta, la rândul său, a efectuat mai multe operații pe pointeri pentru a calcula condiția și mai multe, în funcție de rezultatul expresiei condiționate. Acesta a fost un bun exemplu de scriere a codului în primul rând pentru o mașină, mai degrabă decât pentru un om: nimeni altul decât autorul fragmentului nu ar înțelege exact ce face o linie, chiar și după ce a citit-o de mai multe ori. Dacă programatorul care a scris codul ar fi spart logica în mai multe părți, ar fi luat mult mai puțin timp pentru a rezolva problema.

Nu ar trebui să recuperați, să procesați și să modificați datele în aceeași metodă. Descrierea verbală a fiecărei funcții ar trebui să fie cuprinsă într-o singură propoziție. Scopul fiecărei linii ar trebui să fie clar. Acest lucru face codul ușor de înțeles pentru oameni. Niciunul dintre noi nu poate stoca în capul nostru o funcție lungă de câteva mii de linii. Nu există niciun motiv convingător pentru a crea astfel de funcții în loc de câteva metode mici utilizate împreună.

Trebuie remarcat că acest lucru nu este atât de dificil: pentru a finaliza o sarcină mare, trebuie doar să o descompuneți în mai multe altele mai mici, fiecare având o funcție separată. Este important să vă asigurați că scopul fiecărei funcții rămâne clar, altfel codul devine prea confuz.

Fiecare parte din codul tău ar trebui să facă un singur lucru.

Concluzie
Scrierea unui cod bun este o muncă grea. Programez de patru ani – nu atât de mult, dar suficient cât să văd destul de multe probleme, inclusiv ale mele. Mi-a devenit clar că complicăm dezvoltarea nerespectând aceste reguli simple. Este dificil să le urmărești corect: nu este întotdeauna evident unde este nevoie de o clasă sau o metodă separată. Este o abilitate. Este nevoie de mult timp pentru a deveni un programator bun. Dar dacă nu respectăm aceste reguli, scrierea și întreținerea codului va deveni și mai dificilă.

Traducerea articolului

Deci acum aveți o problemă dacă scrieți o bibliotecă care va fi folosită atât de codul vechi scris cu wchar_t definit ca un alias pentru codul scurt nesemnat, cât și pentru codul new-school scris cu wchar_t ca tip intern separat. Ce tip de date trebuie să utilizați pentru parametrii șir?

Aceasta este o traducere a specificatorilor de format în stilul printf din istoria tristă Unicode în Visual C++.

Windows a implementat Unicode mai devreme decât majoritatea celorlalte sisteme de operare. Ca urmare, soluțiile Windows la multe probleme diferă de cele făcute de cei care au așteptat până când praful s-a așezat¹. Cel mai proeminent exemplu în acest sens este utilizarea de către Windows a UCS-2 ca codificare Unicode. Atunci a fost codarea recomandată de Unicode Consortium, deoarece Unicode 1.0 accepta doar 65"536 de caractere². Unicode Consortium s-a răzgândit cinci ani mai târziu, dar până atunci era prea târziu pentru Windows, care lansase deja Win32s, Windows NT 3.1, Windows NT 3.5 , Windows NT 3.51 și Windows 95 - toate au folosit UCS-2³.

Dar astăzi vom vorbi despre șirurile de format în stil printf.

Aceasta este traducerea lui Dacă FlushInstructionCache nu face nimic, de ce trebuie să-l numiți, revizuit.

Este de așteptat să apelați funcția FlushInstructionCache atunci când generați sau modificați codul executabil în timpul execuției - astfel încât procesorul, atunci când execută codul dvs. generat/modificat, să citească instrucțiunile pe care le-ați scris, mai degrabă decât instrucțiunile vechi care pot rămâne în instrucțiunile procesorului cache.

Anterior am aflat că. Acest lucru se datorează faptului că un simplu apel de funcție a fost suficient pentru a șterge memoria cache a comenzilor.

Dar în Windows NT, funcția FlushInstructionCache face treaba reală, deoarece trebuie să notifice toți ceilalți procesoare pentru a-și goli memoria cache.

Cu toate acestea, dacă te uiți la Windows 10, vei descoperi că funcția FlushInstructionCache arată ca versiunea Windows 95: ea nu face nimic.

Ce s-a întâmplat?

Majoritatea articolelor scrise pe tema angajării programatorilor sună mai mult sau mai puțin la fel. De obicei, astfel de articole recomandă „angajarea numai a celor mai buni”. Recunosc, nu sunt încântat de acest sfat pentru că sună prea vag. Este la fel ca și cum ai veni la un dealer auto și ai întreba vânzătorul ce mașină ți-ar recomanda, iar el ți-ar răspunde că „Cel mai bun” nu este indicat pentru nimeni din dealer.

Vă rog să nu mă înțelegeți greșit, nu vă sfătuiesc să căutați în mod deliberat programatori mediocri. Desigur, toată lumea vrea să angajeze doar cei mai talentați și experimentați programatori. Deciziile de angajare au mize mari. Decizia ta va afecta munca întregii echipe și a membrilor ei individuali. După cum se spune:

„A respinge un candidat bun este mult mai bine decât a-l accepta pe unul rău... Dacă ai chiar și cea mai mică îndoială, nu te angajezi”

Dar sfaturile standard încă mă enervează. Nu este vorba atât de sfatul în sine, cât de faptul că oamenii tind să-l înțeleagă greșit. Dacă este aplicată fără alte ajustări, această practică creează în principal un sentiment de auto-superioritate. Acest efect este deosebit de comun în rândul programatorilor, deoarece elitismul este cumva inerent în noi. Când auzim că ar trebui să angajăm doar „cei mai buni”, acest sfat suferă o transformare subconștientă:

„Cel mai bun?” Dar eu sunt! Eu sunt "cel mai bun". Desigur, trebuie să angajez oameni la fel de talentați, deștepți și arătoși ca mine. Și de ce să împrăștie echipa mea minunată cu tot felul de oameni?

Cine sunt cei mai buni programatori?

Desigur, această abordare nu creează cele mai bune condiții pentru luarea deciziilor. Regula standard funcționează mult mai bine dacă o înțelegem puțin diferit:

„Vreau să formez cea mai eficientă echipă posibilă. Angajând un angajat suplimentar, mă străduiesc nu numai să măresc numărul de personal. Fiecare persoană angajată trebuie să-mi îmbunătățească echipa într-un fel. Nu caut deloc o persoană la fel de talentată ca mine. Mai degrabă, am nevoie de cineva care este mai talentat decât mine în cel puțin un domeniu important.”

Șeful

Cel mai rău șef este cel care se simte amenințat de echipa sa. Conștient sau nu, se teme de „cel mai bun” și, prin urmare, angajează constant oameni împotriva cărora va arăta avantajos.

Probabil că te poți descurca într-o companie mare cu această abordare. Bănuiesc cu tărie că Shaggy Boss din benzile desenate Dilbert se bazează pe viață.

Dar în lumea firmelor mici de dezvoltare, lucrurile stau complet diferit. Dacă sunteți fondatorul sau „guru șef” al unei companii mici, încercați să vă priviți cu atenție, onest și obiectiv. Dacă sunteți unul dintre cei care se simt amenințați de propriii angajați, opriți-vă și gândiți-vă. Până nu reușești să rezolvi această problemă, șansele de a construi o echipă eficientă vor fi zero.

Personal de programatori

Adevăratul scop al regulii standard este să nu ne mângâiem egoul - este să ne reamintim să nu ne fie frică să căutăm cei mai buni angajați. Totuși, este necesar să clarificăm mai precis ce înseamnă de fapt cuvântul „cel mai bun”.

Căutați oameni care sunt conștienți de sine

„Cei mai buni” angajați nu încetează niciodată să învețe.

Consider că unul dintre cele mai importante criterii atunci când evaluez candidații este ceea ce eu personal numesc „prima derivată”. Această persoană studiază? El înaintează sau stă nemișcat? (Unele dintre gândurile mele despre acest subiect sunt publicate în articolul „Calcul carierei” de pe blogul meu).

Oamenii care sunt serioși cu privire la succesul lor viitor au mai multe șanse să reușească. Această mentalitate este adesea cel mai puternic atribut pentru deciziile de angajare.

Asta nu înseamnă că ar trebui să angajezi doar oameni care vor să reușească. Toți oamenii vor să reușească. Sfatul meu este să angajezi oameni serioși în ceea ce privește învățarea continuă. Acești oameni nu pierd timpul încercând să te convingă cât de multe știu. Ei se concentrează mai degrabă pe trecut decât pe viitor. În timp ce îi intervievezi, ei te intervievează, încercând să afle ce pot învăța de la tine.

Cum să găsești o astfel de persoană?

Un semn clar este că oamenii care se angajează în învățarea continuă știu bine ceea ce nu știu. Își cunosc slăbiciunile și nu le este frică să vorbească despre ele.

În interviuri, candidații sunt adesea rugați să-și descrie principalele puncte slabe. Deși această întrebare este îngrozitor de tradițională, îmi place.

Din păcate, mulți candidați încearcă să evite să răspundă la întrebare. Ei merg la o librărie și cumpără o carte despre interviuri. Cartea mă avertizează că le voi pune această întrebare și sugerează modalități „creative” de a evita să răspund sincer:

  • Uneori muncesc prea mult.
  • Uneori, atenția mea la detalii îi irită pe alți membri ai grupului.

Când îi cer unui candidat să-și împărtășească punctele slabe, mă aștept la un răspuns inteligent, sincer și încrezător. Când aud un candidat recunoscând o slăbiciune, face impresie. Dar dacă un candidat dă un răspuns evaziv direct din carte, încep să mă gândesc la următorul candidat.

Angajați dezvoltatori, nu programatori

Într-o companie mică, cei „mai buni” programatori sunt cei care fac mai mult decât doar programare. Încercați să angajați dezvoltatori, nu programatori. Deși aceste cuvinte sunt adesea folosite interschimbabil, le diferențiez. Este vorba despre diferența dintre doar programare și a face parte dintr-o echipă care lucrează la un produs. Permiteți-mi să citez dintr-un articol pe care l-am scris pe acest subiect pe blogul meu:

„În acest articol, un „programator” este cineva care este implicat exclusiv în codarea de noi funcții și [dacă aveți noroc] remedierea erorilor. Programatorii nu scriu specificații. Nu creează cazuri de testare automatizate. Ele nu ajută la menținerea la zi a sistemelor de construcție automatizate. Nu ajută clienții să rezolve probleme tehnice. Nu ajută la scrierea documentației, nu participă la testare și nici măcar nu citesc codul. Tot ce fac ei este să scrie cod nou. O companie mică nu ar trebui să păstreze astfel de oameni.

În loc de „programatori” (oameni specializați în scrierea codului), aveți nevoie de „dezvoltatori” (oameni care contribuie în multe feluri la succesul produsului).”

Ce înseamnă regula standard? Care este exact atributul care trebuie măsurat pentru a determina dacă un candidat este „cel mai bun”?

Această regulă este de obicei înțeleasă că se aplică numai abilităților de codificare. Dar programatorii cu adevărat buni sunt inteligenți. Ei înțeleg lucruri care nu sunt de obicei predate și pot funcționa de 10 ori mai eficient decât un programator mediu. Desigur, ar fi înțelept să cauți una dintre aceste personalități „de zece ori”, mai ales în organizațiile mari unde specialiști precum programatorii „puri” sunt destul de potriviți. Dar o companie mică are nevoie de versatilitate. Adesea, membrilor echipei li se cere să îndeplinească mai multe funcții dincolo de simpla scriere a codului. În astfel de cazuri, este foarte important să găsiți cel mai bun dezvoltator, iar această persoană nu va fi neapărat cel mai bun programator.

Deci, regula standard funcționează destul de bine, dar de la recomandările generale este necesar să trecem la altele mai specifice. Pentru a rezuma ceea ce s-a discutat în secțiunile anterioare, iată 10 întrebări pe care trebuie să le puneți atunci când vă gândiți la un candidat pentru o poziție de dezvoltator:

  1. Poate acest candidat să facă ceva pentru grup pe care nimeni altcineva nu poate?
  2. Este într-un proces constant de învățare?
  3. Este acest candidat conștient de slăbiciunile sale și le poate discuta cu calm?
  4. Cât de versatil este acest candidat și de capabil să facă „tot ce este nevoie” pentru ca produsul să devină un succes comercial?
  5. Este candidatul unul dintre programatorii de 10x?
  6. Are o diplomă de licență de la o universitate de renume?
  7. Dacă candidatul are un doctorat, există alte indicii că are capacitatea de a dezvolta produse comerciale?
  8. Candidatul are experiență de lucru în echipe care au dezvoltat produse comerciale?
  9. Poate candidatul să ofere exemple de cod bun?
  10. Candidatul iubește programarea suficient pentru a scrie cod în timpul liber?

Nu este necesar un răspuns pozitiv la toate cele 10 întrebări. Nici măcar nu voi specifica numărul maxim de răspunsuri pozitive necesare pentru a accepta un candidat. Angajarea este o loterie și fiecare întrebare poate servi drept ghid pentru evaluarea adecvării unui candidat.

În cele din urmă, orice decizie de angajare este o decizie discreționară și nu se pot face garanții. Cu toate acestea, acordând atenție acestor probleme, este mai probabil să nu regretați decizia dvs. mai târziu.

15 Reguli pentru scrierea codului de calitate

Există nenumărate moduri de a scrie cod rău. Din fericire, pentru a ajunge la nivelul codului de calitate, trebuie doar să urmați 15 reguli. Urmărirea lor nu te va face un maestru, dar îți va permite să-l imiti în mod convingător.

Regula 1: Urmați standardele de codare.

Fiecare limbaj de programare are propriul standard de formatare a codului, care dictează cum să indentați, unde să puneți spații și paranteze, cum să denumiți obiectele, cum să comentați codul etc.

De exemplu, în această bucată de cod există 12 erori conform standardului:

Pentru(i=0;i

Studiați standardul cu atenție, învățați elementele de bază pe de rost, urmați regulile precum poruncile și programele dvs. vor fi mai bune decât cele mai multe scrise de absolvenți de facultate.

Multe organizații își adaptează standardele pentru a se potrivi nevoilor lor specifice. De exemplu, Google a dezvoltat standarde pentru mai mult de 12 limbaje de programare. Sunt bine gândite, așa că verificați-le dacă aveți nevoie de ajutor pentru programare cu Google. Standardele includ chiar setări ale editorului pentru a vă ajuta să respectați stilul și instrumente speciale pentru a verifica dacă codul dvs. este conform cu acel stil. Folosește-le.

Regula 2: Dați nume descriptive.

Limitați de mașini de teletip lente și greoaie, programatorii din antichitate foloseau contracte pentru nume de variabile și proceduri pentru a economisi timp, apăsări de taste, cerneală și hârtie. Această cultură este prezentă în unele comunități de dragul menținerii compatibilității cu versiunile inverse. Luați, de exemplu, funcția C wcscspn, care rupe limbajul (interval de completare a șirurilor de caractere). Dar această abordare nu este aplicabilă în codul modern.

Utilizați nume lungi și descriptive, cum ar fi complementSpanLength, pentru a vă ajuta pe dvs. și colegii să înțelegeți codul în viitor. Excepțiile sunt câteva variabile importante utilizate în corpul unei metode, cum ar fi iteratoarele de buclă, parametrii, valorile temporare sau rezultatele execuției.

Este mult mai important să te gândești mult înainte de a numi ceva. Numele este corect? Ați vrut să spuneți cel mai mare preț sau cel mai bun preț? Este numele suficient de specific pentru a evita utilizarea lui în alte contexte pentru obiecte similare? Nu ar fi mai bine să apelați metoda getBestPrice în loc de getBest? Se potrivește mai bine decât alte nume similare? Dacă aveți o metodă ReadEventLog, nu ar trebui să apelați un alt NetErrorLogRead. Dacă denumești o funcție, numele descrie valoarea returnată?

În sfârșit, câteva reguli simple de denumire. Numele de clase și de tip trebuie să fie substantive. Numele metodei trebuie să conțină un verb. Dacă o metodă determină dacă unele informații despre un obiect sunt adevărate sau false, numele acesteia trebuie să înceapă cu „este”. Metodele care returnează proprietățile obiectelor trebuie să înceapă cu „get”, iar metodele care stabilesc valorile proprietăților trebuie să înceapă cu „set”.

Regula 3: Comentariu și document.

Începeți fiecare metodă și procedură cu o descriere într-un comentariu a ceea ce face metoda sau procedura, parametrii, valoarea returnată și posibilele erori și excepții. Descrieți în comentarii rolul fiecărui fișier și clasă, conținutul fiecărui câmp de clasă și pașii principali ai codului complex. Scrieți comentarii pe măsură ce dezvoltați codul. Dacă crezi că le vei scrie mai târziu, te înșeli singur.

În plus, asigurați-vă că aplicația sau biblioteca dvs. are un manual care explică ce face codul dvs., definește dependențele acestuia și oferă instrucțiuni pentru construirea, testarea, instalarea și utilizarea acestuia. Documentul trebuie să fie scurt și convenabil; un simplu fișier README este adesea suficient.

Regula 4. Nu te repeta.

Nu copiați și lipiți niciodată cod. În schimb, izolați partea comună într-o metodă sau clasă (sau macro, dacă este necesar) și utilizați-o cu parametrii corespunzători. Evitați să utilizați date și bucăți de cod similare. De asemenea, utilizați următoarele tehnici:

  • Generați referințe API din comentarii folosind Javadoc și Doxygen.
  • Generarea automată de teste unitare bazate pe adnotări sau convenții de denumire.
  • Generați PDF și HTML dintr-o singură sursă etichetată.
  • Preluarea structurii clasei din baza de date (sau invers).

Regula 5: Verificați erorile și răspundeți la ele.

Metodele pot returna simptome de eroare sau pot arunca excepții. Procesați-le. Nu te baza pe faptul că discul nu se va umple niciodată, fișierul tău de configurare va fi mereu acolo, aplicația ta va rula cu toate drepturile de care are nevoie, cererile de alocare a memoriei vor reuși întotdeauna sau că conexiunea ta nu va eșua niciodată. Da, o bună gestionare a erorilor este greu de scris și face codul mai lung și mai greu de citit. Dar ignorarea erorilor pur și simplu mătură problema sub covor, unde un utilizator nebănuit o va descoperi într-o zi.

Regula 6: Împărțiți codul în părți scurte, discrete.

Fiecare metodă, funcție sau bloc de cod ar trebui să se încadreze într-o fereastră obișnuită a ecranului (25-50 de linii). Dacă este mai lung, împărțiți-l în bucăți mai scurte. Chiar și în cadrul unei metode, împărțiți codul lung în blocuri, a căror esență o puteți descrie într-un comentariu la începutul fiecărui bloc.

Mai mult, fiecare clasă, modul, fișier sau proces trebuie să îndeplinească un anumit tip de sarcină. Dacă o bucată de cod îndeplinește sarcini complet diferite, atunci împărțiți-o în consecință.

Regula 7. Utilizați API-uri cadru și biblioteci terțe.

Explorați ce caracteristici sunt disponibile prin API-ul cadrului dvs. și, de asemenea, ce pot face bibliotecile mature terțe. Dacă bibliotecile sunt acceptate de managerul de pachete de sistem, acestea vor fi probabil o alegere bună. Folosește un cod care descurajează dorința de a reinventa roata (și un pătrat inutil de altfel).

Regula 8: Nu supraproiectați.

Proiectați doar ceea ce este relevant acum. Puteți face codul suficient de generic pentru a sprijini dezvoltarea ulterioară, atâta timp cât nu devine prea complex. Nu creați clase parametrizate, fabrici, ierarhii profunde și interfețe ascunse pentru a rezolva probleme care nici măcar nu există - nu puteți ghici ce se va întâmpla mâine. Pe de altă parte, atunci când structura codului nu se potrivește sarcinii, nu ezitați să-l refactorizați.

Regula 9: Fii consecvent.

Fă aceleași lucruri în același mod. Dacă dezvoltați o metodă a cărei funcționalitate este similară cu cea a uneia existente, utilizați un nume similar, o ordine similară a parametrilor și o structură similară a corpului. Același lucru este valabil și pentru clase. Creați câmpuri și metode similare, oferiți-le interfețe similare și potriviți nume noi cu cele existente în clase similare.

Codul dumneavoastră trebuie să respecte convențiile cadrului dumneavoastră. De exemplu, este o bună practică să faceți gamele semideschise: închise (inclusiv) în stânga (la începutul intervalului) și deschise (exclusiv) în dreapta (la sfârșit). Dacă nu există acorduri pentru un anumit caz, atunci faceți o alegere și rămâneți la ea fanatic.

Regula 10: Evitați problemele de securitate.

Codul modern rareori funcționează izolat. Are un risc iminent de a deveni o țintă de atac. Nu trebuie să vină de pe Internet; atacul poate avea loc prin datele de intrare ale aplicației dvs. În funcție de limbajul și domeniul dvs. de programare, este posibil să aveți nevoie să vă faceți griji cu privire la depășirile de buffer-uri, scripturile între site-uri, injecția SQL și alte probleme similare. Studiați aceste probleme și evitați-le în codul dvs. Nu este greu.

Regula 11: Utilizați structuri de date și algoritmi eficienți.

Codul simplu este adesea mai ușor de întreținut decât același cod, dar modificat pentru eficiență. Din fericire, puteți combina întreținerea și eficiența folosind structurile de date și algoritmii pe care cadrul dvs. vă oferă. Folosiți harta, setul, vectorul și algoritmii care funcționează cu ele. Acest lucru va face codul dvs. mai curat, mai rapid, mai scalabil și mai eficient în memorie. De exemplu, dacă stocați o mie de valori într-o mulțime sortată, operația de intersecție va găsi elemente comune cu un alt set în același număr de operații, mai degrabă decât un milion de comparații.

Regula 12. Utilizați teste unitare.

Complexitatea software-ului modern îl face mai costisitor de instalat și mai dificil de testat. O abordare productivă ar fi să însoțiți fiecare bucată de cod cu teste care verifică corectitudinea funcționării acestuia. Această abordare simplifică depanarea deoarece permite detectarea mai devreme a erorilor. Testarea unitară este necesară atunci când programați în limbaje cu tastare dinamică, cum ar fi Python și JavaScript, deoarece acestea captează orice erori numai în timpul execuției, în timp ce limbajele tastate static, cum ar fi Java, C# și C++, pot prinde unele dintre ele în timpul execuției timp. Testarea unitară vă permite, de asemenea, să vă refactorizați codul cu încredere. Puteți utiliza XUnit pentru a facilita scrierea testelor și pentru a automatiza execuția acestora.

Regula 13: Păstrați codul portabil.

Cu excepția cazului în care aveți un motiv anume, nu utilizați funcționalitatea care este disponibilă numai pe o anumită platformă. Nu vă bazați pe anumite tipuri de date (cum ar fi numere întregi, indicatori și marcaje temporale) pentru a avea o anumită lungime (de exemplu, 32 de biți), deoarece acest parametru diferă pe platforme diferite. Păstrați mesajele programului separat de cod și nu codificați parametrii specifici culturii (cum ar fi separatorii zecimali sau formatele de dată). Sunt necesare convenții pentru a se asigura că codul poate rula în diferite țări, astfel încât localizarea să fie cât mai nedureroasă posibil.

Regula 14: Fă-ți codul compus.

O comandă simplă ar trebui să vă asamblate codul într-o formă pregătită pentru distribuție. Comanda ar trebui să vă permită să construiți și să rulați rapid testele necesare. Pentru a atinge acest obiectiv, utilizați instrumente automate de construcție precum Make, Apache Maven sau Ant. În mod ideal, ar trebui să instalați un sistem de integrare care vă va verifica, construi și testa codul ori de câte ori se schimbă.

Regula 15: Pune totul în controlul versiunii.

Toate elementele dvs. - cod, documentație, surse de instrumente, scripturi de construcție, date de testare - ar trebui să fie în controlul versiunii. Git și GitHub fac această sarcină ieftină și fără probleme. Dar multe alte instrumente și servicii puternice vă sunt, de asemenea, disponibile. Ar trebui să puteți construi și testa programul pe un sistem configurat pur și simplu descărcându-l din depozit.

Concluzie.

Făcând aceste 15 reguli parte din practica dumneavoastră zilnică, veți ajunge să creați un cod care este mai ușor de citit, care este bine testat, care are mai multe șanse să ruleze corect și care este mult mai ușor de schimbat când va veni momentul. De asemenea, te vei scuti pe tine și pe utilizatorii tăi de multe dureri de cap.

Cu toții suntem oameni și avem tendința de a greși. Și chiar și computerele greșesc dacă programul care le alimentează a fost scris cu o eroare. Pentru a vă ajuta să evitați unele greșeli când scrieți programe în orice limbaj de programare, voi vorbi despre câteva reguli folosite la scrierea programelor și metodele de programare. Urmărirea metodelor descrise mai jos nu numai că vă va ajuta să evitați unele erori, dar va preveni și apariția acestora și va simplifica depanarea programului dumneavoastră. Toate exemplele și codul programului de mai jos sunt scrise în Visual Basic 6.0. Puteți folosi materialul din acest articol pentru alte limbaje de programare. Articolul nu te leagă de niciun limbaj specific și este universal.

Metoda de proiectare software

Pentru a rezolva problemele de programare, se folosește „Metoda de proiectare software”. Această metodă constă din mai mulți pași:

1. Determinarea condițiilor problemei.
2. Analiza sarcinii.
3. Crearea unui algoritm pentru rezolvarea problemei.
4. Implementarea algoritmului.
5. Testarea și depanarea programului terminat.
6. Suport și actualizare a programului finalizat.

În prima etapă, sunt determinate condițiile problemei și este necesar să înțelegem clar ce este necesar pentru a o rezolva. Scopul principal în acest caz este de a elimina aspectele minore din esența principală a sarcinii.

În a doua etapă, sunt determinate datele de intrare, datele de ieșire, datele intermediare și ce dificultăți suplimentare pot apărea la rezolvarea problemei.

Al treilea pas este crearea unui algoritm - înregistrarea procedurilor pas cu pas și apoi asigurarea faptului că algoritmul rezolvă problema corect. Algoritmul poate fi scris și sub formă de organigrame.

Probabil tuturor celor care au studiat programarea sau informatica în instituțiile de învățământ li s-a spus cum să deseneze diagrame. Și probabil că majoritatea oamenilor nu le place să le deseneze. Umilul tău slujitor este, de asemenea, unul dintre ei. Dar să nu credeți că diagramele sunt absolut inutile în programare. Personal, nu desenez niciodată diagrame de flux când dezvolt programe, dar o pot face bine. Și vă sfătuiesc cu tărie să învățați cum să le desenați mai bine decât oricine altcineva. Dacă nu învățați să desenați diagrame de flux singur și corect, nu veți putea înțelege esența modului în care funcționează programul! Este schema bloc care vă permite să arătați clar și clar (schematic) cum se execută programul pas cu pas (linie cu linie). La urma urmei, o diagramă bloc este algoritmul pentru executarea programului în sine. Ce este un algoritm?

Algoritm- aceasta este o descriere a execuției exacte, pas cu pas, a acțiunilor care rezolvă sarcina în mod corespunzător. Prin urmare, dacă puteți scrie un algoritm pentru executarea unui program, puteți scrie programul în sine și în orice limbaj de programare (pe care, desigur, îl veți ști). După ce ați învățat să desenați diagrame, veți învăța să analizați codul programului linie cu linie, procesându-l în cap, la fel ca un computer. Acest lucru este foarte important la depanarea programului (etapa a cincea).

Când vă confruntați cu rezolvarea unei probleme foarte complexe, puteți (și ar trebui) să utilizați metoda „descompunere”. Esența metodei este de a împărți o problemă complexă în mai multe subsarcini interdependente, mici și simple, rezolvând pe care separat veți obține rezultatul dorit. Aici putem da o analogie cu o mătură. Este foarte greu să spargi întreaga mătură, dar dacă o rupi o dată, totul se va rezolva.

A patra etapă a metodei de proiectare a mediului software este de a scrie algoritmul creat ca program într-un limbaj de programare specific.

La a cincea etapă, programul este testat și depanat. Constă în a găsi tot felul de erori și a permite programului să funcționeze corect. În procesul de identificare a erorilor, se utilizează „depanarea manuală a programelor”. Constă în executarea mentală a fiecărui pas al unui algoritm care îi rezolvă problema (cum va face computerul ulterior) și vă permite să vă asigurați că acest algoritm va funcționa corect.

De asemenea, în procesul de testare a programului, se folosește o „soluție de referință”. Aceasta este o soluție la o problemă dată folosind o altă metodă (de exemplu, matematic), care vă permite să obțineți rezultate de calcul evident corecte. Mai mult, soluția de referință utilizează nu date unice, ci o varietate de date diferite care permite acoperirea tuturor situațiilor posibile de calcul. Pe baza unei astfel de „soluții de referință”, este posibil să se identifice toate capcanele posibile și erorile de program sau situațiile în care programul nu va funcționa corect. De asemenea, trebuie să implementați „foolproofing” în programul dvs. Acesta este atunci când sunt luate în considerare situațiile pentru care programul nu este destinat în principiu. De exemplu, introducerea numerelor într-un câmp sau variabilă concepută pentru a stoca un nume de familie.

Unele situații și erori nu pot fi identificate nici măcar pe baza unei „soluții de referință”. Astfel de erori apar numai în timpul utilizării pe termen lung a programului cu multe date de intrare. În a șasea etapă, acestea sunt corectate, precum și programul este modificat în conformitate cu reglementările guvernamentale sau politicile companiei modificate.

Când scrieți programe, trebuie să respectați și alte reguli, care vor fi discutate mai jos.

Variabile

Nume de variabile

În aproape toate programele trebuie să folosim variabile, uneori chiar și o mulțime de variabile. Principalul lucru este să nu vă confundați mai târziu cu ce variabilă stochează ce date. Pentru a face acest lucru, trebuie să dați nume variabilelor nume semnificative. Singurele excepții pot fi variabilele utilizate în bucle, dar nu implicate în mod repetat în calcule.

Pentru i = 1 până la 10 Pasul 1
Pentru j = 1 până la 10 Pasul 1
dmsTable(i, j) = i * j
Următorul j
În continuare i

Dacă trebuie să salvăm anul de naștere al cuiva într-o variabilă. Numiți variabila „vblYearsBorn” în loc de „A”. Încercați să vă asigurați că numele variabilei reflectă esența datelor pe care intenționează să le stocheze, astfel încât să fie intuitiv. Acest lucru poate face ca numele variabilei să fie puțin lung, dar vă va împiedica să vă confundați și vă va împiedica să reutilizați această variabilă în alte calcule pentru care nu este destinată. Este indicat să începeți numele variabilei cu majuscule vbl, din variabila (variabilă) engleză. Acest lucru este valabil mai ales în programarea orientată pe obiecte (denumită în continuare OOP). Deoarece numele unei variabile poate fi confundat cu numele unui obiect din formular (acesta va fi discutat mai jos).

Pentru claritate, să numim aceste trei litere inițiale „Identificator de obiect”, deoarece în continuare le voi menționa de mai multe ori.

După identificator, fără spații, ar trebui să scrieți numele variabilei. Trebuie să înceapă cu o literă mare, astfel încât atunci când vizualizați lista de programe să puteți vedea că este o variabilă sau un alt obiect, astfel încât literele să iasă în evidență și să nu se îmbine într-o singură linie.

Declararea variabilelor

Unele limbaje de programare (de exemplu, Visual Basic) vă permit să lucrați cu variabile fără a le declara în codul programului. Cred că aceasta este o mare greșeală și nu un limbaj de programare solid (dar asta nu înseamnă că acest limbaj de programare este rău)!

Declararea unei variabile înseamnă definirea tipului și a numelui acesteia.

Dim vblFirstName ca șir (Visual Basic)
Var vblFirstName: String; (Turbo Pascal)
Char vblFirstName; (C++)

Aceste. indicăm programului că vom folosi o variabilă numită vblFirstName și tipul de date al acestei variabile este String (text/literal).

De ce este acest lucru important (acest lucru se aplică doar acelor limbaje de programare care permit acest lucru. De exemplu, dacă nu declarați o variabilă în C++ sau Turbo Pascal, va fi generată o eroare în timpul compilării că variabila utilizată nu este declarată) ? Este foarte simplu. Dacă nu declarăm o variabilă, i se va atribui automat tipul Variant, asta înseamnă că în variabilă pot fi stocate date de aproape orice tip. În primul rând, vom putea scrie date numerice în variabila care stochează numele de familie sau invers. ESTE GREȘIT! Deoarece numele de familie nu poate conține numere. Creăm în mod deliberat un gol în program, o oportunitate de a greși. Acestea sunt tipurile de erori pe care hackerii le folosesc pentru a pirata sisteme și așa mai departe. În al doilea rând, tipul atribuit automat ocupă mult spațiu în RAM. Un program bun ar trebui să cântărească cât mai puțin posibil. Și nu contează câți gigaocteți de memorie RAM aveți pe computer. În al treilea rând, declararea explicită a variabilelor vă va permite să le atribuiți tipul de date de care aveți nevoie. Și îți va fi mult mai ușor să afli ce variabile sunt deja folosite în program. Va fi suficient să te uiți la începutul codului de program sau al modulului pentru a vedea care variabile sunt deja setate și să nu cercetezi întregul cod de program. Nu puteți re-declara o variabilă deja declarată în același modul sau nu puteți amesteca numele acestora, ceea ce înseamnă că nu utilizați variabila în calcule pentru care nu este destinată.

OOP vă permite să declarați variabile cu același nume de mai multe ori, cu condiția ca aceste variabile să fie locale și să fie utilizate numai în module diferite. Vizibilitatea variabilelor va fi discutată mai jos.

Inițializarea variabilelor

După ce ați declarat o variabilă, aceasta trebuie inițializată, adică. atribuiți-i o valoare sau resetați-o la zero. Acest lucru este foarte important pentru variabilele utilizate în calcule. Faptul este că atunci când o variabilă este declarată, memorie este alocată (rezervată) pentru aceasta. Rezervarea memoriei nu șterge celulele valorilor care au fost stocate anterior în ele, așa că dacă declararea unei variabile nu este urmată de inițializarea acesteia, atunci valoarea curentă a acestei variabile va fi imprevizibilă și nu zero, la fel de mulți oameni gandeste-te. Nu este necesar să fie exact ceea ce se va întâmpla, dar dacă se întâmplă acest lucru, motivul calculelor incorecte este uneori dificil de identificat, deoarece codul programului este corect sintactic și logic, dar calculele sunt încă incorecte.

Dacă aceasta este o variabilă de tip numeric și este folosită pentru a acumula o sumă, atunci este suficient să o resetați pur și simplu la zero.

vblSum = 0
Pentru I = 1 până la 10 Pasul 1
vblSum = vblSum + i
În continuare i

Sau atribuiți-i unul dacă variabila este folosită ca multiplicator sau divizor.

vblSum = 1
Pentru I = 1 până la 10 Pasul 1
vblSum = vblSum * i
În continuare i

Dacă este o variabilă șir, curățați-o.

vblFirstName = ""

Personal, inițializez întotdeauna variabilele, chiar dacă îi atribui o valoare diferită pe linia următoare.

Variabile globale și locale

Toate variabilele au propriul domeniu de aplicare, în funcție de modul în care le-ați declarat. Variabilele pot fi locale sau globale.

Variabile locale- acestea sunt variabile declarate în interiorul unei funcții (subrutine). Ele sunt vizibile numai în cadrul unei anumite funcții și nu pot fi apelate direct din textul programului principal. Când execuția programului revine de la o funcție la codul principal al programului sau al unei alte funcții, variabilele locale sunt șterse din memorie.

Variabile globale- acestea sunt variabile definite în afara corpului unei funcții (pentru OOP, variabile declarate în modulele de proiect). Aceste variabile au un domeniu de aplicare global și sunt accesibile din orice procedură, funcție sau subrutină.

Adesea apar erori atunci când se utilizează variabile globale.

În unele limbaje de programare, un nume de variabilă globală care are același nume cu o variabilă locală își poate schimba valorile reciproc.

Pericolul utilizării variabilelor globale vine din natura lor publică, ceea ce înseamnă că o funcție poate modifica valoarea unei variabile fără ca o altă funcție să observe. În astfel de situații pot apărea erori care sunt foarte greu de identificat.

Utilizați variabile globale numai atunci când este absolut necesar, când este imposibil sau problematic să folosiți alte metode.

constante

Despre constante pe scurt. De asemenea, trebuie să fii atent când le folosești într-un program (ca și când faci programare în general). Cel mai bine este să începeți numele constantelor cu trei litere con, de la constanta engleză (constant).

Const conPi = 3,14159265

Amintiți-vă că valorile constantelor nu pot fi modificate în program (la urma urmei, acestea sunt constante, ceea ce înseamnă permanent), altfel va fi generată o eroare. Cel mai bine este să folosiți constante atunci când există o valoare care este implicată în multe calcule și valoarea acesteia nu se modifică niciodată în program. Sau atunci când este necesar să se folosească un coeficient (și, de regulă, acestea sunt, de asemenea, constante).

Programare structurată

Programare structurată- o abordare disciplinata a programarii care asigura crearea de programe usor de inteles si reduce probabilitatea erorilor. Esența acestei abordări este de a respecta stilul de programare general acceptat și de a asigura lizibilitatea textului sursă. Probabil ați observat că tot codul de program dat în exemple este scris cu o structură specifică. Aceasta este programare structurată.

Declarațiile de la începutul și sfârșitul ciclului sunt scrise strict unul sub celălalt, iar toate afirmațiile din interiorul ciclului sunt ușor la dreapta. Toate indentările sunt realizate folosind file (tasta Tab). Circuitele logice sunt scrise în același mod. Acest mod de a scrie vă face programul mai ușor de citit și mai ușor de înțeles. De asemenea, facilitează depanarea programului. Puteți compara exemplul de mai jos, scriind cod folosind principiul programării structurate și fără acesta. Exemplul este dat în Turbo Pascal (parte a codului de sortare al matricei).

Exemplu „Cod structurat”:

Pentru i:=1 până la 9 face
ÎNCEPE
vblMin:=A[i];
k:=i;
Pentru j:=1+i până la 10 do
ÎNCEPE
Dacă (vblMin>A[j]) Atunci
ÎNCEPE
vblMin:=A[j];
k:=j;
Sfârşit;
Sfârşit;
vblStuf:=A[i];
A[i]:=vblMin;
A[k]:=vblStuf;
Sfârşit;

Exemplu „Cod normal”:

Pentru i:=1 până la 9 face
ÎNCEPE
vblMin:=A[i];
k:=i;
Pentru j:=1+i până la 10 do
ÎNCEPE
Dacă (vblMin>A[j]) Atunci
ÎNCEPE
vblMin:=A[j];
k:=j;
Sfârşit;
Sfârşit;
stuf:=A[i];
A[i]:=vblMin;
A[k]:=vblStuf;
Sfârşit;

Care opțiune este mai ușor de citit și de înțeles? Fără îndoială primul.

Trebuie să vă obișnuiți să respectați toate nuanțele descrise mai sus. Desigur, nerespectarea nu este critică, dar folosirea acestor metode vă va face mult mai ușor să scrieți programe și să le întrețineți în viitor.

Erori

Programele funcționează foarte rar corect prima dată. Legea lui Murphy, care spune: „Dacă se poate întâmpla ceva rău, se va întâmpla”, pare să fi fost scrisă special pentru programe de calculator.

Erorile care apar în timpul funcționării programului pot fi împărțite în mai multe tipuri:

1. Erori de sintaxă
2. Erori de rulare
3. Erori logice

Erorile de sintaxă apar atunci când codul sursă al unui program este scris cu încălcarea uneia dintre regulile gramaticale ale limbajului de programare în care scrieți programul. Această încălcare este detectată atunci când se încearcă compilarea programului.

Erorile de rulare sunt detectate de computer în timp ce programul rulează. Astfel de erori apar atunci când un program instruiește computerul să efectueze o operațiune incorectă (cum ar fi împărțirea la zero sau manipularea datelor nedescrise sau invalide).

Erorile de introducere a datelor sunt, de asemenea, erori de rulare. Cauza unor astfel de erori este o încercare de a introduce date de tip greșit (de exemplu, unei variabile de tip întreg i se atribuie un parametru șir sau un număr de tip real).

Erorile logice apar atunci când un program execută un algoritm incorect. Aceste erori sunt cele mai insidioase, sunt foarte greu de identificat, deoarece nu sunt înregistrate în timpul compilării. Aceste erori apar atunci când programul produce rezultate incorecte. Singurele modalități posibile de a identifica astfel de erori este utilizarea următoarelor metode: „soluție de referință” și „depanare manuală”.

Folosirea cu pricepere a tuturor acestor metode și reguli: metoda de descompunere, programarea structurată, metoda de proiectare software, soluția de referință și altele vorbesc despre profesionalism.