ブール値パラメーターを使用して値を決定するのは間違っていますか?


39

動作を決定するためにブール値パラメーターを使用するのは間違っていますか?、ブールパラメータを使用して動作を決定することを避けることの重要性を知っています。たとえば:

元のバージョン

public void setState(boolean flag){
    if(flag){
        a();
    }else{
        b();
    }
    c();
}

新しいバージョン:

public void setStateTrue(){
    a();
    c();
}

public void setStateFalse(){
    b();
    c();
}

しかし、動作の代わりにブール値パラメーターを使用して値を決定する場合はどうでしょうか?例えば:

public void setHint(boolean isHintOn){
    this.layer1.visible=isHintOn;
    this.layer2.visible=!isHintOn;
    this.layer3.visible=isHintOn;
}

私はisHintOnフラグを削除し、2つの別個の関数を作成しようとしています。

public void setHintOn(){
    this.layer1.visible=true;
    this.layer2.visible=false;
    this.layer3.visible=true;
}

public void setHintOff(){
    this.layer1.visible=false;
    this.layer2.visible=true;
    this.layer3.visible=false;
}

ただし、変更されたバージョンは次の理由で保守性が低いようです。

  1. 元のバージョンよりも多くのコードがあります

  2. layer2の可視性がヒントオプションの反対であることを明確に示すことはできません

  3. 新しいレイヤー(例:layer4)が追加されたら、追加する必要があります

    this.layer4.visible=false;
    

    そして

    this.layer4.visible=true;  
    

    setHintOn()およびsetHintOff()に個別に

だから私の質問は、ブールパラメータが値のみを決定するために使用され、動作ではない場合(たとえば、そのパラメータのif-elseなし)、そのブールパラメータを削除することはまだ推奨されていますか?


26
結果のコードがより読みやすく、保守しやすい場合は決して間違っていません;-) 2つの別個のメソッドの代わりに単一のメソッドを使用することをお勧めします。
-helb

32
これらのブール値を設定するメソッドの単一の実装により、クラスの保守と実装の理解が容易になるという説得力のある議論を提示します。結構; これらは正当な考慮事項です。ただし、クラスのパブリックインターフェイスは、それらに対応するために変形する必要はありません。別のメソッドでパブリックインターフェイスの理解と操作が容易になる場合setHint(boolean isHintOn)は、プライベートメソッドとして定義し、それぞれとを呼び出すパブリックメソッドsetHintOnsetHintOffメソッドを追加setHint(true)setHint(false)ます。
マークアメリー

9
私はそれらのメソッド名と非常に不幸になるだろう:彼らは本当に提供していない任意のオーバー利益をsetHint(true|false)。じゃがいもポタート。少なくとも使用のようなものをsetHintunsetHint
コンラッドルドルフ


4
@kevincline条件が1つの名前の場合、is最初に記述します。isValidなど。では、なぜそれを2つの単語に変更するのでしょうか。その上、「より自然」は見る人の目にあります。。あなたは私のために、その後、英語の文としてそれを発音したい場合は、「」に隠れて「ヒントが上にある場合は、」持っているより自然だろう
氏リスター

回答:


95

APIの設計では、呼び出し側からAPIのクライアントに最も有用なものに焦点を当てる必要があります。

たとえば、この新しいAPIで呼び出し元がこのようなコードを定期的に記述する必要がある場合

if(flag)
    foo.setStateTrue();
else
    foo.setStateFalse();

パラメータを避けることは、呼び出し元が記述できるAPIを持つよりも悪いことは明らかです

 foo.setState(flag);

前のバージョンでは問題が発生するだけで、呼び出し側で解決する必要があります(おそらく複数回)。これは、読みやすさや保守性を向上させるものではありません。

実装側は、しかし、パブリックAPIのルックスが好きな方法を指示べきではありません。以下のような関数ならばsetHint、パラメータとは、実装が少ないコードを必要とするが、面でAPIがsetHintOn/ setHintOffクライアントのために使用する方が簡単に見えますが、一つは、このようにそれを実装することができます。

private void setHint(boolean isHintOn){
    this.layer1.visible=isHintOn;
    this.layer2.visible=!isHintOn;
    this.layer3.visible=isHintOn;
}

public void setHintOn(){
   setHint(true);
}

public void setHintOff(){
   setHint(false);
}

