質問

同僚の鉱山国 boolean値を割り当てメソッドの引数は不可.彼らは交換によるenumerationsは.最初かったの動きをタイムリーかつ詳細に利益がもらった一例です。

どうしてわかりやすい?

file.writeData( data, true );

または

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

現在わかった!;-)
これは例が列挙として第二のパラメータのコードに入ってき易い。

では、どのご意見このトピック?

役に立ちましたか?

解決

ブール値は「yes / no」を表します;選択肢。 「はい/いいえ」を表す場合は、ブール値を使用します。それは一目瞭然です。

ただし、2つのオプションのどちらかを選択し、どちらも明らかにyesまたはnoでない場合、enumはより読みやすくなることがあります。

他のヒント

Enumは、3つ目(またはそれ以上)の選択肢が必要な将来の変更にも対応しています。

問題を最もよくモデル化したものを使用してください。この例では、列挙型の方が適しています。ただし、ブール値の方が優れている場合もあります。それはあなたにとってより理にかなっています:

lock.setIsLocked(True);

または

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

この場合、ブールオプションを選択するのは、それが非常に明確で明確だと思うからです。それでも、2番目の選択肢は有効ですが、不必要に複雑です、私見。

私はあなたがほとんど自分でこれに答えたと思います、私は最終目標はコードをより読みやすくすることだと思います、そしてこの場合enumがそれをしたと思いますガイドラインとして、つまり列挙型は一般的なブールや整数などよりもコードで読みやすいことが多いですが、ルールには常に例外があります。

キューバミサイル中に国連でゾリン大使に提起された質問Adlai Stevensonを思い出してください危機

  

"あなたは世界の法廷にいます   今の意見、あなたは答えることができます    yesまたはno 。あなたはそれを否定しました[ミサイル]   存在し、私はかどうかを知りたい   あなたを正しく理解しました。   まで私の答えを待つ準備をしました   それがあなたの場合、地獄は凍結します   決定。"

メソッドにあるフラグが、バイナリ決定にピン留めできるような性質のものであり、その決定が3つに決してならない場合-wayまたはn-wayの決定。ブール値を使用します。表示:フラグの名前は isXXX です。

モード切り替えであるものの場合、ブール値にしないでください。そもそもメソッドを書くときに考えていたよりももう1つのモードが常にあります。

1つ以上のモードのジレンマには、たとえば幽霊の多いUnixでは、ファイルまたはディレクトリが現在持つことのできる許可モードは、ファイルの種類、所有権などに応じて、モードの奇妙な二重の意味をもたらします。

私にとって、ブール値も列挙も使用するのは良い方法ではありません。 Robert C. Martinは、これをクリーンコードヒント#12:ブール引数の削除で非常に明確に捉えています。

  

ブール引数は、関数が複数のことを行うことを大声で宣言します。それらは紛らわしいため、削除する必要があります。

メソッドが複数のことを行う場合は、2つの異なるメソッドを記述する必要があります。たとえば、 file.append(data) file.overwrite(data)

列挙を使用しても、物事は明確になりません。何も変更せず、フラグ引数のままです。

これが悪いことであることに気付いた理由は2つあります。

  1. 一部の人々は次のようなメソッドを記述するため:

    ProcessBatch(true, false, false, true, false, false, true);
    

    これは明らかにパラメーターを混同するのが簡単すぎるため悪いことであり、何を指定しているのか見てもわかりません。ただし、1つのブール値はそれほど悪くはありません。

  2. 単純なyes / noブランチによってプログラムフローを制御することは、2つのまったく異なる関数が異常な方法で1つにまとめられることを意味する場合があるためです。例えば:

    public void Write(bool toOptical);
    

    本当に、これは2つのメソッドである必要があります

    public void WriteOptical();
    public void WriteMagnetic();
    

    これらのコードはまったく異なる可能性があるためです。彼らはあらゆる種類の異なるエラー処理と検証を行わなければならないかもしれませんし、あるいは発信データを異なってフォーマットしなければならないかもしれません。 Write()または Write(Enum.Optical)を使用するだけではわかりません(もちろん、これらのメソッドのいずれかが内部メソッドWriteOpticalを呼び出すだけでも構いません) /必要に応じてマグ)。

