Da un principi SOLID prospettiva la risposta di jgauffin ha senso. Tuttavia, non dovresti dimenticare i principi generali di progettazione, ad es. nascondere le informazioni .
Vedo diversi problemi con l'approccio dato:
- Come hai sottolineato tu stesso, le persone non si aspettano di utilizzare la parola chiave "nuova", quando l'oggetto creato non gestisce nessuno stato . Il tuo design riflette la sua intenzione. Le persone che utilizzano la tua classe potrebbero confondersi su quale stato gestisce e se le successive chiamate al metodo potrebbero comportare un comportamento diverso.
- Dal punto di vista della persona che usa la classe, lo stato interiore è ben nascosto, ma quando vuoi apportare modifiche alla classe o semplicemente comprenderla, stai rendendo le cose più complesse. I hanno già scritto molto sui problemi che vedo con i metodi di suddivisione solo per renderli più piccoli , specialmente quando si sposta lo stato sull'ambito della classe. Stai modificando il modo in cui la tua API dovrebbe essere utilizzata solo per avere funzioni più piccole! che a mio avviso sta decisamente prendendo troppo.
Alcuni riferimenti correlati
Forse un punto di discussione principale sta nella misura in cui estendere il principio di responsabilità singola . "Se lo porti a quell'estremo e costruisci classi che hanno una ragione per esistere, potresti finire con un solo metodo per classe. Ciò causerebbe una grande dispersione di classi anche per i processi più semplici, causando sistema difficile da capire e difficile da modificare. "
Un altro riferimento pertinente relativo a questo argomento: "Dividi i tuoi programmi in metodi che eseguono un'attività identificabile. Mantieni tutte le operazioni in un metodo su lo stesso livello di astrazione ." - Kent Beck La chiave qui è "lo stesso livello di astrazione". Ciò non significa "una cosa", poiché viene spesso interpretata. Questo livello di astrazione dipende interamente dal contesto per il quale stai progettando.
Quindi qual è l'approccio corretto?
Senza conoscere il tuo caso d'uso concreto è difficile dirlo. C'è uno scenario in cui a volte (non spesso) uso un approccio simile. Quando voglio elaborare un set di dati, senza voler rendere questa funzionalità disponibile per l'intero ambito di classe. Ho scritto un post sul blog, come lambdas può migliorare ulteriormente l'incapsulamento . I hanno anche avviato una domanda sull'argomento qui su Programmers . Quello che segue è un ultimo esempio di dove ho usato questa tecnica.
new TupleList<Key, int>
{
{ Key.NumPad1, 1 },
...
{ Key.NumPad3, 16 },
{ Key.NumPad4, 17 },
}
.ForEach( t =>
{
var trigger = new IC.Trigger.EventTrigger(
new KeyInputCondition( t.Item1, KeyInputCondition.KeyState.Down ) );
trigger.ConditionsMet += () => AddMarker( t.Item2 );
_inputController.AddTrigger( trigger );
} );
Poiché il codice molto "locale" all'interno di ForEach
non viene riutilizzato da nessun'altra parte, posso semplicemente tenerlo nella posizione esatta in cui è rilevante. Delineare il codice in modo tale che il codice che si affida a vicenda è strongmente raggruppato insieme rende più leggibile a mio parere.
Possibili alternative
- In C # è possibile utilizzare invece i metodi di estensione. Quindi agisci sull'argomento direttamente passerai a questo metodo 'una cosa'.
- Verifica se questa funzione in realtà non appartiene a un'altra classe.
- Rendi una funzione statica in una classe statica . Questo è probabilmente l'approccio più appropriato, come si riflette anche nelle API generali a cui ti sei riferito.