Come evitare i nomi generali per le classi astratte?


10

In generale è bene evitare parole come "handle" o "process" come parte dei nomi di routine e dei nomi di classe, a meno che non si abbia a che fare con (ad esempio) handle di file o (ad esempio) processi unix. Tuttavia le classi astratte spesso non sanno davvero cosa faranno con qualcosa oltre a, diciamo, elaborarlo. Nella mia situazione attuale ho un "EmailProcessor" che accede alla posta in arrivo di un utente ed elabora i messaggi da esso. Non è molto chiaro per me come dare a questo un nome più preciso, anche se ho notato la seguente questione di stile:

  • meglio trattare le classi derivate come client e nominare la classe base dalla parte della funzionalità che implementa? Dà più significato ma violerà is-a. Ad esempio EmailAcquirer sarebbe un nome ragionevole poiché sta acquisendo per la classe derivata, ma la classe derivata non sarà acquisita per nessuno.
  • O solo un nome davvero vago da chissà cosa faranno le classi derivate. Tuttavia, "Processore" è ancora troppo generico poiché sta eseguendo molte operazioni rilevanti, come l'accesso e l'uso di IMAP.

Qualche via d'uscita da questo dilemma?

Il problema è più evidente per i metodi astratti, in cui non si può veramente rispondere alla domanda "cosa fa questo?" perché la risposta è semplicemente "qualunque cosa il cliente desideri".


Hai una fonte (e qualche contesto) per quell'affermazione "in generale"? Inoltre, un'ulteriore regola di denominazione per l'elenco - non perdere tempo alla ricerca di un nome perfetto che probabilmente non esiste. In caso di dubbio, assegnagli il nome migliore che puoi, aggiungi una descrizione più lunga come commento in cui è definita se necessario, ma puoi sempre rifattorizzare in seguito se a qualcuno non piace la tua scelta o il nome perfetto ti appare all'improvviso quando " stai facendo qualcos'altro.
Steve314,

3
@ Steve314 - sì, Steve McConnell, Codice completo, 1a edizione, capitolo 4 o 5 sulle routine. Ampia discussione sulla denominazione in questi capitoli, essenzialmente concludendo che se non hai un buon nome probabilmente non hai una buona funzione.
djechlin,

non riuscire a trovare un buon nome può sembrare un brutto segno, ma IMO dovresti sapere se la funzione è cattiva in base alla funzione stessa. Il refactoring solo perché la lingua inglese non è stata progettata su misura per il tuo progetto è un po 'stupido. No, non è un problema di tutti i giorni, ma hai già deciso di avere un problema.
Steve314,

1
@ Steve314 La programmazione riguarda interamente la gestione della complessità e se il tuo cervello non riesce a trovare una parola per qualcosa, c'è una buona possibilità che non sia in grado di gestirne la complessità quando deve fare cose come usarlo in frasi più grandi o come parte di sistemi più grandi. In realtà non è un'affermazione audace dire che l'incapacità di trovare un buon nome è una grande causa di pausa per preoccupazione. Ma questo è ampiamente discusso in McConnell, consiglierei di leggere quei due capitoli almeno sebbene l'intero libro valga la pena leggere da copertina a copertina.
Djechlin,

le affermazioni nel Codice completo non devono essere necessariamente attendibili. Sono consapevole della reputazione libri, ma sono anche consapevole di questo . Inoltre, gestisco la complessità perfettamente bene da anni - gli errori accadono, di uso comune, ma quando le cose vanno male, a volte il problema è una funzione che è così semplice che ovviamente non può essere sbagliato, ma lo è comunque .
Steve314,

Risposte:


10

Il problema non è il nome, ma che stai mettendo troppo in una classe.

Nella tua classe di esempio, alcune parti sono molto concrete (come saranno ottenute le mail). Altre parti sono molto astratte (cosa farai con le mail).

Meglio farlo con classi separate, piuttosto che con l'eredità.

Suggerisco:

  • un MessageIterator astratto, sottoclassato da un POPMailBoxDownloader

  • un'altra classe che PROPRIETÀ un POPMailBoxDownloader e fa qualcosa con i messaggi.


Sembra esattamente giusto. Sembra che se ti trovi a nominare qualcosa di "processEvent" o una classe "MessageProcessor", ci sono buone probabilità che tu abbia potuto progettare sulla composizione anziché sulla derivazione. In questo caso è un compromesso, dal momento che i manutentori possono essere utili ma un cliente sarebbe infastidito chiedendosi esattamente cosa fa ogni funzione (più del manutentore).
djechlin,

6