それは単に依存していると思います。 #1を除いて、私はそれについて大したことはしません。

列挙型の方が優れていますが、ブール型のパラメーターを「受け入れられない」とは呼びません。場合によっては、1つの小さなブール値を挿入して先に進む方が簡単な場合があります(プライベートメソッドなどを考えてください)

PythonやObjective-Cのような名前付きパラメータを持つ言語では、名前がパラメータの機能を説明できるため、ブール値は問題ない場合があります。

file.writeData(data, overwrite=true)

または:

[file writeData:data overwrite:YES]

これが良いルールであることには同意しません。明らかに、Enumはいくつかのインスタンスでより良い明示的または冗長なコードを作成しますが、原則として到達する方法のようです。

まず、例を挙げましょう。 ブール値のパラメーターを使用しても、優れたコードを記述するプログラマーの責任(および能力)が実際に危険にさらされることはありません。あなたの例では、プログラマは次のように記述することで、冗長コードと同じように書くことができます。

dim append as boolean = true
file.writeData( data, append );

または私はより一般的なものを好む

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

2番目: 指定したEnumの例は、「良い」だけです。あなたはCONSTを通過しているからです。ほとんどのアプリケーションでは、ほとんどの場合、関数に渡されるパラメーターのほとんどは変数ではありませんが、少なくとも一部は変数です。この場合、2番目の例(変数に適切な名前を付ける)の方がはるかに優れており、Enumを使用してもほとんどメリットはありません。

Enumsて明確な利益をございますのでご注意下さいんだけを交換すべてのboolean値を代入とenums.多くの場所がありますがtrue/falseの場合は実際の表でいるのかもしれません。

しかし、使用してメソッドの引数は疑いるものの、なかなかできないを見な掘り込もうすることになっているのですどうかをtrue/false 実際に手段

