web-dev-qa-db-ja.com

より良いShow()+ Hide()またはSetVisible(bool visible)ですか?

何が良いのか、なぜですか? (インターフェース設計の観点から):

a)Show()およびHide()関数を2つ持つ

b)SetVisible(bool visible)関数を1つ持つ

編集:たとえば、一部のオブジェクトには可視性の状態があり、この関数はそれを変更するために使用されます。

c)3つのShow()Hide()SetVisible(bool visible)関数をすべて持つ

59
user3123061

私はSetVisible(bool visible)を好みます。これにより、次のようなクライアントコードを記述できます。

SetVisible(DetermineIfItShouldBeVisible());

書く必要はありません

if (DetermineIfItShouldBeVisible()) {
    Show();
} else {
    Hide();
}

SetVisibleアプローチを使用すると、実装が容易になる場合もあります。たとえば、特定の具象クラスが単純にメソッドをその複合クラスに委任する場合、SetVisibleは実装するメソッドが1つ少ないことを意味します。

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
81
Josh Kelley

同じことをするために複数の機能を提案することは良いことだと示唆するすべてのポスターに同意しません。 3つの関数が1つではなく膨らんでいるように見えないかもしれませんが、クラスには多くのそのような関数(たとえば、setEnabledenabledisable)が存在する可能性があることに注意してください。したがって、このアプローチは最終的にmuchより大きなクラスインターフェイスになります。さらに、クラス内の類似のサウンド関数/プロパティ/何でも結局最終的になる可能性が高く、関数の乗算により、どれが何に対応するかがさらに不明瞭になります。

プロパティをサポートする言語では、これらが推奨されますが、JavaもC++もそうではないので、私はそれが問題点だと思います。

私はsetVisible()がこれらの理由で好まれるべきだと思います:

  1. 逆関数が何であるかはすぐに分かります。 setVisible(false)を逆にするには、setVisible(true)を呼び出しますが、hide()の反対は簡単にreveal()になります。
  2. コードでどの状態をとるべきかを決定するときは常に、プログラム的に単純です。つまり、ifステートメントを使用する代わりにsetVisible(wantToSee)を呼び出すことができます。
  3. 類似の関数が複数あると、setX()形式で一般化され、一貫した関数のセットを使用できるようになります。一方、動詞を使用したアプローチでは、自分が何をしているかわからない場合に特定が困難な関数のホストが生成されます。探している。 APIの一貫性により、APIの学習と覚えがかなり容易になります。
35
Jack Aidley

それは、コンテキストでどのように表示および非表示が意味するかによって異なります。まず、どちらが「主な方法」であるかを理解し、それを開発することに焦点を当てる必要があります。

  • 選択する理由setVisible(bool)
    • 単純なビットフリップであるか、オブジェクトが主に状態を保持しています
    • オブジェクトはほとんどの時間をCRUDフレームワークに費やします
    • 表示と非表示の間に簡単に共有できるコードがたくさんあります
  • show()hide() を選択する理由
    • オブジェクトがすべてのコンテナーをtheir可視性状態についてチェックする必要がある場合など、実行されている重要な副作用または多くのロジックがあります。遷移アニメーションをトリガーします。
    • intentを表現することが重要なドメインモデルの一部ですか?

