Coesione nello sviluppo mobile: basi, livelli e come migliorarla

Autore: IT Sectr Pubblicato: 2026-05-13 Tempo di lettura: 9 min

La coesione è una metrica che mostra quanto strettamente correlati sono gli elementi all'interno di un modulo o una classe. Secondo Wikipedia, un'alta coesione è una caratteristica di un modulo ben progettato, dove tutti i metodi e i campi lavorano su un unico compito. La coesione influisce direttamente sulla manutenibilità del codice e si contrappone all'accoppiamento — l'interconnessione tra moduli.

Punti chiave

  • Coesione — una misura di quanto gli elementi all'interno di un modulo sono uniti da uno scopo comune
  • Alta coesione facilita la comprensione del codice, i test e l'apporto di modifiche
  • Bassa coesione significa che il modulo esegue diversi compiti non correlati
  • Coesione e accoppiamento sono metriche correlate: maggiore è la coesione, minore è l'accoppiamento
  • Coesione funzionale — il livello più alto a cui tendere

Cos'è la coesione

La coesione è una metrica che valuta quanto logicamente connessi sono i metodi, i campi e le proprietà all'interno di una classe o modulo. Un modulo altamente coeso esegue un compito e contiene solo gli elementi necessari per svolgerlo. Un modulo a bassa coesione cerca di fare più cose contemporaneamente — i suoi metodi sono debolmente correlati nel significato.

Nel contesto della programmazione orientata agli oggetti, la coesione è strettamente legata al Principio di Responsabilità Unica (S). Se una classe ha una responsabilità chiara, la sua coesione è generalmente alta. Se una classe gestisce UI, logica di business e rete contemporaneamente — la coesione è bassa, e tale classe dovrebbe essere suddivisa in più classi separate con responsabilità più ristrette.

Comprendere la coesione aiuta gli sviluppatori a prendere decisioni di refactoring. Quando vedi un metodo in una classe che non utilizza alcun campo della classe, è un segno di bassa coesione. Tale metodo è fuori posto nella classe, oppure la classe è mal progettata. Cercare un'alta coesione è uno sforzo continuo per migliorare l'architettura a ogni livello del codice.

Tipi e livelli di coesione

Nell'ingegneria del software, si distinguono sette livelli di coesione, ordinati dal peggiore al migliore. Comprendere questa scala consente di valutare oggettivamente la qualità di un modulo e determinare la direzione per il refactoring. Più alto è il livello, più manutenibile e comprensibile sarà il codice.

Coesione bassa: coincidenziale, logica e temporale

Coincidenziale — il peggior livello, dove gli elementi di un modulo sono raggruppati casualmente senza alcuna connessione logica. Esempio: una classe Utilities con metodi per formattare date, inviare email e calcolare sconti. Tale classe non può essere compresa senza leggere tutti i suoi metodi, e modificarne uno potrebbe romperne altri semplicemente perché sono insieme.

Logica — gli elementi eseguono compiti logicamente correlati ma fondamentalmente diversi. Una classe con metodi parseJSON, parseXML e parseCSV è logicamente connessa dal tema dell'“analisi,” ma ogni metodo fa un lavoro radicalmente diverso. Il problema: quando si aggiunge un nuovo formato (YAML), la classe cresce e la sua interfaccia diventa gonfiata.

Temporale — gli elementi sono raggruppati per tempo di esecuzione. Una classe AppInitializer che configura il database, carica la configurazione e inizializza le analisi — tutto ciò accade all'avvio dell'app, ma i compiti stessi non sono correlati. È meglio dividerli in Initializer separati per ogni area di responsabilità.

Coesione media: procedurale e comunicazionale

Procedurale — si verifica quando gli elementi sono uniti da una sequenza di esecuzione. Un modulo “Elaborazione ordini” contiene metodi validateCart, processPayment e sendConfirmation — ogni metodo viene chiamato rigorosamente dopo il precedente. Questo è meglio della coesione coincidenziale o logica, ma non è ancora ideale: ogni passaggio potrebbe essere estratto in un modulo separato.

Comunicazionale — gli elementi lavorano con gli stessi dati. Una classe UserService con metodi getUser, updateUser e deleteUser è unita dall'entità comune User. Questo è significativamente meglio della coesione procedurale: la classe ha un dominio chiaro. La maggior parte delle classi Repository nei progetti mobili hanno coesione comunicazionale.

