web-dev-qa-db-ja.com

継承を使用する場合、「ブール値フィールド」を使用する場合

私たちのRailsアプリケーションでは、通知を追加しています。これらの一部はblockingです:それらは追加されたリソースの進行を停止します。そのリソースに関するいくつかの情報が欠落しているためです。

その他の通知は単純な通知であり、情報を提供するだけです。

今日、私はチームの他のプログラマーと話し合いました。私はこのような継承構造を作成しました:

enter image description here

ただし、彼はむしろ、各通知のブール値を返すメソッドとしてblockingを追加し、通知の親クラス内でブロックしているサブクラスのリストを指定することを望んでいます。

これらのアプローチの違いはそれほど大きくありません。私のアプローチでは、このリストを指定する必要はなく、ルートクラスをよりクリーンに保ちます。一方、Notification::Blockingで現在行われている特別なロジックもそれほど大きくありません。

この問題にはどのような抽象化が適していますか?

18
Qqwy

基本クラスが派生クラスを認識しないようにする必要があります。新しい派生クラスを作成するたびにリストに追加することを忘れないようにする必要があるため、密結合が導入され、メンテナンスの頭痛の種となります。

また、このクラスを複数のプロジェクトで使用する場合は、Notificationクラスを再利用可能なパッケージ/アセンブリに入れることができなくなります。

本当に単一の基本クラスを使用したい場合、これを解決する別の方法は、基本の通知クラスに仮想プロパティまたはメソッドIsBlockingを追加することです。派生クラスは、trueまたはfalseを返すようにオーバーライドできます。基本クラスが派生クラスを知らなくても、単一のクラスソリューションになります。

35
17 of 26

そして、Notification親クラス内でブロックしているサブクラスのリストを指定します。

それは非常に独特に見え、特定のコードのにおいです。

クラス間の動作に違いがあり、これらすべての通知を同じ方法で(つまり、polymorphismを使用して)処理したい場合は、サブクラスを提供します。

13
Brian Agnew

既存の回答とは逆に、使用するモードを動的に変更する必要がある場合(たとえば、ブロックするタイプのリストを提供する構成ファイルを介して)、ブールプロパティを使用することをお勧めします。そして、そうではありません)。

とはいえ、この状況でも、Decoratorオブジェクトを使用する方が良いデザインになる可能性があります。

7
Jules

私は最初に「両方」を使用することを考えましたが、それはブロック通知に関して他にどれだけ特別なものであるかに依存すると思います。

class Notification
 virtual Boolean Blocking{get return false;}

class BlockingNotification inherits Notification
 virtual overrides Boolean Blocking{get return true;}

そうすれば、n.Blockingまたはn is BlockingNotification(すべて疑似コード)、ただし、クラスに状況依存のBlocking値の実装を許可する場合は、その値を毎回チェックする必要があるため、BlockingNotificationクラスはあまり役に立たなくなります。

いずれにせよ、Blockingの基本クラス実装に派生クラスについて知らせてほしくない他の回答にも同意します。

1
Mark Hurd

2つの基本クラスとそれぞれの複数のインスタンスを作成する代わりに、ブール値を使用して1つの通知クラスを作成し、通知がブロックされているかどうかと、通知をユーザーに伝えるために必要なその他の情報を示します。

これにより、通知の処理と表示に1つのコードセットを使用して、コードの複雑さを軽減できます。

0
Trisped