クラスが単一の責任原則を満たしているかどうかを判断する方法は?


34

単一責任の原則は、高い結束の原則に基づいています。この2つの違いは、SRPに準拠するクラスの責任は1つだけであるのに対し、非常に凝集性の高いクラスには密接に関連する一連の責任があることです。

しかし、特定のクラスに一連の責任があり、したがって非常に凝集性があるのか​​、それとも1つの責任しか持たず、したがってSRPに準拠するのかをどのように判断するのでしょうか。言い換えれば、クラスが非常にきめ細かいと考える人もいるかもしれません(クラスがSRPに準拠していると考える人もいるかもしれませんが)



回答:


21

はい、それは非常に主観的であり、プログラマーが入る多くの白熱した議論の対象です。

答えは1つではなく、ソフトウェアがより複雑になると答えが変わる可能性があります。かつて単一の明確に定義されたタスクであったものが、最終的には複数の不十分に定義されたタスクになる可能性があります。それは常に摩擦です。プログラムをタスクに分割する適切な方法をどのように選択しますか?

私が与えることができる唯一のアドバイスについてはこれです:あなた(そしてあなたの同僚)の最高の判断を使用してください。そして、間違いをすぐに見つければ(通常)修正できることを忘れないでください。


コンピュータサイエンスが実際の科学に似ていればいいのにと思います。主観は実際の科学には場所がありません。SOLIDの原則はそれ自体で問題ありませんが、主観性を最小化し、客観性を最大化するために反復する必要があります。それはまだ起こっていないので、現実世界での彼らの正当性に疑問を抱かせる。
-DarkNeuron

13

発祥ボブ・マーティン(アンクルボブ)、SOLIDその原則SRP最初であるが、(私は言い換えています、実際の言葉を思い出すことができない)、このことについてこう述べています。

クラスに変更する理由は1つだけです

複数の理由がある場合、SRPに準拠しません。


14
それは本当に定義を繰り返しているだけですが、実際にsrpに固執することはまだかなり主観的です。
アンディ14年

7

いくつかの経験則を説明できます。

  • クラスに名前を付けるのは簡単ですか?クラスに名前を付けるのが難しい場合は、おそらくやりすぎです。
  • クラスにはいくつのパブリックメソッドがありますか?7 +/- 2は良い経験則です。クラスにそれ以上ある場合は、クラスをいくつかのクラスに分割することを検討する必要があります。
  • 個別のコンテキストで使用されるパブリックメソッドの凝集グループはありますか?
  • プライベートメソッドまたはデータメンバーはいくつありますか?クラスの内部構造が複雑な場合は、おそらくリファクタリングして、内部が別の小さなクラスにパッケージ化されるようにする必要があります。
  • そして、最も簡単な経験則:クラスの大きさは?数百行を超える単一のクラスを含むC ++ヘッダーファイルがある場合は、おそらく分割する必要があります。

2
2番目のポイントについては、uxmyths.com / post / 931925744
キャメロンマーティン

7
7 +/- 2については強く反対します。単一の責任原則は、任意の数字ではなく、意味の結合に関するものです。
ジャックB

1
経験則は、独立した科学的証拠を必要としません。現代の科学的手法は何世紀も昔のことであり、建築と工学は何千年も昔のことです。パブリックメソッドの経験則は「数個」であり、「少数」のパラメーターはありません。他のニュースでは、一部の子供の絵はそうでなければ人々の腕が頭から出てこないことを示しているにもかかわらず[要出典]。
abuzittin gillifirca

@CameronMartin設定に応じて、クラスのインターフェイスはすぐに読むことができる場合とできない場合があります。UIを検索することは、コードを書くこととほとんど同じではありません。1分ごとにドキュメントを参照する必要がある場合、少なくとも実際の作業にかかる時間は2倍になります。
18

6

単一責任原則では、各ソフトウェアモジュールには変更する理由が1つだけあるべきであると述べています。ボブおじさんが最近の記事で「変更する理由」を説明し、

ただし、この原則について考えると、変更の理由は人であることに注意してください。変更を要求するのは人々です。そして、多くの異なる人々がさまざまな理由で関心を持っているコードを混ぜることによって、それらの人々またはあなた自身を混乱させたくありません。

さらに彼は、一例で概念を説明HERE


それは男自身が書いた素晴らしい記事です。
MrDustpan 16

4

これに答えるには、一歩下がって、単一の責任原則の意図を考慮してください。そもそもなぜそれが推奨される設計原則なのですか?

