1. Meseria de programator

Foarte des, programatorii începători gândesc munca unui programator complet diferit de modul în care o consideră programatorii experimentați .

Începătorii spun adesea ceva de genul „Programul funcționează, ce altceva ai nevoie?” Un programator cu experiență știe că „funcționează corect” este doar una dintre cerințele unui program și nici măcar nu este cel mai important lucru !

Lizibilitatea codului

Cel mai important lucru este că codul programului este înțeles de alți programatori . Acest lucru este mai important decât un program de lucru corect. Mult mai mult.

Dacă aveți un program care nu funcționează corect, îl puteți repara. Dar dacă ai un program al cărui cod este de neînțeles, nu poți face nimic cu el.

Doar luați orice program compilat, cum ar fi notepad, și schimbați culoarea de fundal în roșu. Ai un program de lucru, dar nu ai un cod sursă de înțeles: este imposibil să faci modificări unui program de acest fel.

Un exemplu de manual este atunci când dezvoltatorii Microsoft au eliminat jocul Pinball din Windows, deoarece nu l-au putut porta la arhitectura pe 64 de biți. Și chiar aveau codul sursă. Pur și simplu nu au putut înțelege cum funcționează codul .

Contabilitate pentru fiecare caz de utilizare

A doua cea mai importantă cerință pentru un program este să țină cont de fiecare scenariu. De multe ori, lucrurile sunt puțin mai complicate decât par.

Cum vede un programator începător să trimită mesaje SMS:

Un program care funcționează corect

Cum vede un programator profesionist:

Un program care funcționează corect

Scenariul „funcționează corect” este de obicei doar unul dintre mai multe posibile. Și de aceea mulți începători se plâng de validatorul de sarcini CodeGym: doar un scenariu din 10 funcționează, iar programatorul începător crede că este suficient.


2. Situații anormale

Situații anormale

În execuția oricărui program pot apărea situații anormale.

De exemplu, decideți să salvați un fișier, dar nu există spațiu pe disc. Sau programul încearcă să scrie date în memorie, dar memoria disponibilă este redusă. Sau descărcați o imagine de pe Internet, dar conexiunea se pierde în timpul procesului de descărcare.

Pentru fiecare situație anormală, programatorul (autorul programului) trebuie a) să o anticipeze , b) să decidă cum exact trebuie să o gestioneze programul și c) să scrie o soluție cât mai apropiată de cea dorită.

De aceea programele au avut un comportament foarte simplu pentru o perioadă destul de lungă de timp: dacă a apărut o eroare în program, programul se termina. Și asta a fost o abordare destul de bună.

Să presupunem că doriți să salvați un document pe disc, în timpul procesului de salvare descoperiți că nu există suficient spațiu pe disc. Ce comportament ți-ar plăcea cel mai mult:

  • Programul se încheie
  • Programul continuă să ruleze, dar nu salvează fișierul.

Un programator începător poate crede că a doua opțiune este mai bună, deoarece programul încă rulează. Dar în realitate nu este așa.

Imaginați-vă că ați tastat un document în Word timp de 3 ore, dar la două minute după procesul de scriere a devenit clar că programul nu va putea salva documentul pe disc. Este mai bine să pierzi două minute de lucru sau trei ore?

Dacă programul nu poate face ceea ce trebuie, este mai bine să îl lăsați să se închidă decât să continuați să pretindeți că totul este în regulă. Cel mai bun lucru pe care îl poate face un program atunci când întâlnește o defecțiune pe care nu o poate remedia singur este să raporteze imediat problema utilizatorului.


3. Context despre excepții

Programele nu sunt singurele care se confruntă cu situații anormale. Ele apar și în cadrul programelor - în metode. De exemplu:

  • O metodă vrea să scrie un fișier pe disc, dar nu există spațiu.
  • O metodă dorește să apeleze o funcție pe o variabilă, dar variabila este egală cu nul.
  • Împărțirea cu 0 se întâmplă într-o metodă.

În acest caz, metoda de apelare ar putea corecta situația (executa un scenariu alternativ) dacă știe ce fel de problemă a apărut în metoda apelată.

Dacă încercăm să salvăm un fișier pe disc și un astfel de fișier există deja, putem cere pur și simplu utilizatorului să confirme că ar trebui să suprascriem fișierul. Dacă nu există spațiu disponibil pe disc, putem afișa un mesaj utilizatorului și îi putem cere utilizatorului să selecteze un alt disc. Dar dacă programul rămâne fără memorie, se va bloca.

Pe vremuri, programatorii s-au gândit la această întrebare și au venit cu următoarea soluție: toate metodele/funcțiile trebuie să returneze un cod de eroare care să indice rezultatul execuției lor. Dacă o funcție a funcționat perfect, a returnat 0 . Dacă nu, a returnat un cod de eroare (nu zero).

Cu această abordare a erorilor, după aproape fiecare apel de funcție, programatorii au trebuit să adauge o verificare pentru a vedea dacă funcția sa terminat cu o eroare. Codul a crescut în dimensiune și a ajuns să arate astfel:

Cod fără gestionarea erorilor Cod cu gestionarea erorilor
File file = new File("ca:\\note.txt");
file.writeLine("Text");
file.close();
File file = new File("ca:\\note.txt");
int status = file.writeLine("Text");
if (status == 1)
{
   ...
}
else if (status == 2)
{
   ...
}
status = file.close();
if (status == 3)
{
   ...
}

Mai mult decât atât, destul de des o funcție care a descoperit că a apărut o eroare nu știa ce să facă cu ea: apelantul trebuia să returneze eroarea, iar apelantul apelantului o returna apelantului său și așa mai departe.

Într-un program mare, un lanț de zeci de apeluri de funcții este norma: uneori puteți găsi chiar și o adâncime de apel de sute de funcții. Și acum trebuie să treceți codul de eroare de jos în sus. Și dacă undeva pe parcurs o funcție nu se ocupă de codul de ieșire, atunci eroarea se va pierde.

Un alt dezavantaj al acestei abordări este că, dacă funcțiile returnau un cod de eroare, nu mai puteau returna rezultatele propriei lucrări. Rezultatul calculelor a trebuit să fie transmis prin intermediul parametrilor de referință. Acest lucru a făcut codul și mai greoi și a crescut și mai mult numărul de erori.