1

OOPおよび一般的なすべてのプログラミングでは、メソッドは1つの特定のタスクのみを実行する必要があり、別のタスクを実行する必要がある場合は別のメソッドを作成する必要があることは明らかです。私の問題は、1つの大きなメソッドではなく、より多くのコードを使用しているため、これは私の状況では無意味に見えることです。

これが私のコードを構造化する2つの方法です(1つは標準の規則に従うもの、もう1つはコードを保存するだけです)

シナリオ1(2つの方法)

統計メソッドの増加

public void increaseStat(short value, string stat)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   stamina += value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       }

統計法を減らす

public void decreaseStat(short value, string stat)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   stamina -= value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       } 

ご覧のとおり、コードは、-ではなく+である1つの操作を除いてまったく同じです。したがって、慣例のためにすべてのコードを別のメソッドにコピーする代わりに、これを行うことにしました

シナリオ2(増減に取り組む1つの大きな方法)

public void alterStat(short value, string stat, bool operator)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               { 
                   if (Operator == true) stamina -= value;
                   else stamina += value

                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases but to save time I removed them
       }

このように、単純なifステートメントを追加することで、それぞれの場合に2行を追加しますが、コピーされるコードの負荷を節約します。

これが優れたプログラミング手法と見なされるかどうかについて意見をお聞かせください。

お時間をいただきありがとうございます。

4

4 に答える 4

2

次のようなことができます:

public void Change(string stat, bool decrease)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   if(decrease)
                      stamina -= value;
                   else
                      stamina += value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       }
}

したがって、渡された値を増減するため課金するメソッドを作成します。それが行うことはパラメータに基づいていboolます。

これは、2番目のケースで行う可能性のある「形状」の1つですが、解決策が少し異なります。

于 2013-01-01T22:27:05.850 に答える
2

私の見解では、コードの重複がはるかに少ないという利点は、特にコードの保守に関しては、関心の分離のルールを明らかに上回っています。

同様のシナリオはEnum、オブジェクトの状態フラグとしてを使用することです。適切なOOPの方法は、各状態を状態階層内の個別のクラスとしてモデル化することです。後者の欠点は、特にビジターパターンを使用する場合(OOPを使用する場合に必要)、オブジェクトの状態を確認するために作成する必要のあるコードです。

あなたが言及したルールは、クラスのインターフェースに関しては特に役立ちます。一般的なものではなく、操作IncreaseStat()を行う方が(クラスのユーザーにとって)明確である場合、統計を増減するための対応するメソッドによって呼び出されるメソッドの実装を妨げるものはありません。このようにして、両方の利点を活用できます。内部的に重複コードがない間に、特定のタスクに対して特定の操作を行うことができます。DecreaseStat()ChangeStat()private ChangeStat()public

于 2013-01-02T02:42:55.060 に答える
1

最適な解決策は、両方が必要なため、両方の世界から良いものを維持できるかどうかです。問題は、公開するパブリックインターフェイスと内部実装(OOPの基本概念の1つ)を分離することです。どうしますか?

2つのメソッドを使用して、そのまま増加および減少させてから、共通コードをプライベートメソッドにリファクタリングして、それぞれの増加および減少メソッドが適切なフラグを使用して呼び出すことができます。

public void increaseStat(short value, string stat){
    alterStat(value, stat, true);
}

public void decreaseStat(short value, string stat){
    alterStat(value, stat, false);
}


private void alterStat(short value, string stat, bool operator){
    // do the actual work here.
}

これは、クラスを設計する上で非常に重要なパターンです。繰り返しになりますが、アイデアは、クラスインターフェイスとして公開するものと、それを実際に実装する方法を分離することです。それぞれがその目的を果たす必要があり、両方が連携して機能します。

于 2013-01-02T19:46:32.337 に答える
0

C#にはラムダがあるため、これらのソリューションはどちらも理想的ではありません。代わりに、関数として操作を渡そうとします。

public void modStat(string stat, Func<short, short> op)
{
   switch (stat)
   {
       case "stamina":
           if (staminaCheck.Checked == true)
           { 
               stamina = op(stamina)

               staminaText.Text = Convert.ToString(stamina);
           }
           staminaCheck.Checked = false;
           break;

      // more cases
   }

これも以前よりずっと一般的です。理想的には、同じ方法でプロパティを抽象化することもできますが、それははるかに困難です(レンズと呼ばれるものが必要であり、C#はレンズをあまりサポートしていません)。

于 2013-01-01T22:37:44.723 に答える