Devo ripetere il codice di controllo delle condizioni o inserirlo in una funzione? [duplicare]

4

Ho un sacco di chiamate a un metodo che può o non può essere necessario a seconda se determinate funzionalità sono abilitate o meno. Come tale, ho spostato queste chiamate in if blocchi controllando gli stati abilitati.

Gli argomenti del metodo in ciascuna di queste chiamate utilizzano alcuni nomi di variabili lunghe, quindi li ho suddivisi in righe diverse per la leggibilità / aderire al nostro standard di codifica della lunghezza della linea.

Questi grandi blocchi di chiamata metodo, combinati con i controlli delle condizioni per vedere se devono essere eseguiti (esacerbati dal mandato che includiamo tutti i blocchi if in parentesi), sono piuttosto rumorosi.

Quindi ho qualcosa del genere:

if (FeatureSettings.FeatureXIsEnalbed)
{
    this.TheMethodImCalling(
        FeatureSettings.ReallyLongFeatureXSettingAName,
        FeatureSettings.ReallyLongFeatureXSettingBName,
        ...);
}

if (FeatureSettings.FeatureYIsEnalbed)
{
    this.TheMethodImCalling(
        FeatureSettings.ReallyLongFeatureYSettingAName,
        FeatureSettings.ReallyLongFeatureYSettingBName,
        ...);
}

if (FeatureSettings.FeatureZIsEnalbed)
{
    this.TheMethodImCalling(
        FeatureSettings.ReallyLongFeatureZSettingAName,
        FeatureSettings.ReallyLongFeatureZSettingBName,
        ...);
}

Per ridurre il rumore e la ridondanza in questo codice, stavo pensando di prendere la struttura di blocchi if e metterla dentro TheMethodImCalling , quindi passare il valore ...IsEnabled insieme al resto degli argomenti.

Questo sembra un po 'sciocco, visto che chiamerei il metodo e dire "Non fare niente". quando una funzione non è stata abilitata.

Ora, potrei probabilmente rendere il codice un po 'più leggibile assegnando le impostazioni lunghe a variabili temporanee più corte o persino a campi di una classe Arguments che poi passerò al metodo, ma quelli non indirizzano il core domanda:

Devo ripetere la condizione di controllo del codice o inserirla nella funzione?

O c'è un'alternativa che dovrei considerare? (Entrambe le opzioni sembrano un po 'puzzolenti ...)

    
posta paul 19.07.2013 - 17:22
fonte

4 risposte

4

Di solito quando qualcosa si sente così imbarazzante, è perché hai bisogno di rifattorizzare i tuoi oggetti per allocare più logicamente le responsabilità. Se ne hai una manciata, la mia preferenza personale sarebbe metterli in una lista e chiamarli così:

for feature in enabledFeatures:
    feature.process()

In questo modo non stai nemmeno perdendo un controllo condizionale sulle funzionalità disabilitate, che è particolarmente utile quando il rapporto tra le funzioni disabilitate e quelle abilitate è elevato.

    
risposta data 19.07.2013 - 18:04
fonte
1

Potresti non avere una scelta qui: se valutando la proprietà ReallyLongFeatureZSettingAName quando FeatureSettings.FeatureZIsEnalbed equivale a false si traduce nel lancio di un'eccezione, l'idea di passare il "guarding" FeatureSettings.FeatureZIsEnalbed a TheMethodImCalling attiverà un eccezione:

this.TheMethodImCallingIfEnabled(
    FeatureSettings.FeatureZIsEnalbed,
    FeatureSettings.ReallyLongFeatureZSettingAName,
    FeatureSettings.ReallyLongFeatureZSettingBName,
    ...);

A seconda della lingua di destinazione, potresti essere in grado di abbreviare il codice "invertendo" la sequenza di chiamate: ad esempio, in C # potresti aggiungere questo metodo a FeatureSettings

class FeatureSettings {
    ...
    public void RunIfEnabledZ(Func<string,string> callback) {
        if(FeatureZIsEnalbed) {
            callback(ReallyLongFeatureZSettingAName, ReallyLongFeatureZSettingBName);
        }
    }
}
...
var theCallback = (a, b) =>  this.TheMethodImCalling(a, b, ...);
FeatureSettings.RunIfEnabledX(theMethod);
FeatureSettings.RunIfEnabledY(theMethod);
FeatureSettings.RunIfEnabledZ(theMethod);
    
risposta data 19.07.2013 - 17:43
fonte
1

Non c'è nulla di sbagliato in una condizione di guardia nella parte superiore di una funzione, ma prima considererei due cose: (1) qual è il caso d'uso normale - viene normalmente chiamato con sì o no? E poi (2) è esternamente visibile? Possono fare lo stesso tipo di controllo?

Chiamare un metodo che non fa il 99% delle volte, è una cattiva idea - è fuorviante.

Se la tua funzione è esposta esternamente e chiamata da altrove, la tua condizione potrebbe non avere senso, quindi passeranno sempre true.

Sarebbe meglio se la tua funzione potesse calcolare FeatureIsEnabled stessa.

    
risposta data 19.07.2013 - 17:56
fonte
0

In parole semplici:

  • Il codice mi sembra a posto.
  • Ha una complessità ciclomatica molto piccola.
  • Non vedo alcun rumore nel dover chiudere le parentesi graffe di if .
  • Avere semplice sequenziale "se" blocchi * non è un odore di codice *.

Ma se pensi che la lista dei processi condizionali crescerà in futuro dovresti considerare i modelli di "Command" o "Chain of responsability" . In questo modo non avrai bisogno del ifs con le parentesi graffe corrispondenti che ti infastidiscono così tanto.

    
risposta data 19.07.2013 - 18:44
fonte

Leggi altre domande sui tag