Lecție-punte: cum împarți o problemă mare în funcții mici

Mediu~11 min9 pași

De ce contează?

Nu construiești o casă turnând tot betonul deodată. O împarți pe etape: fundație, pereți, acoperiș — fiecare cu echipa și planul ei. Un program mare e la fel: îl spargi în funcții mici, fiecare cu o treabă clară, ca să-l poți construi și verifica bucată cu bucată.

De ce să împarți deloc?

Un main de 200 de linii e greu de citit, greu de depanat și imposibil de refolosit. Împărțit în funcții mici cu nume clare, același program devine o listă de pași pe care îi înțelegi dintr-o privire:

int main() {
    citesteDate();
    proceseaza();
    afiseazaRezultat();
    return 0;
}

Nu mai trebuie să citești tot codul ca să înțelegi ce face programul — numele funcțiilor îți spun.

Cum recunoști o funcție ascunsă în cod

Trei semnale că o bucată de cod merită scoasă într-o funcție:

  1. Se repetă. Dacă același calcul apare în trei locuri, fă-l o funcție și apeleaz-o de trei ori. Repararea unui bug se face apoi într-un singur loc.
  2. Are un nume clar. Dacă poți rezuma o secvență în câteva cuvinte („verifică dacă e prim", „suma cifrelor"), aceea e o funcție.
  3. E un nivel de detaliu diferit. main ar trebui să spună ce se întâmplă; detaliile lui cum coboară în funcții.
Observația-cheie

Test rapid: dacă, ca să denumești o funcție, trebuie să folosești „și" („citește și sortează și afișează"), probabil ar trebui să fie trei funcții. O funcție = o responsabilitate.

Ce intră, ce iese

Gândește fiecare funcție ca o cutie cu intrare și ieșire:

  • Intrarea = datele de care are nevoie ca să lucreze → parametri.
  • Ieșirea = rezultatul pe care îl produce → return (un singur rezultat) sau parametri prin referință (mai multe rezultate).
// intrare: doua numere -> iesire: cmmdc-ul lor
int cmmdc(int a, int b) {
    while (b != 0) {
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}

Funcția nu depinde de nimic din afară: îi dai a și b, îți dă cmmdc-ul. O poți muta în orice program.

Observația-cheie

O funcție care primește tot ce-i trebuie prin parametri și întoarce rezultatul prin return e independentă și ușor de testat: o apelezi cu valori concrete și verifici răspunsul, fără să rulezi tot programul.

Exemplu: o problemă spartă bine

Problemă: „câte numere prime sunt într-un vector?". Spargem în două funcții cu roluri clare:

#include <iostream>
using namespace std;

bool estePrim(int x) {
    if (x < 2) return false;
    for (int d = 2; d * d <= x; d++) {  // pana la radacina lui x
        if (x % d == 0) return false;
    }
    return true;
}

int cateprime(int v[], int n) {
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (estePrim(v[i])) cnt++;   // refolosesc estePrim
    }
    return cnt;
}

int main() {
    int v[6] = {4, 7, 9, 11, 2, 15};
    cout << cateprime(v, 6) << "\n";  // 3  (7, 11, 2)
    return 0;
}

cateprime nu se ocupă de cum verifici primalitatea — deleagă lui estePrim. Fiecare funcție e scurtă, clară și ușor de verificat singură.

Greșeli frecvente

Capcane când împarți în funcții:

  • Funcție care face prea multe: citește, calculează și afișează în același loc. Greu de refolosit. Sparge după responsabilitate.
  • Prea multe variabile globale ca scurtătură: în loc să pasezi datele prin parametri, le lași globale „să fie mai ușor". Pe termen lung face fluxul de date imposibil de urmărit. Preferă parametri + return.
  • Despici excesiv: o funcție de o linie apelată o singură dată poate adăuga zgomot fără folos. Împarte unde câștigi claritate sau refolosire, nu de dragul împărțirii.
  • Funcții care depind de ordinea apelului prin globale: dacă proceseaza() merge doar dacă citesteDate() a rulat înainte și a setat globale, ai cuplaj ascuns. Fă dependențele explicite prin parametri.

Recapitulare

  • Sparge un program în funcții când codul se repetă, are un nume clar sau ține de un alt nivel de detaliu.
  • O funcție = o responsabilitate; intrarea ei sunt parametrii, ieșirea e return-ul (sau referințele).
  • Preferă parametri și return în locul globalelor — fac funcțiile independente și ușor de testat.

Întrebarea 1 / 3

Care e semnul bun că o bucată de cod ar trebui scoasă într-o funcție?