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


12

Sto scrivendo una domanda e sono arrivato a questo punto:

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

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

private void GiveApples()
{
    ...
}

private void GiveBananas()
{
    ...
}

Sembra piuttosto semplice. Vi 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, ciascuno dei metodi si custodisce da solo, quindi anche se uno di questi metodi GiveAppleso GiveBananasviene chiamato dall'esterno SomeMethod, verranno eseguiti solo se hanno il flag corretto in Impostazioni.

È qualcosa che dovrei davvero considerare un problema?

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


5
Dipende se potresti mai aver bisogno di chiamare GiveApples o GiveBananas senza prima controllare. Poiché la guardia è associata al metodo, probabilmente appartiene al metodo.
Robert Harvey,

Risposte:


13

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

In tal caso, la protezione appartiene sicuramente al metodo. Questo ti impedisce di chiamarlo accidentalmente da un altro punto dell'applicazione senza prima controllare le protezioni.

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


5

Posizionare la protezione all'interno del metodo stesso. Il consumatore GiveApples()o GiveBananas()non dovrebbe essere responsabile della gestione delle guardie 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 ottenerla. L'astrazione del recupero dei frutti diventa permeabile se SomeMethod()è responsabile di sapere che esiste un ambiente globale che consente il recupero di determinati frutti. Ciò si verifica se il meccanismo di protezione cambia, poiché ora tutti i metodi che devono GetApples()o GetBananas()devono essere rifattorizzati separatamente per implementare questa nuova protezione. È anche molto facile provare a dimenticare e ottenere frutta senza quel controllo mentre scrivi 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.


4

In generale, è spesso una buona idea separare le responsabilità di testare qualcosa come impostazioni fornite esternamente e il "codice delle attività principali" come GiveApples. D'altra parte, anche avere funzioni che raggruppano ciò che appartiene è una buona idea. Puoi raggiungere entrambi gli obiettivi riformattando il 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 refactoring del codice di GiveApplese / o GiveBananasin un posto separato senza dipendenze dalla Settingsclasse. Ciò è ovviamente vantaggioso quando si desidera chiamare tali metodi in un test unitario che non interessa a nessuno Settings.

Tuttavia, se è sempre sbagliato nel tuo programma, in qualsiasi circostanza, anche in un contesto di test, chiamare qualcosa come GiveApplesal di fuori di un contesto in cui Settings.GiveApplesviene controllato per primo, e hai l'impressione che fornire una funzione come GiveApplessenza il Settingscontrollo sia soggetto a errori , quindi attenersi alla variante in cui si esegue il test Settings.GiveApplesall'interno di GiveApples.

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.