L'accoppiamento tra classi di oggetti (CBO) è una metrica proposta da Chidamber & Kemerer per misurare per una classe quanto altre classi sono accoppiate. Un accoppiamento significa che un oggetto di una classe usa metodi o proprietà di un oggetto in un'altra classe.
Il fattore polimorfico (PF) è una metrica proposta da Abreu & Melo per misurare quanto un tipo derivato sostituisce un metodo dalla classe base. Viene calcolato contando il numero di metodi sottoposti a override rispetto al numero di metodi.
Queste sono misure indipendenti, quindi in teoria puoi trovare qualsiasi tipo di relazione. Ma diamo un'occhiata a un esempio per mostrare come si relazionano nella pratica.
Supponiamo di avere classi per rappresentare diverse forme ( Circle , Square , ecc ...) e una classe Figure , composta da più forme. Figure ha una funzione draw() che richiama un metodo di disegno per ciascuna delle sue forme.
-
Implementazione Uggly : ogni forma come una propria classe indipendente con una propria funzione di disegno specifica (ad esempio
draw_circle() , draw_square( ), ...). Figure deve quindi essere abbinato a tutte le forme, con un sacco di condizionali per far fronte alle diverse forme. Ogni volta che aggiungi una nuova forma, aggiungi un nuovo accoppiamento.
- CBO = N, dove N è il numero di forme.
- PF = 0 perché non c'è ereditarietà e quindi non ha priorità.
-
Implementazione polimorfica: ogni forma eredita da una superclasse
Shape e sovrascrive la funzione polimorfa draw() . Figure conosce solo Shape .
- CBO = 1, perché
Figure richiama solo draw() su un oggetto Shape .
- PF tende al 100% (precisamente è
N/(2+N) perché Figure::draw() e Shape::draw() non sono overrides, ma Shape::draw() è sovrascritto da N forme
L'ipotesi comune è che un sistema con accoppiamento basso sia più facile da mantenere. Pertanto, molti modelli di progettazione intendono ridurre l'accoppiamento. Nella maggior parte dei casi, il polimorfismo è il fattore abilitante per un disaccoppiamento.
L'astrazione è la chiave, non la funzione linguistica utilizzata per implementarla. L'ereditarietà dell'interfaccia e l'ereditarietà normale sono due modi per ottenere l'astrazione. L'ereditarietà dell'interfaccia richiede di fornire un'implementazione per le funzioni dell'interfaccia (vale a dire fornire un override per le funzioni astratte che non sono definite). Quindi aumenta matematicamente PF. Tuttavia, alcuni linguaggi come il C ++ non hanno interfacce ma usano pure funzioni virtuali alla fine con ereditarietà multipla per fare lo stesso, con un PF identico. Nel nostro esempio, l'ereditarietà è l'abilitazione per ridurre l'accoppiamento.