2016-10-28 5 views
1

今日、2つの値を返すのが最善であることについて、同僚と議論しました。 3つの意見がありました。この問題の重要な点は、この質問の優先回答である余分なクラスまたは構造体(したがってタプルはありません)を使用できないことです。Clean Code - Are output parameters bad?2つの値と比較した場合の値の戻り値

public enum Offset 
{ 
    None = 0, 
    Training = 10, 
    Cancel = 20 
} 

static void Main(string[] args) 
{ 
    //Option 1 
    int outValue = 0; 
    Offset outOffset; 
    HandleOffset(35, out outValue, out outOffset); 

    //Option 2 
    int refValue = 0; 
    outOffset = SubtractOffset(ref refValue); 

    //Option 3 
    outOffset = GetOffsetById(35); 
    int id = GetIdWithoutOffset(35); 
} 

//Option 1 
public static void HandleOffset(int inValue, out int outValue, out Offset outOffset) 
{ 
    outValue = inValue; 
    outOffset = Offset.None; 
    if ((inValue-(int)Offset.Cancel)>15) 
    { 
     outValue -= (int)Offset.Cancel; 
     outOffset |= Offset.Cancel; 
    } 
    if ((inValue - (int)Offset.Training) > 15) 
    { 
     outValue -= (int)Offset.Training; 
     outOffset |= Offset.Training; 
    } 
} 

//Option 2 
public static Offset SubtractOffset(ref int id) 
{ 
    Offset offset = Offset.None; 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     id -= (int)Offset.Cancel; 
     offset |= Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     id -= (int)Offset.Training; 
     offset |= Offset.Training; 
    } 
    return offset; 
} 

//Option 3 
public static Offset GetOffsetById(int id) 
{ 
    Offset offset = Offset.None; 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     offset |= Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     offset |= Offset.Training; 
    } 
    return offset; 
} 

//Option 3 
public static int GetIdWithoutOffset(int id) 
{ 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     id -= (int)Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     id -= (int)Offset.Training; 
    } 
    return id; 
} 

オプション2は戻り値+参照値のために醜いようです。

オプション1も2つの出力パラメータのために醜いようですが、実際には2番目のオプションよりもきれいに見えます。

オプション3は私に一番きれいです。

これらのソリューションの中で最もクリーンなソリューション(bob martinできれいなコードできれいになっています)と思われるソリューションや、問題を解決するための選択肢がありますか?

+0

パフォーマンスの違いは何ですか?パフォーマンスクリティカルなコードのスピードアップがあれば、ref/outの欲望を理解することができますが、オプション3が最も近い "clean code by bob martin"のようにクリーンなものを探していると思います。一般に私の会社の人は、あなたのメソッドがあまりにも多くをやろうとしているという指標であるため、ref/outパラメータを避ける傾向があります。 –

+0

オプション4:2つの関数それぞれが返り値を返します – zerkms

+0

@zerkmsあなたの解を説明できますか?オプション3との違いは何ですか? – Bongo

答えて

1

一般的に言えば、最もきれいな解決策は、outまたはrefのパラメータを必要としないソリューションです(構造体/クラスが最適です、タプルも機能します)。あなたがクラス/構造体またはタプルを使用することは許可されていないので、これは好ましい方法です。私はまだ最も簡単な方法として最初のオプションを使用します。

outキーワードはあなたが望むものを正確に実行するはずなので、私の意見では、outというキーワードは完全に駄目なので、refを使うことは全く必要ありません。

3番目のオプションは大丈夫ですが、非常に乱雑ですが、それほど簡単ではありません。タプルを使用することはできず、明確なコードを維持したいので、避けてください。

TL; DR:最初のオプションを使用してください。

1

私はこれを投げ捨てるつもりですが、私はこれを決してプロダクションでは行っていません(少なくともパブリックAPIの場合)。

代わりの方法は、dynamic戻り値の型を使用することです。 paramがありません。 refパラメータなし。返される値の難読化のみ:

public class Program 
{ 
    public static void Main() 
    { 
     dynamic offset = HandleOffset(); 

     Console.WriteLine(offset); 
    } 

    public static dynamic HandleOffset() 
    { 
     return new 
     { 
      Value = 64, 
      Offset = Offset.Cancel 
     }; 
    } 
} 

public enum Offset 
{ 
    None = 0, 
    Training = 10, 
    Cancel = 20 
} 
+0

うわーこれは面白いです。私は異なるオプションがある場合、私は生産でそれを使用したくないことに同意するが、これは本当に面白いです。 +1 – Bongo

関連する問題