Se non riesco a trovare un buon nome per una classe, scrivo una documentazione del codice in linea per la classe. Descrive lo scopo della classe in un solo profumo. Di solito posso derivare un buon nome per la classe da questa descrizione. Questo è utile anche per le classi astratte.

Se la descrizione della classe è "Accede alla posta in arrivo di un utente ed elabora i messaggi da essa", suggerirei "InboxProcessor" come nome della classe. Se una classe derivata ha "Accede alla posta in arrivo di un utente e sposta l'e-mail di spam in una cartella spam" come descrizione, sceglierei "InboxSpamMover" come nome.

Non vedo un problema quando si usano nomi generici come "processore" se riflette lo scopo generico di una classe astratta.

Se hai problemi a descrivere lo scopo di una classe in uno o due profumi, allora potresti avere un problema di progettazione. Forse la classe sta facendo troppo e viola il principio della responsabilità singola . Questo vale anche per le classi astratte.


2

Per parafrasare Frank Zappa, è quello che è e dovrebbe essere chiamato così. Il tuo esempio non scava abbastanza in profondità nel tipo di elaborazione in corso. È un EmailToTroubleTicketProcessor, un EmailGrammarCorrectoro un EmailSpamDetector?

Il problema è più evidente per i metodi astratti, in cui non si può veramente rispondere alla domanda "cosa fa questo?" perché la risposta è semplicemente "qualunque cosa il cliente desideri".

Questo non è esattamente vero; la domanda a cui non puoi rispondere per qualcosa di astratto è " come fa quello che fa?" perché è specifico dell'implementazione. Se una EmailSenderclasse ha un DeliveryStatus deliver(Email e)metodo, esiste un contratto implicito secondo cui un'implementazione richiederà un'e-mail, prova a consegnarla e restituisce un certo stato su come è andata. Non ti importa se si connette a un server SMTP o lo stampa per essere legato a un piccione viaggiatore purché l'implementazione faccia ciò che è stato promesso. Gli abstract semplicemente quantificano quella promessa, quindi un'implementazione può dire "sì, lo faccio".


Che dire di quando la funzione fine è in un certo senso terminale, quindi la classe astratta sta dicendo "e qui, fai quello che vuoi?" ad esempio, il metodo non ha accesso allo stato, tipo di ritorno vuoto, no-throw.
djechlin,

È sempre la stessa cosa. Anche se il tuo metodo è void doWhatYouDoWith(Email e), potresti comunque chiamare la classe an EmailDisposer, che è abbastanza specifica da dire cosa fa ma abbastanza generale da come dipende l'implementazione. Anche se penso che @KrisVanBael l'abbia inchiodato: se hai fatto ricorso a qualcosa di così ambiguo, potrebbe esserci troppo sotto lo stesso tetto.
Blrfl,

0

Pensa al motivo per cui è male usare tali parole. Sono descrittivi? Quali parole ci sono per descrivere le lezioni? EmailBaseClass? Potrebbe essere più descrittivo di dire EmailManager o qualcosa di simile? La chiave è avere una visione della classe in questione, quindi trova verbi o nomi propri. Tratta il tuo codice come se fosse poesia.


"EmailBaseClass" sarebbe come nominare int age"ageInteger", anche peggio dato che mi aspetterei di derivare e-mail di testo, e-mail MIME ecc. Da esso. Non c'è bisogno di descrivere ciò che è preceduto dalla parola abstractin primo luogo (questo è Java). Hai qualche idea particolare per la parte base di questa classe? E ulteriori intuizioni non risolvono ancora il problema di nominare qualcosa che sta per attraversare una relazione is-a, posso avere qualcosa di troppo vago o troppo generale, non vedo una via d'uscita a meno che se non lo avessi più intuizione per avere più intuizione.
Djechlin,

@djechlin - ci sono rari casi in cui ageIntegero qualcosa del genere è effettivamente appropriato. La notazione ungherese è una versione abbreviata di un contesto in cui è successo molto. Certamente, ci sono momenti in cui potresti aver bisogno di qualcosa sulla falsariga ageNumerice ageStringnello stesso ambito, con un'indicazione del tipo nel nome che è il modo più semplice e chiaro per chiarire le ambiguità.
Steve314,

@djechlin Personalmente trovo che sia più semplice lavorare con il codice a cui posso dare un'occhiata per capire. Cioè, i nomi mi dicono con cosa sto lavorando. Non c'è bisogno di sapere se systemControllerè una classe base astratta o una foglia in una gerarchia enorme. Ovviamente questo può essere risolto con IDE (come immagino sia il caso della maggior parte dello sviluppo Java?) Che può immediatamente informare l'utente sui contenuti e sulla struttura della classe, quindi in realtà nomi insight non possono essere giustificati in modo simile.
zxcdw,
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.