2011-01-21 12 views
10

Attualmente sto facendo qualche lavoro di progettazione API, coinvolgendo la specifica di un certo numero di interfacce come astrazioni che verranno successivamente implementate da varie classi concrete.Ottenere il giusto livello di granularità dell'interfaccia

Come accade, sto usando Java, ma penso che la domanda sia pertinente a qualsiasi linguaggio che supporti un concetto di interfaccia simile.

ho notato che v'è spesso una scelta tra:

  • Fare una grande interfaccia con una gamma completa di metodi
  • Rendere più interfacce contenenti ciascuno un sottoinsieme di tutta la gamma di metodi (un la singola classe concreta dovrebbe probabilmente implementare molte o tutte queste interfacce)

Quali sono i pro/contro di ciascun approccio?

+3

hai visto l'articolo di Bob Martin sul principio di segregazione dell'interfaccia? http://www.objectmentor.com/resources/articles/isp.pdf –

+0

@Nathan - articolo molto interessante - grazie! – mikera

+0

@NathanHughes Il link non è più disponibile. – byxor

risposta

2

Non vorrei difendere un'interfaccia con troppi metodi, come non lo farei anche per una classe. Il programmatore che deve utilizzare tali interfacce o le classi derivate avrebbe difficoltà a capire come si relazionano; inoltre cercando di ricordare cosa sono e quando usare è come destreggiarsi troppe palle.

Per me, in generale, più di 1000 linee in un modulo sono troppo; più di 100 linee anche in un metodo; più di 15 metodi circa in una classe o interfaccia. Naturalmente ci possono essere delle eccezioni, ma cerco di evitarle.

Definire quali interfacce si hanno prima di pensare quali metodi vanno in loro. Considera quali sono i 'comportamenti atomici' per ogni entità astratta nel tuo sistema e fai di ogni entità un'interfaccia, componendo con ereditarietà se necessario. Quindi decidere i metodi - dopo di che, probabilmente non ci sarebbero molti in ogni interfaccia.

+1

+1 @Fabio I tuoi numeri sono buoni. Avrei avuto un altro numero di regola empirica. Evito funzioni che richiedono più di 4/5 parametri. E riguardo i 100 metodi di righe ... In realtà il mio limite è la dimensione dello schermo: se non riesco a leggere tutte le funzioni dall'inizio alla fine in un intero, allora è troppo lungo, quindi il mio limite è di 50 linee di codice per funzione: -) –

+0

Sono assolutamente d'accordo, compresa la dimensione del metodo - quella che si adatta allo schermo è l'ideale. Nel mio caso specifico ho dovuto allentare un po 'quella regola perché volevo avere lo stesso standard per tutte le lingue che uso (Java, C, C++, C#) e quando programmare in C/C++ per Windows è più difficile fare piccoli metodi a volte - con tutte quelle enormi funzioni e strutture API Win32 che assomigliano ai moduli IRS. –

4

Il professionista di suddividere l'interfaccia è che è possibile dividere i metodi in gruppi di responsabilità che hanno senso essere insieme. Il contro è che la tua interfaccia è ora divisa in un gruppo di piccole che una classe potrebbe implementare.

Si consiglia di suddividere l'interfaccia in modo da facilitare la leggibilità e non oltre. Se hai una classe che implementa 10 interfacce, queste interfacce devono essere combinate in una sola, o forse la classe sta assumendo molte responsabilità e in realtà devono essere due o più classi.

2

Rendere più interfacce contenenti ciascuno un sottoinsieme della gamma di metodi

Tale approccio tenderebbe a lavorare meglio con il principio di progettazione "prefer composition to inheritence", perché classi separate potrebbero ciascuna attuare uno (o alcune) delle interfacce.

2

Non ho una buona risposta alla tua domanda. Il design dell'API è un po 'un'arte. Se sei nel mezzo di un grande sforzo di progettazione, ti consiglio di procurarti una copia di Practical API Design di Jaroslav Tulach di fama NetBeans.

Penso che raccomanderebbe contro troppi metodi, alcuni dei quali potrebbero essere solo metodi di supporto. Dovresti esporre il minimo necessario per lavorare con l'API. Meno verboso, meglio è.

2

Il numero di metodi in un'interfaccia deve essere guidato solo dal suo utilizzo noto (o previsto). Se in genere i chiamanti utilizzano tre membri diversi (ma sovrapposti) dei sei membri di un'interfaccia, allora sei!

Un gran numero di metodi spesso indica una scarsa coesione e una buona progettazione degli oggetti dovrebbe comunque porre un limite naturale a quel numero. Ma non dovresti mai dividere un'interfaccia solo per ridurre il numero di metodi che contiene.

3

Un problema non ancora menzionato: le interfacce che inseriscono elementi in una raccolta devono essere separate da quelle che eliminano gli elementi; un'interfaccia combinata dovrebbe ereditare da entrambi. Segregare le interfacce in questo modo consente la covarianza e la controvarianza. Ad esempio, un ReadableBunch (Of ToyotaPrius) può essere tranquillamente passato a una routine che prevede un ReadableBunch (Of Car) [poiché un oggetto che fornisce istanze di ToyotaPrius genererà in tal modo istanze di Car], e un WritableQueue (Of Car) può essere tranquillamente passato a una routine che si aspetta un WriteableQueue (Of HondaCivic) [dal momento che un oggetto che può accettare un'automobile, per definizione, accetta un HondaCivic].

Non so se questo tipo di covarianza e controvarianza significhi qualcosa in Java, ma poiché la domanda è stata codificata in linguaggio agnostico, il problema dovrebbe essere considerato da chiunque codifichi per piattaforme che supportano covarianza e controvarianza (es.)

+0

+1 per aver menzionato la co/controvarianza. – 9000

+0

bel principio - +1 per aiutarmi direttamente con una delle decisioni di progettazione dell'API che mi trovo nel mezzo! – mikera

Problemi correlati