メソッド呼び出しまたはメソッド自体を保護する方が良いですか?


12

私はアプリケーションを書いていますが、このポイントに到達しました:

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

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

private void GiveApples()
{
    ...
}

private void GiveBananas()
{
    ...
}

これは非常に簡単です。いくつかの条件があり、それらが真である場合、メソッドが呼び出されています。しかし、私は考えていました、このようにするのがむしろ良いですか?

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

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

    ...
}

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

    ...
}

2番目のケースでは、各メソッドはそれ自体を保護するため、これらのメソッドのGiveApplesいずれかまたはGiveBananas外部から呼び出された場合でもSomeMethod、設定に正しいフラグがある場合にのみ実行されます。

これは私が実際に問題と見なすべきものですか?

私の現在のコンテキストでは、これらの2つのメソッドがこのメソッドの外部から呼び出されることはほとんどありませんが、だれもそれを保証することはできません。


5
最初にチェックせずに、GiveApplesまたはGiveBananasを呼び出す必要があるかどうかによって異なります。ガードはメソッドに関連付けられているため、おそらくメソッドに属します。
ロバートハーベイ

回答:


13

ガードはメソッド従わなければならないものだと思います。あなたの例では、Settings.GiveApplesがfalseの場合、メソッドはリンゴを与えてはいけません。

その場合、ガードは間違いなくメソッド内に属します。これにより、最初にガードをチェックせずに、アプリケーションの別のポイントから誤って呼び出すことを防ぎます。

一方、設定が呼び出しメソッドにのみ適用され、コードの他の場所の別のメソッドが設定に関係なくGiveApplesを使用できる場合、それはガードではなく、おそらく呼び出しコードにあるはずです。


5

メソッド自体の中にガードを配置します。の消費者は、GiveApples()またはGiveBananas()のガードを管理する責任を負わないでくださいGiveApples()

設計の観点からは、SomeMethod()果物が必要であることだけを知っている必要があり、それを得るためにアプリケーションが何をする必要があるかを気にするべきではありません。SomeMethod()特定の果物の検索を許可するグローバルな設定があることを知る責任がある場合、果物検索の抽象化は漏れやすくなります。この新しいガードを実装するために個別にリファクタリングする必要がある、GetApples()またはGetBananas()リファクタリングする必要があるすべてのメソッドとして、ガードメカニズムが変更された場合、これはカスケードします。また、コードを書いているときに、そのチェックなしで忘れてみて、実を結ぶのは簡単です。

このシナリオで考慮する必要があるのは、設定でアプリケーションが果物を与えることが許可されていない場合のアプリケーションの対応方法です。


4

一般に、外部提供の設定などのテストの責任と、「コアビジネスコード」のような責任を分離することは、多くの場合、良いアイデアGiveApplesです。一方で、一緒に属するものをグループ化する関数を持つことも良い考えです。次のようにコードをリファクタリングすることにより、両方の目標を達成できます。

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

これにより、クラスの依存関係がなくても、コードをリファクタリングしGiveApplesたりGiveBananas、別の場所にリファクタリングしたりできますSettings。これは、何も気にしないユニットテストでこれらのメソッドを呼び出す場合に明らかに有益ですSettings

しかし、どのような状況でも、テストコンテキストであっても、プログラムで常に最初にチェックされるGiveApplesコンテキストの外のようなものを呼び出すことが間違っている場合、チェックなしのSettings.GiveApplesような関数を提供するとエラーが発生しやすくなります、その後、内でテストするバリアントに固執します。GiveApplesSettingsSettings.GiveApplesGiveApples

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.