Wrappers di funzioni senza argomenti: cattiva pratica?

3

Il mio collega ama scrivere classi contenenti metodi simili a questo:

public function doTaskA()
{
    return $this->doTask('A');
}
public function doTaskB()
{
    return $this->doTask('B');
}
private function doTask($task)
{
    ...

Dico che è una cattiva pratica e preferirei semplicemente rendere pubblico il metodo doTask. Penso che se senti davvero che è necessario codificare i possibili valori di $ task nella classe, quindi basta renderli costanti di classe e chiamare doTask (self :: TASK_A) piuttosto che scrivere una nuova funzione puramente come wrapper.

Il caso peggiore che ho visto di questo, era una classe con più di una dozzina di questi wrapper, e il metodo doTask era lungo appena una ventina di righe.

Quindi, questa è in realtà una cattiva pratica? O è solo una questione di stile? O mi sbaglio, e in realtà è considerata una pratica buona , come insiste?

    
posta Benubird 01.06.2015 - 09:51
fonte

4 risposte

4

Dipende dagli scenari.

Chiamate identiche multiple

Considera di dover eseguire una determinata attività più volte nel tuo codice. Fare foo.doTask(args) potrebbe diventare noioso. Dover fornire gli argomenti ogni volta, può anche essere soggetto a errori. Avere un involucro che lo avvolge per te può essere conveniente e anche meno incline agli errori. Inoltre, immagina se devi cambiare il valore di uno degli argomenti in quella funzione, dovrai passare tutte le chiamate e apportare più modifiche. L'utilizzo dell'approccio wrapper significherà che la modifica sarà localizzata.

Più chiamate leggermente diverse

Dall'altra parte dello spettro, avere un sacco di wrapper leggermente diversi, uno per ogni tipo possibile, può produrre troppi wrapper che alla fine confondono l'utente della tua API. Cambiare il codice potrebbe essere fonte di confusione, dal momento che potresti non essere così sicuro di ciò che desideri cambiare.

In entrambi i casi però, i wrapper dovrebbero essere utili se devi fornire un accesso controllato ai tuoi metodi, quindi è un'altra cosa che dovresti tenere a mente.

    
risposta data 01.06.2015 - 10:02
fonte
4

Questa non è una cattiva pratica. Sovraccaricare un singolo metodo per fare cose diverse a seconda dei parametri è in realtà un antipattern. Se diverse stringhe portano a un comportamento diverso, è buona norma creare metodi distinti.

Eg.

x.deleteFile()
x.sendMail()

è un'interfaccia molto migliore di

x.doTask("DeleteFile")
x.doTask("SendMail")

anche se chiamano internamente lo stesso metodo privato. Questo fatto è un dettaglio di implementazione che dovrebbe essere incapsulato.

Considera gli aspetti negativi della seconda soluzione:

  • non puoi aggiungere parametri a una delle attività in futuro.
  • non è possibile modificare in modo sicuro il nome di un'attività
  • non puoi ispezionare il codice per vedere dove viene utilizzata la funzionalità "SendMail"
  • errori ortografici non verranno rilevati dal compilatore ma causeranno il fallimento del programma in fase di runtime.
  • stai creando un "metodo divino" che è un antipattern perché infrange il principio di responsabilità singola e il principio di alta coesione / basso aggancio.
  • non puoi facilmente vedere quali compiti supporta il "metodo-dio".
  • non è possibile separare l'interfaccia secondo i principi SOLID, il che significa che non è possibile eseguire l'override o fornire un'implementazione alternativa di "DeleteFile" senza fornire un'alternativa all'implementazione di "SendMail".

Quindi dovresti assolutamente ascoltare il tuo collega e considerare attentamente i suoi punti di vista!

    
risposta data 01.06.2015 - 18:57
fonte
3

Non direi che questa è una cattiva pratica come regola generale, ma si distingue dalle pratiche di programmazione flessibile come l'uso di Iniezione di dipendenza .

Se le "dipendenze" di una classe o funzione possono essere passate come argomenti, rendono la classe / funzione più riutilizzabile, più facile da refactoring e meno una scatola nera per il programmatore che deve usare la classe . Ho scoperto che aderire a questo stile attraverso un progetto porta a un codice flessibile e gestibile.

Non dire mai mai o sempre in programmazione, ma penso che tu possa fare una ragione ragionevole per allontanare i colleghi da questo stile di codifica.

Anche l'argomento di npinti è valido. Se ti ritrovi a chiamare la stessa funzione con gli stessi parametri più e più volte, e un contenitore IoC (vedi l'iniezione delle dipendenze sopra) non può fare questo lavoro per te, quindi potresti volerli avvolgere con una funzione dedicata, anche se il nome dovrebbe indicare chiaramente che si tratta di una variazione sulla funzione più generale che accetta i parametri.

    
risposta data 01.06.2015 - 11:01
fonte
1

The worst case I saw of this, was a class with more than a dozen of these wrappers, and the doTask method was barely twenty lines long.

Penso che questo abbia bisogno di un indirizzamento migliore rispetto al problema dell'utilizzo di wrapper di funzioni, che come sottolineato dalle altre risposte tendono ad avere più vantaggi che svantaggi.

Supponendo che hai bisogno di almeno una riga per argomento del metodo in doTask($task) , qualcosa di simile di seguito:

// PHP I think?
private function doTask($task)
{
    // ...
    if ($task === 'A') actuallyDoTaskA();
    if ($task === 'B') actuallyDoTaskB();
    // ...
}

doTask() ora diventa più di un ostacolo dal momento che è semplicemente delegare chiamate ad altri metodi, che avrebbero dovuto essere chiamati da doTaskA()/doTaskB() in primo luogo.

In conclusione, tali wrapper di funzioni possono rivelarsi utili se si desidera rendere coerenti gli argomenti utilizzati nella base di codici, oppure se vengono utilizzati in modo da ridurre la duplicazione del codice (ad esempio sostituzioni di valori diversi per la formattazione delle stringhe dai chiamanti). Tuttavia, se il metodo sottostante chiamato diventa un altro 'function wrapper' di per sé , dovresti prendere in considerazione la possibilità di rimuovere un livello ... preferibilmente il metodo sottostante.

    
risposta data 02.06.2015 - 02:53
fonte

Leggi altre domande sui tag