したがって、パブリックAPIにはブール値パラメーターはありませんが、ここには重複するロジックはないため、新しい要件(質問の例のような)が到着したときに変更する場所は1つだけです。

これは逆の方法でも機能しsetStateます。上記のメソッドで2つの異なるコードを切り替える必要がある場合、そのコードを2つの異なるプライベートメソッドにリファクタリングできます。だから私見では、内部を見て「1つのパラメータ/ 1つの方法」と「0つのパラメータ/ 2つの方法」を決定するための基準を検索することは意味がありません。ただし、APIをコンシューマーの役割で表示する方法を見てください。

疑わしい場合は、「テスト駆動開発」(TDD)を使用してみてください。これにより、パブリックAPIとその使用方法について考えるようになります。


DocBrown、適切な区分線は、各状態の設定に複雑で、おそらくは不可逆的な副作用があるかどうかだとお考えですか?たとえば、ブリキに表示されていることを実行するフラグを単に切り替えているだけで、基礎となるステートマシンがない場合は、さまざまなステートをパラメーター化します。たとえば、のようSetLoanFacility(bool enabled)にメソッドをパラメーター化しないのは、ローンを提供したため、それを取り戻すのは簡単ではない可能性があり、2つのオプションは完全に異なるロジックを伴う可能性があり、別のCreateに移動したい/ Removeメソッド。
スティーブ

15
@Steve:実装側にある要件からAPIを設計しようとしています。まっすぐに:それはまったく無関係です。呼び出し側から使用しやすいパブリックAPIのバリアントを使用します。内部的には、パラメーターを指定して2つのパブリックメソッドから1つのプライベートメソッドをいつでも呼び出すことができます。またはその逆に、パラメータを持つ1つのメソッドに、異なるロジックを持つ2つのプライベートメソッドを切り替えることができます。
Doc Brown

@スティーブ:私の編集を参照してください。
Doc Brown

私はあなたのすべてのポイントを取ります-私は実際に発信者側からそれについて考えています(したがって、「錫に書かれていること」への私の参照)、発信者が通常各アプローチを使用することを期待する適切なルールを策定しようとしています。ルールは、呼び出し元が繰り返し呼び出しがべき等であり、状態遷移が制約なしで複雑な副作用なしであると期待するかどうかであるように思えます。部屋の照明スイッチのオン/オフの切り替えはパラメーター化され、地域の発電所のオン/オフの切り替えは複数の方法で行われます。
スティーブ

1
@Steveしたがって、ユーザーが特定の設定を確認する必要がある場合、Toggle()提供する適切な機能ではありません。それが全体のポイントです。呼び出し側が「それが最終的に何になるか」ではなく「変更」のみに関心Toggle()がある場合、追加のチェックと意思決定を回避するオプションです。私はそれを一般的なケースとは呼びませんし、正当な理由なしにそれを利用可能にすることもお勧めしませんが、ユーザーがトグルを必要とするなら、トグルを与えます。
カミルドラカリ

40

マーティン・ファウラーは、個別のsetOn() setOff()方法推奨する際にケント・ベックを引用していますが、これは不可侵と見なされるべきではないと言っています。

UIコントロールやデータソースなどのブールソースからデータを取得する場合はsetSwitch(aValue)

if (aValue)
  setOn();
else
  setOff();

これは、呼び出し元が簡単になるようにAPIを記述する必要があるため、呼び出し元がどこから来ているかがわかっている場合は、その情報を考慮してAPIを設計する必要があります。これは、発信者を両方の方法で取得する場合、両方のスタイルを提供することもあると主張しています。

別の推奨事項は、列挙値またはフラグ型使用してtruefalseより適切なコンテキスト固有の名前を付けることです。あなたの例では、showHinthideHint良いかもしれません。


16
私の経験では、答えで引用されているif / elseコードのために、setSwitch(value)はほとんどの場合、setOn / setOffよりも全体的なコードが少なくなります。私は、setSwitch(value)ではなくsetOn / setOffのAPIを提供する開発者を呪う傾向があります。

1
同様のレンズからそれを見る:値が何であるかをハードコードする必要がある場合、それはどちらでも簡単です。ただし、たとえばユーザー入力に設定する必要がある場合、値を直接渡すことができる場合は、ステップが節約されます。
ニックハートリー