さて、これで「ゴールドスタンダード」のコアをコード化したので、他のスタイルでシンコンビニエンスメソッドを追加する価値があるかどうかを判断して、オブジェクトを使用する人にとって使いやすいようにする必要があります。

  • setVisible(bool) の利便性
    • 些細な条件があり、可視性のみに影響するifステートメントを回避できます(例:setVisible(a==b)
    • 特定のゲッター/セッターフレームワークに接続できます。
  • show()およびhide() の利便性
    • ファーストクラスの関数とコールバックを備えた言語で役立ちます(例:onSuccess(widget.show)
    • スタックトレースとパフォーマンスプロファイリングを使用すると、プログラムが何をしようとしているかをすばやく確認できるので、はるかに読みやすくなります。

TLDR:最も重要なものを見つけて実装し、他のスタイルをシンコンビニエンスメソッドとして追加する価値があるかどうかを確認します。

19
Darien

「3つすべて」と言います。

Show()Hide()は、SetVisible(true)SetVisible(false)よりも扱いやすい傾向があります。ただし、可視性を論理的に設定する場合は、そのboolの周囲にifを作成するのではなく、boolを取るメソッドを使用することをお勧めします。

ロジックを重複させずに定型文を最小限に抑えて、3つすべてをサポートできます。

void Show() {
    foo.Show();
    bar.Show();
}

void Hide() {
    foo.Hide();
    bar.Hide();
}

void SetVisible(bool visible) {
    if (visible) {
        Show();
    } else {
        Hide();
    }
}

または、ラップしているものにもっとSetVisible- ish APIがある場合:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
12
Garry Shutler

Hide()を使用するよりも何が起こっているかを理解する方が簡単であるため、Show()/SetVisible(true)の代替案は魅力的であると考えていますが、たくさんの条件文。

その場合は、SetVisibleへの入力として列挙型を使用することをお勧めします。これにより、SetVisible(Visibility.Visible)またはSetVisible(Visibility.Hidden)が得られます。実行中のアクションを瞬時に読み取ることができる単一の機能があります。

Javaの命名規則を使用すると、おそらくsetVisible(Visibility.VISIBLE)またはsetVisible(Visibility.HIDDEN)になります。

5
Gabe

私はshow()とhide()を好みます。実際、1つのブール値を受け取るすべてのメソッドは、APIの意図をよりよく表す2つのメソッドに変更できます。たとえば、クリーンなコードのRobert Martinは、引数が1つのメソッドよりも引数がゼロのメソッドを推奨しています。

私にとってもう1つの重要な議論は可読性です。私の意見では、良いコードは散文のように読むことができます。「main_window hide」ではなく「main_window setVisible false」のような本当に奇妙な散文です。より自然な言語を使用することが完全に可能な場合、ソフトウェアプログラムでの言語構築。

5
AlfredoCasado

私は、メソッドが表現力豊かであればあるほど、コードが読みやすくなり、その結果、保守しやすくなると信じています。次の2つのケースを検討してください。

ケース1:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  customerPanel.setVisible(customer.isCustomerEnabled());
}

ケース2:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  //always show customer panel
  customerPanel.setVisible(true);
}

最初のケースでは、関数「setVisible」が何をしているのかは明らかですが、それを読みたい場合は、次のようにします。

顧客が有効な場合は顧客パネルを表示するように設定し、顧客が無効な場合は非表示に設定します。

もっと説明的に言うと:

  • お客様のステータスを確認します。
    • 顧客が有効な場合は、顧客のパネルを表示します
    • それ以外の場合は、それを非表示にします

「ケース1」機能を次のように変更します。

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  if(customer.isCustomerEnabled()){
    customerPanel.Show();
  }
  else{
    customerPanel.Hide();
  }
}

より多くのコードを生成しますが、より読みやすくなります。

2番目のケースには明らかな欠陥があります。つまり、パネルを表示したいことはすでにわかっているので、「表示」機能を使用しないのはなぜですか。

「setVisible」の使用が完全に間違っていると言っているわけではありませんが、時間の経過とともに作成されていないコードを読み取ろうとすると混乱し、「関数は1つの操作のみを実行する」という規則に準拠しません。

5
OKAN

ダリエンの答えには同意しますが、C#プログラマの観点から見た視点を追加したいと思いました。

「setXXX」というコードが表示されたら、それを読んでそれが物事に値を設定していると言いますが、これはその値を設定する以外にその物に副作用があるとは思わず、べき等であることを期待しています(つまり、同じ値を設定し続けることができ、問題ありません)。フィールドにアクセスするようなものです。通常、「setXXX」とともに「getXXX」メソッドが表示されることも期待しています。

