Tieni le mie classi e i miei metodi il più piccoli possibile?

17

Alcuni giorni fa, stavo parlando con un dottorando in Ingegneria del software e ad un certo punto mi ha detto:

Keep your classes and methods as small as possible

E mi chiedo se sia sempre una buona pratica.

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

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

    
posta Florents Tselai 15.12.2011 - 14:13
fonte

7 risposte

21

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

Il granello di verità è che nella pratica, le classi e i metodi tendono sempre a crescere per natura, non a restringere . 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 pulita 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 tramite refactoring . Refactoring produce quasi sempre molte classi / metodi più piccoli da pochi grandi. Ma ovviamente c'è un limite ragionevole alla miniaturizzazione. Il punto di refactoring non è quello di avere classi e metodi più piccoli di per sé, ma per rendere il tuo codice più pulito, più facile da capire e da mantenere . Ad un certo punto, riducendo i tuoi metodi / classi, diminuisci la leggibilità piuttosto che aumentarla. Mirare a quell'ottimale. È un'area di destinazione sfocata e in movimento, quindi non è necessario colpire il punto. Solo migliora il codice un po 'ogni volta che noti qualche problema con esso .

    
risposta data 15.12.2011 - 14:19
fonte
8

Il problema più importante da sottolineare qui è creare buone astrazioni . Classi di piccole dimensioni che sono liberamente accoppiati 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 che i metodi "allegati" a questa classe incapsulino anche su come è possibile manipolare questi attributi e assicurarsi di proteggerli da altre parti del programma modificandoli.

Un altro aspetto positivo della creazione di una classe in questo caso è che la classe può evolvere molto meglio / meglio di una struttura di 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 all'SRP di solito sono molto più facili da capire per un umano rispetto alle classi che non lo fanno.

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

    
risposta data 15.12.2011 - 14:33
fonte
2

Nella programmazione orientata agli oggetti, il principio di responsabilità singola afferma che ogni oggetto dovrebbe avere una singola 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 completamente ok. Non dovresti nominare la classe PairOfInteger. Cosa descrivono gli interi? A seconda del tuo scenario, anche una tupla (come in C #) potrebbe essere sufficiente. E potresti voler pensare a un montante invece di una classe.

Cerca di tenere le lezioni piccole. E i metodi ancora più piccoli. Forse 10 linee?!? Attualmente sto cercando di utilizzare il design del flusso e componenti basati su eventi che sembrano aiutare a mantenere le classi piccole. Per prima cosa ero preoccupato di frequentare molti corsi ma funziona davvero !!! link link

    
risposta data 15.12.2011 - 14:29
fonte
2

Rendi le cose il più semplici possibile, ma non più semplici. Questa è la regola che cerco di seguire. A volte, per una classe è effettivamente logico fare ciò che in senso stretto 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, ciascuna con la propria lista 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 ulteriori 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 gestibile rispetto a quello breve, a parità di altri, prenderò quello lungo ogni giorno.)

Solo "rendere le classi e i metodi il più piccoli possibile" è, a mio avviso, fuorviato. La vera sfida è, come sottolinea @c_maker, fornire buone astrazioni. Il tuo esempio di raggruppare due numeri insieme è ottimo, ad esempio, se stai lavorando su un'implementazione di numeri complessi aritmetici, o se su un sistema Unix devi fare riferimento a un contesto utente / di gruppo. Ha molto poco senso se i numeri rappresentano, ad esempio, un ID fattura e un ID prodotto da aggiungere a quella fattura.

    
risposta data 15.12.2011 - 14:51
fonte
1

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

    
risposta data 15.12.2011 - 14:21
fonte
0

Questo è un consiglio OK, ma deve essere implementato in qualche modo in modo intelligente. Sicuramente non seguirlo ciecamente.

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

Ecco un buon esempio: hai un ciclo e hai forse 60 linee di codice in quel metodo. In quel 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.

    
risposta data 15.12.2011 - 14:46
fonte
0

Lo zio Bob dice che dovresti rifattorici / dividi / estrai i tuoi metodi finché non è impossibile renderli più piccoli . Questo di solito finisce con diversi metodi con 3 o 4 linee ciascuno. Quando ottieni troppi metodi, devi fare più lezioni.

Se provi a seguire SRP e un livello di astrazione per metodo, queste regole ti servono bene. Almeno loro mi servono bene. Mirare a "il più piccolo possibile" mi dà dei metodi ragionevoli, poiché di solito non raggiungo l'obiettivo.

Ed è sempre più facile capire classi più piccole. Vai avanti, leggi "Pulisci codice"

    
risposta data 17.12.2011 - 00:22
fonte

Leggi altre domande sui tag