@ 17of26は具体的な反例として(一方が他方よりも「依存している」ことを示すため)、AppleのAppKitには、ビューを再描画する-[NSView setNeedsDisplay:]必要があるYESかどうかを渡すメソッドがありますNO。指示する必要はほとんどないため、UIKitには-[UIView setNeedsDisplay]パラメーターがありません。対応する-setDoesNotNeedDisplayメソッドはありません。
グラハムリー

2
@GrahamLee、ファウラーの議論は非常に微妙で、本当に判断にかかっていると思います。bool isPremium彼の例ではフラグを使用しませんがBookingType bookingType、各予約のロジックがまったく異なる場合を除き、enum()を使用して同じメソッドをパラメーター化します。ファウラーが参照する「もつれたロジック」は、2つのモードの違いを確認したい場合に望ましいことがよくあります。そして、それらが根本的に異なる場合、パラメータ化されたメソッドを外部に公開し、個別のメソッドを内部に実装します。
スティーブ

3

投稿でAPIと実装の2つのことを混ぜていると思います。どちらの場合も、常に使用できる強力なルールはないと思いますが、これら2つのことを(可能な限り)個別に検討する必要があります。

まず、APIから始めましょう。

public void setHint(boolean isHintOn)

そして:

public void setHintOn()
public void setHintOff()

オブジェクトが提供するものと、クライアントがAPIをどのように使用するかに応じて、有効な代替手段となります。Docが指摘したように、ユーザーがすでにブール変数を持っている場合(UIコントロール、ユーザーアクション、外部、APIなどから)、最初のオプションはより理にかなっています、そうでなければ、クライアントのコードに余分なifステートメントを強制している。ただし、たとえば、プロセスを開始するときにヒントをtrueに変更し、最後にfalseに変更する場合、最初のオプションでは次のようになります。

setHint(true)
// Do your process
…
setHint(false)

2番目のオプションでは次のことができます。

setHintOn()
// Do your process
…
setHintOff()

どのIMOの方がはるかに読みやすいので、この場合は2番目のオプションを使用します。明らかに、両方のオプションを提供することを妨げるものは何もありません(または、もっと意味があれば、Grahamが言ったように列挙型を使用することもできます)。

ポイントは、オブジェクトの実装方法ではなく、オブジェクトが何をするか、クライアントがどのように使用するかに基づいてAPIを選択する必要があるということです。

次に、パブリックAPIの実装方法を選択する必要があります。メソッドsetHintOnsetHintOff公開APIとして選択し、例のようにこの共通ロジックを共有するとします。プライベートメソッド(Docからコピーしたコード)を使用して、このロジックを簡単に抽象化できます。

private void setHint(boolean isHintOn){
    this.layer1.visible=isHintOn;
    this.layer2.visible=!isHintOn;
    this.layer3.visible=isHintOn;
}

public void setHintOn(){
   setHint(true);
}

public void setHintOff(){
   setHint(false);
}

逆に、setHint(boolean isHintOn)API を選択したとしましょうが、ヒントをOnに設定することはOffに設定することとまったく異なるため、例を反転させましょう。この場合、次のように実装できます。

public void setHint(boolean isHintOn){
    if(isHintOn){
        // Set it On
    } else {
        // Set it Off
    }    
}

あるいは:

public void setHint(boolean isHintOn){    
    if(isHintOn){
        setHintOn()
    } else {
        setHintOff()
   }    
}

private void setHintOn(){
   // Set it On
}

private void setHintOff(){
   // Set it Off 
}

ポイントは、どちらの場合も、最初にパブリックAPIを選択してから、選択したAPI(および存在する制約)に合うように実装を調整し、逆ではないということです。

ちなみに、私は、同じことがあなたが行動を決定するブールパラメータの使用についてリンクポストに適用されると思うあなたは、特定のユースケースではなく、その特定の場合にかかわらず、いくつかのハードのルール(に基づいて決定する必要があり、すなわち、通常行うには正しいこと複数の機能に分割します)。


3
副次的な注意として、それが擬似ブロックのようなものである場合(最初に1つのステートメント、最後に1つのステートメント)、おそらくbeginendまたはその同義語を使用する必要があります。始まりには終わりがなければならず、その逆もあります。
ニックハートリー

私はNicに同意し、追加します:開始と終了が常に結合されていることを確認したい場合は、そのための言語固有のイディオムも提供する必要があります:C ++のRAII /スコープガードusing、C#のブロックwith、Pythonのステートメントコンテキストマネージャー、渡すラムダまたは呼び出し可能なオブジェクト(例えば、Rubyブロック構文)などの
本体