原則の目的は、コードベースを「区分化」することであるため、単一の「責任」に関連するコードは単一のユニットに分離されます。これにより、コードの検索と理解が容易になります。さらに重要なことは、「責任」の変更がコードの単一ユニットにのみ影響することを意味します。

システムで絶対に必要としないのは、1つの小さなチャンスによって、コードの明らかに無関係な他の部分が失敗したり、動作が変更されたりする場合です。SRPは、バグと変更を分離するのに役立ちます。

それでは、「責任」とは何でしょうか?これは、他の変更とは独立して変更される可能性があるものです。いくつかの設定をXML構成ファイルに保存し、ファイルからそれらを読み戻すことができるプログラムがあるとします。これは単一の責任ですか、それとも「ロード」と「保存」の2つの異なる責任ですか?ファイル形式または構造に何らかの変更を加えるには、ロードロジックと保存ロジックの両方を変更する必要があります。したがって、単一のクラスによって表されるべき単一の責任です。次に、一部のデータをCVS、Excel、およびXML形式でエクスポートできるアプリを検討します。この場合、1つの形式が他の形式に影響を与えることなく変更できることは容易に想像できます。CVS形式で区切り文字を変更する場合、Excel出力には影響しません。


2

OOは、クラスはデータと機能のグループであると言います。この定義には、主観的な解釈の余地が十分にあります。

クラスは明確かつ簡単に定義する必要があることを知っています。しかし、そのようなクラスを定義するには、クラスが設計全体にどのように適合するかという明確な概念が必要です。逆説的に、アンチパターンと見なされるウォーターフォールタイプの要件がなければ、これを達成することは困難です。

MVCのようなほとんどの場合に機能するアーキテクチャを使用して、クラスデザインを実装できます。MVCアプリケーションでは、データ、ユーザーインターフェイス、および両者が通信するための要件のみを持っていると想定しています。

基本的なアーキテクチャにより、単一責任ルールが破られているケースを簡単に特定できます。EGユーザーコントロールのインスタンスをモーダルに渡す。


1

議論のために、AudioSampleBufferと呼ばれるJUCEのクラスを取り上げます。現在、このクラスは、オーディオのスニペット(またはかなり長いスニペット)を保持するために存在します。チャネル数、サンプル数(チャネルごと)がわかっているので、変数の数値表現やワードサイズではなく、32ビットIEEE floatにコミットされているようです(ただし、これは問題ではありません)。numChannelsまたはnumSamplesおよび特定のチャンネルへのポインターを取得できるメンバー関数があります。AudioSampleBufferを長くしたり短くしたりできます。前者はバッファをゼロで埋め、後者は切り捨てると仮定します。

JUCEが使用する特別なヒープにスペースを割り当てるために使用されるこのクラスのプライベートメンバーがいくつかあります。

しかし、これはAudioSampleBufferが欠けているものです(そして、私はJulesとそれについていくつかの議論をしました):と呼ばれるメンバーSampleRateどうしてそれが欠けているのでしょうか?

AudioSampleBufferが果たす必要のある唯一の責任は、サンプルが表す物理的なオーディオを適切に表すことです。サウンドファイルまたはストリームから読み取るものからAudioSampleBufferを入力する場合、AudioSampleBufferとともに取得してサンプルレートを知る必要がある処理メソッド(フィルターなど)に渡す必要がある追加のパラメーターがあります。最終的に、バッファを再生して聞く(または他の場所にストリームする)メソッドに。なんでも。

しかし、あなたがしなければならないことは、このSampleRateを渡し続けることです。定数 44100.0fが関数に渡されるコードを見てきました。これは、プログラマが他に何をすべきかを知らなかったためです。

これは、単一の責任を果たさない例です。


1

あなたが言ったことに基づいて、具体的な方法を行うことができます-高い凝集性は、凝集性を測定できる単一の責任を導きます。最大の凝集クラスには、すべてのメソッドで使用されるすべてのフィールドがあります。最大の凝集クラスは、常に可能であるとは限らず、望ましいことでもありませんが、これに到達するのが最善です。このクラスの設計目標を設定すると、クラスに多くのメソッドやフィールドを含めることはできないと推測するのは非常に簡単です(せいぜい7個)。

別の方法は、OOPの純粋な基本からです-実際のオブジェクトをモデルにします。実際のオブジェクトの責任をより簡単に確認できます。ただし、実際のオブジェクトが複雑すぎる場合、複数の包含オブジェクトに分割し、それぞれに独自の責任を持たせます。

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