Coesione alta: funzionale

Funzionale — il livello più alto, dove ogni elemento del modulo partecipa all'esecuzione di un unico compito. Una classe PasswordValidator con un unico metodo validate che verifica lunghezza, presenza di caratteri e complessità della password è un esempio di coesione funzionale. Se tale classe cambia, è solo perché le regole di validazione della password sono cambiate.

Raggiungere la coesione funzionale è l'obiettivo principale del refactoring architetturale. Ogni classe dovrebbe avere esattamente un motivo per cambiare. Nello sviluppo mobile, la coesione funzionale si ottiene estraendo Use Cases separati, View personalizzate, formattatori e validatori. Ciascuna di queste classi è un blocco di costruzione completo con un'area di responsabilità chiara.

Coesione vs Accoppiamento

Coesione e accoppiamento sono due facce della stessa qualità. Più alta è la coesione all'interno di un modulo, minore tende ad essere l'accoppiamento tra moduli. Un sistema ben progettato cerca simultaneamente un'alta coesione interna e un basso accoppiamento esterno. Questo principio è riconosciuto come fondamentale nell'ingegneria del software dagli anni '70.

La relazione coesione-accoppiamento può essere pensata come un equilibrio. Se uno sviluppatore sacrifica la coesione combinando più compiti in una classe, i moduli vicini ottengono più dipendenze — devono accedere a questa classe sovraccarica per scopi diversi, aumentando l'accoppiamento. Al contrario, suddividere in classi piccole e altamente coese riduce i punti di interazione tra moduli.

In pratica, ciò significa: quando estrai una nuova classe con coesione funzionale, contemporaneamente liberi altri moduli dalla necessità di conoscere i dettagli della sua implementazione. Ad esempio, estrarre EncryptionManager in una classe separata con coesione funzionale fornisce ad altri moduli una semplice interfaccia encrypt/decrypt senza bisogno di comprendere i dettagli dell'algoritmo di crittografia.

kotlin
// Bassa coesione — la classe fa tutto in una volta
class UserManager {
    fun fetchAndSaveUser(id: String) { }
    fun parseUserJson(json: String): User { }
    fun displayUserName(user: User): String { }
    fun validateEmail(email: String): Boolean { }
}

// Alta coesione — ogni classe risolve un compito
class UserRepository {
    fun fetchUser(id: String): User { }
}

class UserJsonParser {
    fun parse(json: String): User { }
}

class UserNameFormatter {
    fun format(user: User): String { }
}

class EmailValidator {
    fun isValid(email: String): Boolean { }
}

L'esempio mostra la differenza: UserManager ha coesione logica — tutti i metodi riguardano gli utenti, ma ciascuno fa un lavoro fondamentalmente diverso. Dopo il refactoring, ogni classe ha coesione funzionale e l'accoppiamento si riduce perché altri moduli dipendono solo dalla classe di cui hanno bisogno, non dall'intero UserManager.

Come misurare la coesione nel codice

LCOM (Mancanza di Coesione dei Metodi) è la metrica più nota per misurare la coesione di una classe. LCOM conta quante coppie di metodi non condividono campi comuni. Un valore di 0 significa coesione ideale (tutti i metodi lavorano con gli stessi campi), mentre un valore alto indica bassa coesione. LCOM4 (una versione migliorata) considera le connessioni transitive attraverso altri metodi.

Nello sviluppo Android, le metriche di coesione possono essere ottenute tramite Detekt con la regola TooManyFunctions. Le classi con decine di metodi che utilizzano diversi gruppi di campi hanno probabilmente bassa coesione. In iOS, SwiftLint ha le regole file_length e function_body_length — indicatori indiretti: file e metodi lunghi spesso segnalano bassa coesione.

Un metodo di valutazione manuale: poni la domanda “Questa classe cambierà per una ragione o per ragioni multiple?” Se puoi nominare più di una ragione indipendente — la classe ha bassa coesione. Un secondo test: “Questa classe può essere divisa in due classi indipendenti?” Se sì — fallo. Controllare regolarmente la coesione durante le revisioni del codice previene le classi God e riduce il debito tecnico.

