Componenti e Astrazioni
Non c’è niente che ti impedisca di scrivere l’intero tuo programma, per quanto complesso, all’interno della singola funzione main() in un unico enorme file sorgente. Tuttavia, questo approccio diventa rapidamente impossibile da mantenere.
La buona ingegneria del software (Software Engineering) prevede la scomposizione del programma in componenti logici più piccoli.
Coesione (Cohesion) e Accoppiamento (Coupling)
Section titled “Coesione (Cohesion) e Accoppiamento (Coupling)”Quando dividi il tuo codice in più file, devi tenere a mente due proprietà fondamentali dell’architettura del software:
- Alta Coesione (High Cohesion): Misura quanto gli elementi all’interno di un componente siano legati tra loro. Un header file che dichiara solo funzioni matematiche ha alta coesione. Un header file che dichiara il calcolo del seno, la connessione al database e la gestione del mouse ha bassa coesione. Il tuo obiettivo è l’alta coesione.
- Basso Accoppiamento (Low Coupling): Misura quanto un componente sia indipendente dagli altri. Se per includere il modulo “Utente” devi obbligatoriamente includere altri 10 file in un ordine specifico, hai un forte accoppiamento (tight coupling). L’obiettivo è avere moduli indipendenti e riutilizzabili (basso accoppiamento).
Astrazione dei Dati e Tipi Opachi (Opaque Types)
Section titled “Astrazione dei Dati e Tipi Opachi (Opaque Types)”L’astrazione dei dati consiste nel separare nettamente l’Interfaccia Pubblica dai Dettagli Implementativi.
L’interfaccia pubblica si trova nell’header (.h) e viene letta da chi userà la libreria. L’implementazione si trova nel file sorgente (.c) e rimane privata e nascosta.
In C, il modo migliore per nascondere i dettagli di una struct è utilizzare i Tipi Opachi (o tipi incompleti):
// --- FILE: collezione.h (Interfaccia Pubblica) ---#ifndef COLLEZIONE_H#define COLLEZIONE_H
// Tipo Opaco: Diciamo al compilatore che esiste una struct,// ma non riveliamo quali variabili contiene!typedef struct Collezione Collezione;
Collezione* crea_collezione(void);void distruggi_collezione(Collezione* c);int collezione_get_conteggio(const Collezione* c);
#endif // COLLEZIONE_H// --- FILE: collezione.c (Dettagli Implementativi Nascosti) ---#include "collezione.h"#include <stdlib.h>
// Qui definiamo la vera struttura. Solo questo file .c la conosce!struct Collezione { int elementi[100]; int contatore;};
Collezione* crea_collezione(void) { Collezione* c = malloc(sizeof(struct Collezione)); if (c) c->contatore = 0; return c;}
void distruggi_collezione(Collezione* c) { free(c);}
int collezione_get_conteggio(const Collezione* c) { return c ? c->contatore : 0;}💻 Esercizio Pratico
Section titled “💻 Esercizio Pratico”In questo esercizio, simuleremo un header e un file sorgente in un unico blocco di codice per implementare un tipo opaco. Devi definire la struttura opaca e una funzione per interagire con essa.