私は両方の点に同意します、私は他のケースを説明するために単純な例を与えようとしていました(あなたが二人が指摘したようにそれは悪い例ですが:))。
jesm00

2

まず最初に:コードが少し長くなるという理由だけで、コードのメンテナンス性が自動的に低下することはありません。重要なのは明快さです。

さて、あなたが本当にデータを扱うだけなら、あなたが持っているのはブール型プロパティのセッターです。その場合、その値を直接保存し、レイヤーの可視性を導き出すことができます。

bool isBackgroundVisible() {
    return isHintVisible;
}    

bool isContentVisible() {
    return !isHintVisible;
}

(レイヤーに実際の名前を付けるために自由を取りました-元のコードにこれがない場合は、それから始めます)

これには、setHintVisibility(bool)メソッドを使用するかどうかの問題が残ります。個人的には、showHint()and hideHint()メソッドに置き換えることをお勧めします-両方とも本当にシンプルで、レイヤーを追加するときにそれらを変更する必要はありません。ただし、明確な間違いではありません。

これで、関数を呼び出すことでこれらのレイヤーの可視性が実際に変更される場合、実際に動作します。その場合、個別の方法をお勧めします。


tl; dr:レイヤーを追加するときにそれらを変更する必要がないので、2つの機能に分割することをお勧めしますか?layer4が追加された場合、「this.layer4.visibility = isHintOn」も言う必要があるかもしれないので、同意するかどうかはわかりません。どちらかといえば、それはそれに対するデメリットです。レイヤーが追加されると、1つだけではなく2つの関数を編集する必要があります。
エルドリックアイアンローズ

いいえ(わかりやすくするため)(showHintsetHintVisibility)推奨します。OPが心配しているという理由だけで、新しいレイヤーについて言及しました。また、新しいメソッドを1つ追加するだけですisLayer4VisibleshowHintそしてhideHintちょうど設定isHintVisible/真属性をfalseにし、それは変わりません。
-doubleYou

1
@doubleYou、あなたはあなたがより長いコードが自動的に保守性を低下させるわけではないと言う。コードの長さは、保守の容易さと明確さの主な変数の1つであり、構造の複雑さによってのみ克服されていると言えます。より長く、構造的に複雑になったコードは、それに値するはずです。さもないと、単純な問題は、コードに値するよりも複雑な扱いを受けます。
スティーブ

@Steve私はあなたが物事を過剰に設計することができることに完全に同意します。すなわち、それを明確にすることなくコードを長くすることができます-ああ、あなたはコードを常に短くすることができます。
-doubleYou

このようなコードを取り、多くの行でそれを書き換え- 「コードゴルフ」と考えて@Steve 通常、それをより明確にします。「コードゴルフ」は極端ですが、コンパイラーが十分に最適化されていないため、すべてを1つの巧妙な表現に詰め込むことは「優雅」で、おそらくもっと速いと考える多くのプログラマーがまだいます。
ブラックジャック

1

2番目の例では、ブールパラメータで問題ありません。既に理解したように、ブール値パラメーター自体には問題はありません。問題のあるフラグに基づいて動作を切り替えることです。

ただし、最初の例は、ネーミングがセッターメソッドを示すため問題がありますが、実装は異なるようです。したがって、動作切り替えアンチパターン、誤解を招くような名前のメソッドがあります。しかし、メソッドが実際に通常のセッター(動作の切り替えなし)である場合、問題はありませんsetState(boolean)。2つのメソッドを持つ、setStateTrue()setStateFalse()だけ不なしの利益のために物事を複雑にしています。


1

この問題を解決する別の方法は、各ヒントを表すオブジェクトを導入し、そのヒントに関連付けられたブール値を決定する責任をオブジェクトに持たせることです。この方法では、2つのブール状態を持つのではなく、新しい順列を追加できます。

たとえば、Javaでは次のことができます。

public enum HintState {
    SHOW_HINT(true, false, true),
    HIDE_HINT(false, true, false);

    private HintState(boolean layer1Visible, boolean layer2Visible, boolean layer3Visible) {
         // constructor body and accessors omitted for clarity
    }
}

そして、呼び出し元のコードは次のようになります。

setHint(HintState.SHOW_HINT);

実装コードは次のようになります。

