Ist es besser, den Methodenaufruf oder die Methode selbst zu schützen?

12

Ich schreibe eine Bewerbung und bin zu folgendem Punkt gekommen:

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

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

private void GiveApples()
{
    ...
}

private void GiveBananas()
{
    ...
}

Das sieht ziemlich direkt aus. Es gibt einige Bedingungen, und wenn diese erfüllt sind, werden die Methoden aufgerufen. Ich dachte mir jedoch, ist es besser, das so zu machen:

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

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

    ...
}

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

    ...
}

Im zweiten Fall wird jede der Methoden Wachen selbst, so dass selbst wenn eine dieser Methoden GiveApplesoder GiveBananasvon außen aufgerufen wird SomeMethod, werden sie nur , wenn sie die richtige Flagge in den Einstellungen müssen ausgeführt werden.

Ist das etwas, das ich eigentlich als Problem betrachten sollte?

In meinem gegenwärtigen Kontext ist es sehr unwahrscheinlich, dass diese beiden Methoden von außerhalb dieser Methode aufgerufen werden, aber niemand kann dies jemals garantieren.

Nikola
quelle
5
Es hängt davon ab, ob Sie GiveApples oder GiveBananas jemals aufrufen müssen, ohne dies vorher zu überprüfen. Da der Guard der Methode zugeordnet ist, gehört er wahrscheinlich zur Methode.
Robert Harvey
verwandt (möglicherweise ein Duplikat): Wie können Guard-Anweisungen und Small Functions koexistieren?
gnat

Antworten:

13

Ich betrachte Wachen als etwas, dem die Methode gehorchen muss . In Ihrem Beispiel darf die Methode keine Äpfel angeben, wenn Settings.GiveApples false ist.

Wenn dies der Fall ist, gehört der Wächter definitiv in die Methode. Dies verhindert, dass Sie es versehentlich von einem anderen Punkt in Ihrer Anwendung aufrufen, ohne zuvor die Wachen zu überprüfen.

Wenn die Einstellungen jedoch nur für die aufrufende Methode gelten und eine andere Methode an einer anderen Stelle in Ihrem Code unabhängig von der Einstellung GiveApples ausführen kann, ist dies kein Schutz und sollte wahrscheinlich im aufrufenden Code enthalten sein.

Jeremy Hutchinson
quelle
5

Platzieren Sie die Schutzvorrichtung innerhalb der Methode. Der Verbraucher von GiveApples()oder GiveBananas()sollte nicht für die Verwaltung der Wachen von verantwortlich sein GiveApples().

Aus gestalterischer Sicht SomeMethod()sollte nur bekannt sein, dass es Früchte braucht, und es sollte nicht wichtig sein, was Ihre Anwendung tun muss, um sie zu erhalten. Die Abstraktion des Obstabrufs wird undicht, wenn bekannt SomeMethod()ist, dass es eine globale Umgebung gibt, die den Abruf bestimmter Früchte ermöglicht. Dies kann passieren, wenn sich Ihr Schutzmechanismus ändert, da jetzt alle Methoden separat überarbeitet werden müssen GetApples()oder GetBananas()müssen, um diesen neuen Schutz zu implementieren. Es ist auch sehr einfach, beim Schreiben von Code zu versuchen, vergesslich Obst zu bekommen, ohne dass dies überprüft wird.

In diesem Szenario sollten Sie berücksichtigen, wie Ihre Anwendung reagieren soll, wenn die Anwendung in den Einstellungen keine Früchte tragen kann.

Ravibhagw
quelle
4

Im Allgemeinen ist es oft eine gute Idee, die Verantwortlichkeiten für das Testen von Einstellungen, die von außen bereitgestellt werden, von denen des "Kerngeschäfts-Codes" zu trennen GiveApples. Andererseits ist es auch eine gute Idee, Funktionen zu haben, die zusammenfassen, was zusammen gehört. Sie können beide Ziele erreichen, indem Sie Ihren Code folgendermaßen umgestalten:

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()
{
    ...
}

Dies gibt Ihnen eine bessere Chance, den Code von GiveApplesund / oder GiveBananasan eine separate Stelle umzugestalten, ohne dass Abhängigkeiten von der SettingsKlasse bestehen. Das ist natürlich von Vorteil, wenn Sie diese Methoden in einem Unit-Test aufrufen möchten, für den es keine gibt Settings.

Wenn es jedoch in Ihrem Programm immer falsch ist, rufen Sie unter allen Umständen, auch in einem Testkontext, so etwas wie GiveApplesaußerhalb eines Kontexts Settings.GiveApplesauf, in dem zuerst geprüft wird, und Sie haben den Eindruck, dass nur eine Funktion wie GiveApplesohne SettingsPrüfung fehleranfällig ist , dann bleib bei der Variante, in der du Settings.GiveApplestestest GiveApples.

Doc Brown
quelle