特性(特にC#3つのオブジェクトinitializers)又はキーワード引数(a la rubyやpython)がよりよい方法で行われているかがんばboolean引数です。

C#例:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

Ruby例

validates_presence_of :name, :allow_nil => true

Python例

connect_to_database( persistent=true )

しかし、面白いことを考えることができるがbooleanのメソッド引数の権利については、javaでは、がんのいずれか又はキーワード引数になります。この一因となっているのは嫌だjava:-(

多くの場合、列挙型はブール値よりも読みやすく、拡張性が高いことは事実ですが、「ブール値は受け入れられない」という絶対的な規則です。ダフトです。柔軟性がなく、逆効果です。人間の判断の余地はありません。それらは便利なので、ほとんどの言語の基本的な組み込み型です-他の組み込み型に適用することを検討してください。たとえば、「パラメーターとしてintを使用しない」と言ってください。ただ夢中になります。

このルールはスタイルの問題であり、バグや実行時のパフォーマンスの可能性ではありません。より良いルールは、「読みやすさの理由からブール値よりも列挙型を優先する」です。

.Netフレームワークをご覧ください。ブール値は、かなりの数のメソッドのパラメーターとして使用されます。 .Net APIは完全ではありませんが、ブール値をパラメーターとして使用することは大きな問題だとは思いません。ツールチップには常にパラメーターの名前が表示され、この種のガイダンスも作成できます。メソッドパラメーターにXMLコメントを入力すると、ツールチップに表示されます。

また、明確にブール値を列挙にリファクタリングする必要がある場合もあることを追加する必要があります-クラスまたはメソッドparamsに2つ以上のブール値があり、すべての状態が有効ではない場合(たとえば、無効です)両方をtrueに設定します)。

たとえば、クラスに次のようなプロパティがある場合

public bool IsFoo
public bool IsBar

そして、両方を同時に真にするのはエラーです。実際に得られるのは3つの有効な状態であり、次のように表現されます:

enum FooBarType { IsFoo, IsBar, IsNeither };

同僚が順守している可能性のあるルールは次のとおりです:

  • デザインを独断的にしないでください。
  • コードのユーザーに最も適したものを選択します。
  • 今月の形が好きだからといって、星形のペグをすべての穴に打ち込まないでください!

ブール値は、フレームワークの機能を拡張するつもりがない場合にのみ受け入れられます。列挙型を拡張でき、関数呼び出しの以前の実装を壊さないため、列挙型が推奨されます。

Enumのもう1つの利点は、読みやすいことです。

メソッドが次のような質問をする場合:

KeepWritingData (DataAvailable());

where

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

booleanメソッドの引数は、完全に理にかなっているようです。

方法によって異なります。メソッドが非常に明らかに真/偽のことをする場合、それは問題ありません。以下[この方法の最適な設計とは言いませんが、使用法が明白な例にすぎません]。

CommentService.SetApprovalStatus(commentId, false);

ただし、前述の例のように、ほとんどの場合、列挙型を使用することをお勧めします。 .NET Framework自体にはこの規則に従わない例が数多くありますが、それはサイクルのかなり後期にこの設計ガイドラインを導入したためです。

やや明確になりますが、インターフェイスの複雑さを大幅に拡張し始めます-追加/上書きなどのブール演算の選択では、やり過ぎのように見えます。さらにオプションを追加する必要がある場合(この場合は考えられません)、いつでもリファクタリングを実行できます(言語によって異なります)

Enumsは確かにコードを読みやすくすることができます。 (少なくとも.netでは)まだ注意すべきことがいくつかあります

enumの基になるストレージはintであるため、デフォルト値はゼロになるため、0が適切なデフォルトであることを確認する必要があります。 (たとえば、構造体は作成時にすべてのフィールドがゼロに設定されるため、0以外のデフォルトを指定する方法はありません。値0がない場合は、intにキャストせずに列挙をテストすることもできません。悪いスタイル。)

enumがコードに対してプライベートである場合(公開されていない場合)、ここで読むのをやめることができます。

enumが外部コードに何らかの方法で公開されている場合やプログラムの外部に保存されている場合は、明示的に番号を付けることを検討してください。コンパイラーはそれらを自動的に0から番号付けしますが、値を指定せずに列挙型を再配置すると、欠陥が生じる可能性があります。

合法的に書くことができます

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

これに対抗するために、特定できない列挙型を使用するコード(たとえば、パブリックAPI)は、列挙型が有効かどうかを確認する必要があります。これを行うには

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

Enum.IsDefined の唯一の注意点は、リフレクションを使用し、速度が遅いことです。また、バージョン管理の問題もあります。列挙値を頻繁に確認する必要がある場合は、次の方法をお勧めします。

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

バージョニングの問題は、古いコードはあなたが持っている2つの列挙型の処理方法しか知らないということです。 3番目の値を追加すると、Enum.IsDefinedはtrueになりますが、古いコードでは必ずしも処理できません。おっと。

[Flags] 列挙型を使用するとさらに楽しいことができ、その検証コードはわずかに異なります。

移植性のために、enumで ToString()を呼び出し、それらを読み戻すときに Enum.Parse()を使用する必要があることにも注意してください。 ToString() Enum.Parse()はどちらも [Flags] 列挙型も処理できるため、使用しない理由はありません。コードを壊さずに列挙の名前を変更することさえできないので、もう一つの落とし穴です。

そのため、自問自答する際に上記のすべてを考慮する必要がある場合があります。ブールだけで逃げることができますか

IMHOでは、3つ以上のオプションが可能な状況では、enumが明らかな選択肢になるようです。ただし、ブール値だけで十分な場合があります。その場合、boolが機能する列挙型を使用すると、4が機能するときに7つの単語を使用する例になります。

ブール値は、明らかなトグルが2つのうちの1つ(つまり、電球の状態、オンまたはオフ)にしかできない場合に意味があります。それ以外に、あなたが何を渡しているのかが明白になるような方法でそれを書くのは良いことです-例えば。ディスク書き込み-バッファなし、ラインバッファ、または同期-をそのまま渡す必要があります。今すぐ同期書き込みを許可したくない場合(つまり、2つのオプションに制限されている場合)、それらが一目で何をするのかを知るために、より冗長にすることを検討する価値があります。

とはいえ、FalseとTrue(ブール値0と1)を使用することもできます。その後、さらに値が必要な場合は、ユーザー定義値(2と3など)と古い0をサポートするように関数を展開します/ 1の値はうまく移植されるので、コードが壊れてはいけません。

場合によっては、オーバーロードを使用してさまざまな動作をモデル化する方が簡単な場合があります。あなたの例から続けるには:

file.appendData( data );  
file.overwriteData( data );

複数のパラメーターがあり、それぞれがオプションの固定セットを許可している場合、このアプローチは低下します。たとえば、ファイルを開くメソッドには、ファイルモード(オープン/作成)、ファイルアクセス(読み取り/書き込み)、共有モード(なし/読み取り/書き込み)のいくつかの組み合わせがあります。構成の総数は、個々のオプションのデカルト積に等しくなります。当然、このような場合、複数のオーバーロードは適切ではありません。

列挙型は、場合によってはコードを読みやすくしますが、一部の言語(C#など)で正確な列挙型値を検証することは困難な場合があります。

多くの場合、ブール型パラメーターが新しいオーバーロードとしてパラメーターのリストに追加されます。 .NETの1つの例は次のとおりです。

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

後者のオーバーロードは、最初のバージョンよりも後のバージョンの.NET Frameworkで利用可能になりました。

選択肢が2つしかないことがわかっている場合は、ブール値でも構いません。列挙は古いコードを壊さない方法で拡張可能ですが、古いライブラリは新しい列挙値をサポートしない可能性があるため、バージョン管理を完全に無視することはできません。


編集

C#の新しいバージョンでは、名前付き引数を使用することができます。IMOは、enumと同じ方法で呼び出しコードをより明確にすることができます。上記と同じ例を使用します:

Enum.Parse(str, ignoreCase: true);

2つのオプション(および列挙なしで読みやすい2つのオプションのみ)があるメソッドでは、Enumが良い方法であることに同意します。

e.g。

public void writeData(Stream data, boolean is_overwrite)

列挙型が大好きですが、ブール値も便利です。

これは古い投稿の遅いエントリであり、ページをはるかに下回っているので誰も読むことはありませんが、まだ誰もそれを言っていないので...

インラインコメントは、予期しない bool 問題の解決に大いに役立ちます。元の例は特に凶悪です:関数の説明で変数に名前を付けようとしていることを想像してください!次のようなものになるでしょう

void writeData( DataObject data, bool use_append_mode );

しかし、例のために、それが宣言だとしましょう。次に、説明のつかないブール引数については、変数名をインラインコメントに入れます。比較

file.writeData( data, true );

with

file.writeData( data, true /* use_append_mode */);

実際には、引数の正確な性質に依存します。 yes / noまたはtrue / falseでない場合、enumにより読みやすくなります。ただし、列挙型を使用する場合は、引数を確認するか、基になる型の未定義の値を渡すことができるため、受け入れ可能なデフォルトの動作を行う必要があります。

例でブール値の代わりに列挙型を使用すると、メソッド呼び出しが読みやすくなります。ただし、これはメソッド呼び出しの名前付き引数であるC#のお気に入りのウィッシュアイテムの代わりになります。この構文:

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

完全に読みやすく、プログラマーが行うべきことを行うことができます。IDEでの表示方法に関係なく、メソッドの各パラメーターに最適なタイプを選択します。

C#3.0では、コンストラクターで名前付き引数を使用できます。なぜメソッドでもこれができないのかわかりません。

ブール値 true / false のみ。したがって、それが何を表すのかは明確ではありません。 Enum には意味のある名前を付けることができます。たとえば、 OVERWRITE APPEND などです。したがって、enumの方が優れています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top