これがJavaとC++で期待するものかどうかはわかりませんが、C#ではプロパティと呼ばれますが、C#ではこれが簡単な手形ですが、これは次のようなものです。プロパティの使用方法に関する素晴らしいガイダンス( http://msdn.Microsoft.com/en-us/library/ms182181.aspx )。

このビューが与えられた場合、選択するインターフェイスは、(そのフィールド値を変更する以外に)副作用があるかどうかに完全に依存します。

アクションの実行に副作用がある場合、たとえばダイアログボックスが表示される場合は、「Show()」と「Hide()」を使用します。

副作用がない場合は、「ウィジェット」の可視性を設定していて、そのウィジェットがその状態に応じて何かをレンダリングする場合は、setVisibilityまたはsetIsVisibleを使用します。 (私はそれをSetVisibleとは呼びません)。

C#(Javaについては不明)では、オブザーバーパターンを採用するのが一般的です。オブザーバーパターンでは、UIフレームワークがオブジェクトの変更をリッスンし、Visibilityなどのプロパティが変更されたときにUIを自動的に再レン​​ダリングします。つまり、setIsVisibleを呼び出して値を設定すると、副作用があるように見えますが、私の定義ではそうではありません。ウィジェットのコントラクトは、「IsVisible」を表すフィールド値を設定することによって実現されます。

別の言い方をすると、フォームが表示される前に、フォーム上のラベルの可視性を切り替えてもかまいません。つまり、label.getIsVisible == trueですが、フォームは表示されません。

フォームが表示されていないときにHide()を呼び出すのは私にとっては問題です。

3

少し変更したインターフェースをお勧めします:

_Show();
Hide();
ToggleVisible();
ToggleVisible(bool visible);
_

より良い名前

これらのメソッド名は、開発者が何を実行する必要があるかに基づいて、使用するメソッドを決定するのに役立ちます。 SetVisible(bool visible)は、Show()およびHide()と同じセマンティックな意味を伝えるため、開発者を混乱させる可能性がありますが、Toggle()は、アクションを決定します。したがって、各メソッドをいつ使用するかは、開発者にとって直感的になります。

コードの冗長性の低下

インターフェースに複数のメソッドがあることの利点は、呼び出し側のコードが簡素化されることです。 Show()Hide()を公開することもできますが、次のようになります。

  • 舞台裏で実際の作業を行うには(またはSetVisible()Show()の冗長コードを記述する)、何らかのHide()プライベートメソッドが必要になる可能性があります。
  • 呼び出しコードには、使用するメソッドを選択するためだけに多くの冗長なif/elseブロックがある場合があります。これは私の意見ではコードを膨らませます。
  • 私がコンシューマーだった場合、コードの膨張を回避するために、SetVisible()(またはToggle())がすでに行っていることを行う独自のラッパー関数を作成するだけです(冗長なコードは嫌いです)。 。したがって、おそらくすでに存在するであるメソッドを、実装のプライベートメソッドとして複製します。
2
gilly3

可視性を2回切り替えると(表示と再非表示、または非表示と再表示)、操作が実行される前と基本的に同じ状態になる場合にのみ、SetVisible(bool)を使用することをお勧めします( 「自動的に」発生することが期待できる場合は、何かを表示して再非表示にしたり、その逆でオブジェクトを再描画する必要がある場合は問題ありません)。オブジェクトの非表示と表示が1ビットの状態を変更する以外の効果がない場合は、可視性パラメーターを受け入れるいくつかのメソッドを用意することは外部コードにとって意味があり、そのようなコードの記述はSetVisible

オブジェクトを非表示にして再表示すると、Zオーダーの変更などの副作用が生じる可能性がある場合、そのようなアクションは別のメソッドで実行される可能性が高くなります。そのような場合、「可視性」パラメーターを受け入れる外部メソッドの有用性は制限されるため、それらを容易にする利点はほとんどありません。さらに、SetVisibleメソッドは、(誤って)オブジェクトの可視性の変更を副作用なしで実行できることを示唆します。

0
supercat