È meglio proteggere la chiamata al metodo o il metodo stesso?

12

Sto scrivendo un'applicazione e sono arrivato a questo punto:

private void SomeMethod()
{
    if (Settings.GiveApples)
    {
        GiveApples();
    }

    if (Settings.GiveBananas)
    {
        GiveBananas();
    }
}

private void GiveApples()
{
    ...
}

private void GiveBananas()
{
    ...
}

Questo sembra abbastanza semplice. Ci sono alcune condizioni e se sono vere vengono chiamati i metodi. Tuttavia, stavo pensando, è piuttosto meglio fare così:

private void SomeMethod()
{
    GiveApples();
    GiveBananas();
}

private void GiveApples()
{
    if (!Settings.GiveApples)
    {
        return;
    }

    ...
}

private void GiveBananas()
{
    if (!Settings.GiveBananas)
    {
        return;
    }

    ...
}

Nel secondo caso, ognuno dei metodi si difende da solo, quindi anche se qualcuno di questi metodi GiveApples o GiveBananas è chiamato dall'esterno SomeMethod , verranno eseguiti solo se hanno il flag corretto in Impostazioni.

Questo è qualcosa che dovrei considerare come un problema?

Nel mio contesto attuale, è molto improbabile che questi due metodi vengano chiamati al di fuori di questo metodo, ma nessuno potrà mai garantirlo.

    
posta Nikola 26.01.2016 - 16:35
fonte

3 risposte

13

Penso alle guardie come a qualcosa che il metodo deve obbedire. Nel tuo esempio, il metodo non deve dare mele se Settings.GiveApples è false.

Se questo è il caso, la guardia appartiene sicuramente al metodo. Questo ti impedisce di chiamarlo accidentalmente da un altro punto della tua applicazione senza prima controllare le guardie.

D'altra parte se le impostazioni si applicano solo al metodo di chiamata e un altro metodo nel tuo codice può dare a ApplyApples indipendentemente dall'impostazione, allora non è una guardia e probabilmente dovrebbe essere nel codice chiamante.

    
risposta data 26.01.2016 - 16:51
fonte
5

Posiziona la guardia all'interno del metodo stesso. Il consumatore di GiveApples() o GiveBananas() non dovrebbe essere responsabile della gestione delle protezioni di GiveApples() .

Dal punto di vista del design, SomeMethod() dovrebbe solo sapere che ha bisogno di frutta e non dovrebbe preoccuparsi di ciò che l'applicazione deve fare per ottenerlo. L'astrazione del recupero dei frutti perde se il SomeMethod() è responsabile di sapere che esiste un'impostazione globale che consente il recupero di determinati frutti. Questo avviene a cascata se il tuo meccanismo di guardia cambia mai, poiché ora tutti i metodi che hanno bisogno di GetApples() o GetBananas() devono essere rifattorizzati separatamente per implementare questa nuova guardia. È anche molto facile provare e ottenere in maniera smodata frutta senza quell'assegno mentre stai scrivendo il codice.

Quello che dovresti considerare in questo scenario è come la tua applicazione dovrebbe reagire quando Impostazioni non consente alla tua applicazione di dare frutti.

    
risposta data 26.01.2016 - 17:12
fonte
4

In genere, spesso è una buona idea separare le responsabilità di testare qualcosa come le impostazioni fornite esternamente e il "codice core business" come GiveApples . D'altra parte, avere una funzione che raggruppa insieme ciò che appartiene insieme è anche una buona idea. Puoi raggiungere entrambi gli obiettivi eseguendo il refactoring del codice in questo modo:

private void SomeMethod()
{
    GiveApplesIfActivated();
    GiveBananasIfActivated();
}

private void GiveApplesIfActivated()
{
    if (Settings.GiveApples)
    {
        GiveApples();
    }
}

private void GiveBananasIfActivated()
{
    if (Settings.GiveBananas)
    {
        GiveBananas();
    }
}

private void GiveApples()
{
    ...
}

private void GiveBananas()
{
    ...
}

Questo ti dà una migliore possibilità di rifattorizzare il codice di GiveApples e / o GiveBananas in un posto separato senza alcuna dipendenza dalla classe Settings . Ovviamente è utile quando vuoi chiamare quei metodi in un test unitario a cui non interessa il Settings .

Tuttavia, se è sempre sbagliato nel tuo programma, in qualsiasi circostanza, anche in un contesto di test, chiamare qualcosa come GiveApples al di fuori di un contesto in cui Settings.GiveApples è selezionato per primo, e sei sotto impressione solo fornendo un funziona come GiveApples senza il controllo Settings è soggetto a errori, quindi segui la variante in cui testare Settings.GiveApples all'interno di GiveApples .

    
risposta data 26.01.2016 - 21:46
fonte

Leggi altre domande sui tag