Come migliorare la coesione in un progetto mobile

Il primo passo — applicare il Principio di Responsabilità Unica. Ogni classe dovrebbe avere una responsabilità chiara. Se una classe ha un metodo che non riguarda il suo compito principale, estrailo in una classe separata. La tecnica Extract Class o Extract Delegate negli IDE automatizza questo processo. Dopo l'estrazione, verifica se la classe originale è diventata più focalizzata.

Il secondo passo — utilizzare il pattern Facade per semplificare l'interfaccia. Se una classe fornisce 20 metodi ma i clienti ne usano solo 3–4, la classe potrebbe avere bassa coesione — offre troppe funzionalità diverse. Raggruppa i metodi per argomento, estrai classi separate per ogni gruppo e trasforma la classe originale in una facciata o rimuovila.

Il terzo passo — prestare attenzione ai gruppi di campi. Se una classe ha campi che sono usati solo da un sottoinsieme di metodi — è un indicatore di bassa coesione. Dividi la classe per gruppi di campi. Ad esempio, se una classe contiene i campi userRepository, networkClient e analyticsTracker, ma il primo gruppo di metodi usa solo userRepository mentre il secondo usa networkClient — sono due classi diverse.

Il quarto passo — evitare di creare classi “utility” con metodi static arbitrari. Ogni metodo static in una classe Utils o Helpers è candidato all'estrazione in una classe specializzata. FormatUtils.dateToString è meglio spostarlo in DateFormatter, e ValidationUtils.isValidEmail in EmailValidator. Questo aumenta la coesione di ogni classe e rende il codice auto-documentante.

Domande frequenti

L'alta coesione è sempre positiva?

Quasi sempre. La coesione funzionale rende il codice chiaro e prevedibile. Tuttavia, portarla all'estremo può causare una frammentazione eccessiva: creare una classe separata per ogni operazione, rendendo l'architettura eccessivamente complessa. L'equilibrio è poche classi per funzionalità, ciascuna con coesione funzionale.

In cosa la coesione differisce dalla modularità?

La coesione è una metrica di consistenza interna all'interno di un singolo modulo o classe. La modularità è un principio architetturale in cui un'applicazione è divisa in moduli fisici. L'alta coesione è un obiettivo sia nella progettazione di singole classi che di interi moduli.

In che modo gli strumenti di analisi del codice aiutano con la coesione?

Detekt per Android e Xcode Analyzer per iOS evidenziano classi con un numero sospettosamente elevato di metodi o campi. IntelliJ IDEA e AppCode hanno la visualizzazione delle dipendenze — puoi vedere il grafo delle connessioni e individuare classi con bassa coesione. SonarQube calcola le metriche LCOM automaticamente.

Un'interfaccia può avere alta coesione?

. Un'interfaccia con metodi connect, disconnect e isConnected ha alta coesione — tutti i metodi riguardano la gestione della connessione. Un'interfaccia con connect, parseData e renderUI ha bassa coesione. Il Principio di Segregazione delle Interfacce (SOLID) richiede la creazione di interfacce strettamente focalizzate con alta coesione.

Come verificare la coesione durante la revisione del codice?

Poniti tre domande: Lo scopo della classe può essere descritto in una frase? Tutti i metodi supportano questo scopo? Ci sono campi nella classe che non vengono usati da alcuni metodi? Se la risposta a qualsiasi domanda è no — la coesione è bassa e la classe dovrebbe essere divisa.

Riepilogo

  • Coesione — una metrica di consistenza interna del modulo, che mostra quanto i suoi elementi sono uniti da uno scopo comune
  • Coesione funzionale — il livello più alto, dove tutti gli elementi del modulo lavorano verso un unico compito
  • Coesione coincidenziale e logica — i peggiori livelli, che segnalano la necessità di refactoring
  • Coesione e accoppiamento sono inversamente proporzionali: maggiore è la coesione interna, più debole è l'accoppiamento esterno
  • LCOM — una metrica per la valutazione numerica della coesione, disponibile negli analizzatori statici
  • Principio di Responsabilità Unica — uno strumento pratico per raggiungere un'alta coesione
  • Evita classi di utilità come Utils — ogni metodo di tale classe dovrebbe diventare una classe specializzata separata

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche