Mantenere le mie classi e metodi il più piccolo possibile?


20

Qualche giorno fa, stavo parlando con un dottorando in Ingegneria del Software e ad un certo punto mi disse:

Mantieni le classi e i metodi il più piccolo possibile

E mi chiedo se questa è sempre una buona pratica.

Voglio dire, ad esempio, è degno di avere una classe con solo 2 attibutes? Ad esempio, in alcuni metodi ho bisogno di coppie di numeri interi con cui lavorare. Devo scrivere una classe "PairOfIntgers"?

Questo modo di pensare potrebbe "spezzare" il codice in troppi pezzi?


10
Dovrebbe essere"As small as possible, but no smaller."
StuperUser il

"Voglio dire, ad esempio, è degno di avere una classe con solo 2 attibutes?" - Può essere, cerca "Primitive Obsession" (ad esempio jamesshore.com/Blog/PrimitiveObsession.html )
Torsten,

Penso che la fonte di confusione sia la parola "possibile". Il principio diventa ridicolo se "possibile" si riferisce solo al codice, perché la classe più piccola possibile che fa qualcosa di utile ha un solo metodo (e in alcuni casi zero). Molto probabilmente il candidato intendeva prendere in considerazione la coesione e l'accoppiamento.
Kelvin,

Risposte:


23

C'è un granello di verità in quel consiglio, ma IMHO non è molto ben espresso, quindi facile fraintendere e / o portare a un estremo stupido. In ogni caso, questa dovrebbe essere una regola empirica, piuttosto che una legge dura. E dovresti sempre implicare in tali regole la clausola "entro limiti ragionevoli" , o "ma non dimenticare di usare il tuo buon senso" :-)

Il grano della verità è che in pratica, classi e metodi tendono sempre a crescere per natura, non a ridursi . Una correzione di bug qui, una piccola estensione di funzionalità lì, la gestione di un caso speciale laggiù ... e voilà, la tua classe una volta ordinata e piccola inizia a gonfiarsi. Nel corso del tempo, il tuo codice tende quasi inevitabilmente a diventare un mostruoso casino di spaghetti, a meno che tu non combatta attivamente questa tendenza attraverso il refactoring . Il refactoring produce quasi sempre molte classi / metodi più piccoli da alcuni grandi. Ma ovviamente c'è un limite ragionevole alla miniaturizzazione. Il punto di refactoring non è avere classi e metodi più piccoli in sé, ma rendere il codice più pulito, più facile da capire e mantenere. A un certo punto, la riduzione dei metodi / delle classi inizia a ridurre la leggibilità anziché aumentarla. Puntare a quello ottimale. Si tratta di un'area bersaglio sfocata e in movimento, quindi non è necessario colpirla sul punto. Basta migliorare il codice un po 'ogni volta che si nota qualche problema con esso .


1
sicuramente una regola da non seguire alla cieca, troppe classi minuscole sono molto peggio di alcune classi più grandi per la maggior parte del tempo.
Ryathal,

4
La mia regola empirica personale è: se non riesci a vedere l'implementazione di un intero metodo sullo schermo in una sola volta, refactor.
Dan Ray,

6
@DanRay, sì, avevo la stessa regola, fino a quando non ho letto Clean Code . Fu un vero shock, ma gradualmente il mio ottimale scese a circa 10 righe.
Péter Török,

2
Il codice pulito IMO è orribile nella sua estremità verso piccoli metodi. Il problema è che quando i metodi vengono ridotti, ce ne saranno più. Naturalmente i metodi troppo lunghi sono troppo lunghi, ma Bob Martin sembra preferire 10 metodi a 1 riga su 1 a 10 righe (quindi lo stesso codice effettivamente occupa circa 5 volte lo spazio dello schermo). Forse è pensato per essere una sorta di trucco educativo, non posso credere che qualcuno pensi davvero che il codice in quel libro sia buono.
Joonas Pulakka,

5
@JoonasPulakka - Diciamo solo che non ho mai letto un metodo e ho pensato: "Vorrei che questo metodo facesse di più". Abbreviando i metodi è possibile scrivere nomi di metodi molto descrittivi che spesso possono eliminare la necessità di leggere interamente il corpo del metodo. Ho trovato i consigli in Clean Code molto sensibili. Dovremo solo concordare di non essere d'accordo. :)
David Harkness,

9

Il problema più importante da sottolineare qui è la creazione di buone astrazioni . Piccole classi che sono accoppiate liberamente e hanno un'elevata coesione sono il prodotto di buone astrazioni .

A volte ha perfettamente senso incapsulare due numeri interi in una classe. Soprattutto se si desidera avere metodi "collegati" a questa classe per incapsulare anche il modo in cui si possono manipolare questi attributi e assicurarsi di proteggerli da altre parti del programma modificandoli.

Un altro aspetto positivo nel creare una classe in questo caso è che la classe può evolversi molto meglio / meglio di una struttura dati di livello inferiore come una mappa o una lista.

In terzo luogo, una buona astrazione può migliorare notevolmente la leggibilità. Le classi che aderiscono a SRP sono in genere molto più facili da capire da un essere umano rispetto alle classi che non lo fanno.

E proprio come nota finale ... non importa quanto tu sia bravo in uno studente ... per capire OOP e buone astrazioni e quando usarle, hai bisogno di esperienza. Devi scrivere un codice errato e superare il dolore per mantenerlo. Devi vedere gli altri scrivere un buon codice per accrescere le tue conoscenze su ciò che è "buono" e quale sarà un problema lungo la linea ... Quindi non picchiarti se non lo capisci subito.


2

L'anti-pattern di God Object è ciò a cui probabilmente alludeva. Tendo a pensare che se ho un "e" nella descrizione della mia classe, dovrei avere due classi. Se ho più di dieci righe di codice in un metodo / funzione, allora dovrei romperlo. Come codice pirata, quelli sono più linee guida che regole.


2

Nella programmazione orientata agli oggetti, il principio della singola responsabilità afferma che ogni oggetto dovrebbe avere un'unica responsabilità e che la responsabilità dovrebbe essere interamente incapsulata dalla classe. Di solito stai facendo più di una cosa se la tua classe diventa troppo grande. Nel tuo caso la classe è solo una classe di dati che contiene dati che sono totalmente ok. Non dovresti dare un nome alla classe PairOfInteger. Cosa descrivono gli interi? A seconda del tuo scenario potrebbe essere sufficiente anche una Tupla (come in C #). E potresti voler pensare a un puntone invece che a una classe.

Cerca di tenere le lezioni piccole. E metodi ancora più piccoli. Forse 10 linee?!? Attualmente sto cercando di utilizzare la progettazione del flusso e componenti basati su eventi che sembrano aiutare a contenere le classi piccole. Prima ero preoccupato di frequentare molte lezioni ma funziona davvero !!! http://geekswithblogs.net/theArchitectsNapkin/archive/2011/03/19/flow-design-cheat-sheet-ndash-part-i-notation.aspx http://geekswithblogs.net/theArchitectsNapkin/archive/2011/03 /20/flow-design-cheat-sheet-ndash-part-ii-translation.aspx


2

Rendi le cose il più semplici possibile, ma non più semplici. Questa è la regola che cerco di seguire. A volte, in realtà ha senso che una classe faccia ciò che, a rigor di termini, equivale a più di una cosa, se queste cose sono correlate su un tema comune . Guarda .NET; ci sono tonnellate di classi che implementano un gran numero di interfacce, ognuna con il proprio elenco di membri richiesti. Un metodo potrebbe finire per diventare un po 'lungo se fa qualcosa di complesso con una serie di passaggi intermedi che sono tutti interconnessi e quindi non si prestano molto bene a un ulteriore refactoring. (Il refactoring per mantenere i metodi brevi dovrebbe in definitiva riguardare la leggibilità e la manutenibilità; se il metodo lungo è più leggibile e / o mantenibile di un metodo breve, tutto sommato uguale, prenderò quello lungo ogni giorno.)

Secondo me, "rendere le classi e i metodi il più piccoli possibile" è fuorviante. La vera sfida è, come sottolinea @c_maker, fornire buone astrazioni. Il tuo esempio di raggruppamento di due numeri insieme è ottimo, ad esempio, se stai lavorando su un'implementazione di aritmetica di numeri complessi o se su un sistema Unix devi fare riferimento a un contesto utente / gruppo. Non ha molto senso se i numeri rappresentano, per esempio, un ID fattura e un ID prodotto da aggiungere a quella fattura.


0

Questo è un consiglio OK, ma deve essere implementato in modo piuttosto intelligente. Sicuramente non seguirlo alla cieca.

Quando guardo il mio codice so se un metodo è troppo grande. Se sta facendo troppo, e sarebbe troppo difficile da leggere, allora è tempo di rifrattore.

Ecco un buon esempio: hai un ciclo e forse hai 60 righe di codice in quel metodo. In tal caso, è probabilmente il momento di refactoring perché probabilmente stai facendo troppo in quel metodo.

Ma non è una regola dura e veloce. È solo qualcosa che puoi imparare facendo. E, altri sviluppatori con cui lavori non sono sempre d'accordo e potrebbero chiamarti in una revisione del codice o altro.


Mai più piccoli metodi piuttosto seguire SRP e farà automaticamente il lavoro.
Vinay Prajapati,

0

Lo zio Bob dice che dovresti riformattare / dividere / estrarre i tuoi metodi fino a quando è impossibile renderli più piccoli . Questo di solito termina con diversi metodi con 3 o 4 righe ciascuno. Quando ottieni troppi metodi, devi creare più classi.

Se si tenta di seguire SRP e un livello di astrazione per metodo, queste regole sono utili. Almeno mi servono bene. Puntare su "il più piccolo possibile" mi dà metodi piccoli ragionevoli, poiché di solito non riesco a raggiungere l'obiettivo.

Ed è sempre più facile capire le classi più piccole. Vai avanti, leggi "Clean Code"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.