public void setHint(HintState hint) {
    this.layer1Visible = hint.isLayer1Visible();
    this.layer2Visible = hint.isLayer2Visible();
    this.layer3Visible = hint.isLayer3Visible();
}

これにより、強く型付けされた名前付き意図を対応する状態セットに明確にマッピングする新しいデータ型を定義する代わりに、実装コードと呼び出し元コードを簡潔に保ちます。それはすべての方が良いと思います。


0

だから私の質問は、ブールパラメータが値のみを決定するために使用され、動作ではない場合(たとえば、そのパラメータのif-elseなし)、そのブールパラメータを削除することはまだ推奨されていますか?

そのようなことについて疑問があるとき。スタックトレースがどのようになるかを想像するのが好きです。

何年もの間、私はセッターゲッターと同じ機能を使用するPHPプロジェクトに取り組みました。nullを渡した場合は値を返し、そうでない場合は設定します。で動作するように恐ろしいことでした

スタックトレースの例を次に示します。

function visible() : line 440
function parent() : line 398
function mode() : line 384
function run() : line 5

内部状態がわからず、デバッグが難しくなりました。他にも多くのマイナスの副作用がありますが、冗長な関数名に価値があり、関数が単一のアクションを実行するときの明確さを確認してください。

次に、ブール値に基づいてAまたはBの動作を行う関数のスタックトレースを使用した作業の様子を示します。

function bar() : line 92
function setVisible() : line 120
function foo() : line 492
function setVisible() : line 120
function run() : line 5

あなたが私に尋ねる場合、それは混乱しています。同じsetVisible行から2つの異なるトレースパスが生成されます。

質問に戻りましょう。スタックトレースがどのように見えるか、何が起こっているかを人に伝える方法を想像し、将来の人がコードをデバッグするのを手伝っているかどうかを自問してください。

ヒントを次に示します。

  • 引数値を知る必要なく意図を暗示する明確な関数名。
  • 関数は単一のアクションを実行します
  • 名前は突然変異または不変の行動を意味します
  • 言語およびツールのデバッグ機能に関連するデバッグの課題を解決します。

顕微鏡下ではコードが過剰に見えることもありますが、より大きな図に戻ると、最小限のアプローチでコードが消えます。あなたがそれを維持できるように目立つためにそれが必要な場合。多くの小さな関数を追加すると過度に冗長に感じるかもしれませんが、より大きなコンテキストで広く使用すると、保守性が向上します。


1
setVisibleスタックトレースについて私を混乱させているのは、呼び出しを行うと呼び出しsetVisible(true)が発生するように見えることですsetVisible(false)(または、そのトレースをどのように発生させたかに応じて、その逆)。
デビッドK

0

何かの動作を変更するbooleanためのフラグとしてメソッドにパラメーターを渡すほとんどすべての場合、これを行うためのより明示的でタイプセーフな方法を検討する必要があります。

Enum状態を表すを使用する以外に何もしなければ、コードの理解度が向上します。

この例では、次のNodeクラスを使用していますJavaFX

public enum Visiblity
{
    SHOW, HIDE

    public boolean toggleVisibility(@Nonnull final Node node) {
        node.setVisible(!node.isVisible());
    }
}

多くのJavaFXオブジェクトに見られるように、常に優れています:

public void setVisiblity(final boolean flag);

しかし、フラグが最も明示的で最も冗長ではないため、フラグが立っている状況に最適なソリューションだ.setVisible()と思います。.setHidden()boolean

複数の選択があるものの場合、この方法で行うことはさらに重要です。EnumSetこのためだけに存在します。

エド・マンは、まさにこの主題に関する本当に良いブログ投稿をしています。私は彼の言うことを言い換えようとしていたので、努力を繰り返さないために、この答えの補遺として彼のブログ投稿へのリンクを投稿するだけです。


0

(ブール型)パラメーターを渡すインターフェースと、そのパラメーターなしのオーバーロードされたメソッドを渡すインターフェースのアプローチを決定するときは、消費クライアントに注目してください。

すべての使用法が定数値(たとえば、true、false)を渡す場合、それはオーバーロードを主張します。

すべての使用法が変数値を渡す場合は、パラメーターアプローチを使用したメソッドを主張します。

どちらの極端も当てはまらない場合は、クライアントの使用法が混在していることを意味するため、両方のフォームをサポートするか、クライアントの一方のカテゴリーを他方のスタイル(より不自然なスタイル)に適応させるかを選択する必要があります。


統合システムを設計していて、最終的にコードのプロデューサーとコードの「消費クライアント」の両方である場合どうなりますか?消費クライアントの立場に立っている人は、あるアプローチを別のアプローチよりも優先させるにはどうすればよいでしょうか?
スティーブ

@Steve、消費クライアントとして、定数または変数を渡すかどうかを知っています。定数を渡す場合は、パラメーターなしのオーバーロードを優先します。
エリックエイド

しかし、なぜそうなるべきかを明確にすることに興味があります。限られた数の定数に列挙型を使用しないのはなぜですか。これは、この種の目的のために正確に設計されたほとんどの言語の軽量構文であるためです。
スティーブ

@Steve、設計時/コンパイル時にクライアントがすべての場合に定数値(true / false)を使用することがわかっている場合、1つの一般化されたメソッド(パラメーターを取る)ではなく2つの異なる特定のメソッドがあることが示唆されます。私は、パラメーター化されたメソッドが使用されていない場合、パラメーター化されたメソッドの一般性を導入することに反対します。これはYAGNIの引数です。
エリックエイド

0

設計には2つの考慮事項があります。

  • API:ユーザーに提示するインターフェース、
  • 実装:明快さ、保守性など...

それらを混同しないでください。

それは完全に大丈夫です:

  • 単一の実装へのAPIデリゲートに複数のメソッドがあり、
  • 条件に応じて、複数の実装へのAPIディスパッチで単一のメソッドを使用します。

そのため、API設計のコスト/メリットと実装設計のコスト/メリットのバランスをとろうとする議論は疑わしく、慎重に検討する必要があります。


API側で

プログラマーとして、私は一般的にプログラム可能なAPIを好みます。値を転送できる場合のコードは、どの関数を呼び出すかを決定するために値にif/ switchステートメントが必要な場合よりもはるかに明確です。

各関数が異なる引数を予期する場合、後者が必要になる場合があります。

したがって、あなたの場合、単一の方法のsetState(type value)方が良いようです。

しかし、無名のより悪い何もないtruefalse2、等...これらの魔法の値は、自分では意味を持ちません。避け原始的な強迫観念を、そして強い型付けを受け入れます。

したがって、API POVから、次が必要ですsetState(State state)


実装側

もっと簡単なことをすることをお勧めします。

メソッドが単純な場合は、まとめておくのが最適です。制御フローが複雑な場合は、それぞれがサブケースまたはパイプラインのステップを処理する複数のメソッドに分けるのが最善です。


最後に、グループ化を検討します

あなたの例(読みやすくするために空白を追加):

this.layer1.visible = isHintOn;
this.layer2.visible = ! isHintOn;
this.layer3.visible = isHintOn;

layer2トレンドに逆らうのはなぜですか?それは機能ですか、それともバグですか?

2つのリスト[layer1, layer3][layer2]を持ち、それらがグループ化されている理由を示す明示的な名前を付けて、それらのリストを反復処理することは可能ですか?

例えば:

for (auto layer : this.mainLayers) { // layer2
    layer.visible = ! isHintOn;
}
for (auto layer : this.hintLayers) { // layer1 and layer3
    layer.visible = isHintOn;
}

コードはそれ自体を物語っています。2つのグループがあり、それらの動作が異なる理由は明らかです。


0

setOn() + setOff()vsのset(flag)質問とは別に、ここではブール型が最適かどうかを慎重に検討します。3番目のオプションは決してないでしょうか?

ブール値の代わりに列挙型を検討する価値があるかもしれません。拡張性を許可するだけでなく、これによりブール値を間違った方法で取得することも難しくなります。例:

setHint(false)

setHint(Visibility::HIDE)

列挙型を使用すると、誰かが「必要な場合」オプションが必要だと判断した場合に拡張するのがはるかに簡単になります。

enum class Visibility {
  SHOW,
  HIDE,
  IF_NEEDED // New
}

setHint(false)
setHint(true)
setHintAutomaticMode(true) // New

0

...によれば、私はブールパラメータを使用して動作を決定することを避けることの重要性を知っています

この知識を再評価することをお勧めします。

まず第一に、あなたがリンクしたSEの質問であなたが提案しているという結論がわかりません。彼らは主に、メソッド呼び出しのいくつかのステップに渡ってパラメータを転送することについて話しているので、そこでは非常に連鎖的に評価されます。

