Argomenti di campi e metodi [chiuso]


9

Ho appena iniziato a scrivere qualche nuova classe e mi è venuto in mente che stavo aggiungendo molti argomenti di metodo che non sono strettamente necessari. Questo sta seguendo l'abitudine di evitare di avere uno stato in classi specifico per una chiamata al metodo, piuttosto che essere una configurazione generale o dipendenze della classe.

Ciò significa che molti metodi che potrebbero non avere argomenti finiscono con uno, due o tre.

Mi piacerebbe sentire le tue opinioni su ciò che pensi di questo compromesso e su come decidere quale approccio adottare in quale situazione?

Dato che il codice è spesso più facile da capire dell'inglese quando si descrive il codice, ho creato un piccolo riassunto che ha entrambe le varianti: https://gist.github.com/JeroenDeDauw/6525656


Gli argomenti che vengono utilizzati solo come variabili locali (non globali per la durata dell'oggetto) devono essere compresi solo se ha senso ... Lo trovo molto irritante quando gli sviluppatori memorizzano lo stato di non istanza come stato di istanza perché è conveniente ... Solo la mia opinione però. Rende difficile vedere come è effettivamente il flusso di esecuzione.
Max

Usando i parametri e lasciando che la classe si occupi se potrebbe essere necessario cambiare stato durante l'esecuzione di un metodo, si lega bene al principio "non chiedere" . Tieni solo presente che Tell non chiede non significa che non puoi interrogare un oggetto sul suo stato ( spina palese )
Marjan Venema,

Risposte:


2

Poiché l'unico metodo visibile esternamente del tuo esempio è updateTable, penso che sia giusto usare i campi invece dei parametri del metodo.

Se questo fa parte di una classe più generica (ad es. TableTools), Sposterei i metodi di supporto che richiedono lo stato in una classe interna nascosta.

Esempio di pseudo-codice:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

In questo modo, si evitano i campi utilizzati da un solo metodo pubblico. Inoltre, il codice è thread-safe, nel senso che ogni chiamata a updateTable utilizza la propria copia di TableUpdater e, quindi, delle variabili di istanza di TableUpdater.


7

L'uso dei campi coopt la capacità di avere il multithreading disponibile per i metodi che usano quei campi.

L'uso di campi come quello è solo leggermente migliore rispetto all'utilizzo dei globuli dal punto di vista della riusabilità e della manutenibilità, il punto chiave qui è che configurazioni complesse richiedono una documentazione attenta e aggiornata su quali metodi utilizzano e / o clobber quali campi; qualcosa che non devi fare quando usi gli argomenti.


Il multithithreading non è rilevante per il mio caso d'uso, come lo è in PHP. Sono d'accordo che questo approccio è negativo se il modo in cui i campi vengono utilizzati non è banale. In questo caso vengono scritti solo (e sempre scritti) dall'unico metodo pubblico. Non prevedo che ciò causi problemi. Per quanto riguarda i campi come questo è solo leggermente migliore dei globali, non sono abbastanza sicuro di cosa tu voglia dire. Puoi elaborare?
Jeroen De Dauw,

7

Nelle parole di laici:

  • i metodi dovrebbero avere il minor numero di argomenti possibile (Martin's Clean Code)
  • una delle caratteristiche degli oggetti è che possono (e dovrebbero) avere uno stato
  • i metodi non statici che non operano sullo stato dell'oggetto, cioè che ricevono tutto come parametri, non sono coerenti
  • metodi non coerenti potrebbero anche essere resi statici e raggruppati in una classe di utilità

Ancora una volta, a mio modesto parere, i metodi non coerenti appartengono a una classe di utilità e non a una classe con un nome di dominio.


1

Non utilizzare i campi nel caso corrente! Due "thread" che utilizzano contemporaneamente l'oggetto si confondono seriamente. Non devono essere nemmeno discussioni reali e separate (da cui le virgolette). Se si imposta l'oggetto per una tabella, quindi si chiama un metodo che lo utilizza per un'altra tabella, quindi si tenta di utilizzare l'impostazione originale, si verifica un problema. Attenersi ai parametri per il momento.

Quello che vuoi fare qui è creare una nuova classe di aggiornamento che viene utilizzata in un solo caso. La classe originale potrebbe avere un metodo per creare un'istanza ogni volta che è necessario. La nuova classe avrebbe campi. Hai il meglio di entrambi i mondi. A volte è più semplice attenersi ai parametri, ma nel tuo esempio stai già arrivando dove sarebbe meglio una classe separata.


0

Penso che la scelta dovrebbe essere in base alla situazione reale, come la vedi tu. Se un elemento appartiene a un'istanza, dovrebbe essere visto come il suo campo. Se l'elemento è esterno all'istanza, deve essere passato come parametro del metodo.

In questo caso dovremmo essere guidati non dall'efficacia (la differenza è insignificante in ogni caso), o dalla (facilità di Dio!) Della digitazione, ma dalla comprensibilità e dalla naturalezza del codice.


0

Secondo me se stai scrivendo codice che fa qualcosa a qualcosa, allora dovrebbe prendere parametri che definiscono a cosa le cose dovrebbero fare e il suo nome dovrebbe definire il più possibile ciò che gli fa.

Se stai scrivendo un codice che impacchetta un'azione da eseguire su qualcosa , dovresti avvolgere le cose su cui dovrebbe essere eseguito in un oggetto e passarle alla tua cosa che fa qualcosa .

Questa azione diventa quindi una sorta di meta-descrizione delle chiamate ai metodi del primo che puoi quindi eseguire in un secondo momento accodandolo o addirittura decidere di non farlo affatto per qualche motivo.

Quindi la tua domanda si traduce in è un'azione o di una funzione ? Un'azione potrebbe essere posticipato o cancellato e quindi dovrebbe incapsulare ciò che agisce su. Una funzione si verifica immediatamente, quindi non è necessario preservarne i parametri.

È possibile annullare e Azione ma non una Funzione .

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.