この例では、メソッド内でパラメーターを評価しています。その点で、他の種類のパラメーターとまったく違いはありません。

一般に、ブール値パラメーターを使用してもまったく問題はありません。そして、明らかに、どんなパラメーターでも振る舞いを決定しますか、またはそもそもなぜそれを持っているのでしょうか?


0

質問を定義する

あなたのタイトルの質問は「[...]は間違っていますか?」です。-しかし、「間違った」とはどういう意味ですか?

C#またはJavaコンパイラによると、それは間違いではありません。私はあなたがそれを知っていると確信しており、それはあなたが求めているものではありません。それ以外は怖いです、nプログラマーにはn+1異なる意見しかありません。この回答は、Clean Codeがこのことについて述べている本を示しています。

回答

Clean Codeは一般的に関数の引数に対して強い主張をします:

引数は難しいです。彼らは多くの概念的な力を取ります。[...]読者はそれを見るたびに解釈しなければならなかったでしょう。

ここでの「リーダー」はAPIコンシューマーです。また、次のコーダーになることもあります。このコーダーは、このコードが何をするのかまだわかりません。彼らはいずれかを経由します2つの機能別にまたは貫通二度1つの機能維持に一度、trueと一度false心に。
要するに、できるだけ少ない引数を使用してください

フラグ引数の特定の場合は、後で直接対処されます。

フラグ引数はいです。ブール値を関数に渡すのは本当にひどい習慣です。メソッドのシグネチャがすぐに複雑になり、この関数は複数のことを行うと大声で宣言します。フラグがtrueの場合は1つのことを行い、フラグがfalseの場合は別のことを行います!

質問に直接答えるには:
Clean Codeよると、そのパラメーターを削除することをお勧めします。


追加情報:

あなたの例はかなり単純ですが、コードに伝播する単純さを見ることができます:パラメーターなしの関数は単純な割り当てのみを行い、他の関数は同じ目標を達成するためにブール演算を行う必要があります。この単純化された例では単純なブール演算ですが、実際の状況では非常に複雑になる可能性があります。


ここでは、APIユーザーに依存させるべきであるという多くの議論を見てきました。多くの場所でこれを行わなければならないのは馬鹿げているからです。

if (isAfterSunset) light.TurnOn();
else light.TurnOff();

私はない何か非最適がここで起こっていることに同意します。見るのはあまりにも明白かもしれませんが、最初の文は「ブールパラメータを使用して動作を決定することの重要性」に言及しており、それが質問全体の基礎となっています。私は、APIユーザーにとってそれを簡単にするのが悪いことをする理由は見当たりません。


テストを行うかどうかはわかりません-その場合、これも考慮してください:

テストの観点からは、議論はさらに困難です。引数のさまざまな組み合わせがすべて適切に機能することを確認するために、すべてのテストケースを記述することの難しさを想像してください。引数がない場合、これは簡単です。


あなたは本当にここにledeを埋めました:「...あなたの非常に最初の文は「行動を決定するためにブール値パラメーターを使用することの回避の重要性」に言及しており、それは質問全体の基礎です。そのことをAPIユーザーにとって簡単にするのが悪いことにする理由。」 これは興味深い点ですが、最後の段落で自分自身の議論を台無しにしてしまいます。
ワイルドカード

リードを埋めましたか?この答えの核心は、「できるだけ少ない引数を使用する」ことです。これについては、この答えの前半で説明します。その後のすべては単なる追加情報です。矛盾する引数(OPではなく別のユーザーによる)に反論し、誰にも当てはまらないものです。
R.シュミッツ

最後の段落は、タイトルの質問が十分に定義されていないために答えられないことを明確にしようとしています。OPは、それが「間違っている」かどうかを尋ねますが、誰または何に応じて言うことはありません。コンパイラによると?有効なコードのように見えるので、間違っていません。本Clean Codeによると?フラグ引数を使用するため、「間違っています」。ただし、実用的>独断的であるため、代わりに「推奨」と記述します。もっと明確にする必要があると思いますか?
R.シュミッツ

待って、あなたの答えの防御は、タイトルの質問があまりにも不明瞭で答えられないということですか?:Dわかりました...私は実際に私が引用したポイントは興味深い新鮮なテイクだと思った。
ワイルドカード

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