「平易な英語」で、なぜ必要なのか説明できますか 単一の責任の原則 ?
特に、私が「膨張」と呼んでいるものを他の場所に移動させていること。詳細については、以下を参照してください。膨満とは、私の特定のケースでは、コントローラーに複数の責任があり、それらが関数/メソッドとして現れることを意味します。私が理解している方法でSRPを適用することにより、コントローラーをいくつかのコントローラーに分割し、それぞれを1つの方法で行います。したがって、「膨張」は「メソッド数」から「ファイル数」に移動します。
上記のwikiリンクの記事ではSRPについて説明していますが、SRPを使用する「理由」を教えてくれないようです。 whyについて、それほど技術的ではない(または技術的なこともある)理由/説明/意味を教えてください。この原則が必要です。
私の現在の経験では、SRPを実装すると、コードはより小さく、より狭く整列されますが、より多くのファイルが作成されるためです。
例
内部にさまざまなアクション/メソッドを含めることができるコントローラーファイルがあります。依存関係mustある特定のアクションがすべてを必要としない場合でも、すべての可能なアクションをカバーするため依存関係の。
コントローラーを2つ以上に分割して、コントローラーごとに1つのアクションを実行できるようにします。これはSRPを満たしますが、bloats作成する必要があるファイルの数です。
例
/*
* Repository initialized with $quoteId
*/
class Repository
{
private $quoteId;
function __construct($quoteId)
{
$this->quoteId = $quoteId;
}
}
/*
* Controller initialized with $repository
*/
class Controller
{
private $repository;
function __construct($repository)
{
$this->repository = $repository;
}
function addForm()
{
//repository is initialized elsewhere with $quoteId
$this->repository->getFormDataFromQuote();
};
function viewForm()
{
$id = int_val($_GET['id']);
//does *not* use $quoteID
$this->repository->getViewDataFromId($id);
};
}
[〜#〜] srp [〜#〜]
SRPを守るために、コントローラーを2つに分割できます。1つはaddForm用、もう1つはviewForm用です。次に、リポジトリを2つに分割することもできます。コントローラの各メソッドに1つずつです。したがって、2つのファイルから始め、4つのファイルで終わります。
欠点
ここでは、SRPを「コントローラーの分解」と解釈します(ここでは、リポジトリなどのサポートファイルもあると想定しています)。したがって、上記の例では、ControllerAddForm
とControllerViewForm
があり、これらのメソッドのリポジトリを使用している場合は、RepositoryViewForm
を作成する必要があります。 RepositoryAddForm
は、SRPも満たすためです。これは、コントローラーのさまざまなアクションにさまざまなリポジトリメソッドが必要になるためです。したがって、2倍のファイル膨張が発生します。ファイルごとのメソッドの数ではなく、ファイルの数に膨張を移動したにもかかわらず、なぜSRPが推奨されるのか。
Sous Chefに車を修理させないのと同じ理由で、SRPが必要です。 彼らには異なる責任があります。
一人一人が異なる専門分野を専門としています。役立つ場合は、クラスを従業員と考えてください。それぞれに役職を与えます。これは通常、各クラスのnameです。そのクラスの「専門分野」を考え出し、その専門分野を満たすコードを記述します。
SRPは、最も誤解されているソフトウェアエンジニアリングの原則の1つです。 「責任」とは正確に定義されていないため、これを理解するのはさらに困難です。
大まかに言えば、「責任」は単一のアトミックアクションではなく、密接に関連する一連のアクションです。フォームの追加、フォームの表示、フォームの送信などはすべて「フォームXの管理」と同じ責任です。
SRPを守るために、コントローラーを2つに分割できます。1つはaddForm用、もう1つはviewForm用です。
いいえ。SRPを遵守するには、見積もりの管理と顧客の管理のために別々のコントローラーがあります。彼らは、各データ型(見積もりと顧客)の永続性を管理するモデルに委任する場合があります。
一般に、大きなコード単位を小さなコード単位にリファクタリングすることは良い考えです。コードの小さな単位が多すぎて推論できない点まで個人的には、私の「見積もりフォームの管理」コードをすべて1つのクラスにまとめることは素晴らしいアイデアだと思います。見積もり用のコントローラーコードを探す場所を正確に知っています。私はその目的のためにすべてのコードが存在することを知っていますが、顧客を管理するためのコードはありません。
また、Webベースの見積もり管理システムに適用されるSRPは、Linuxカーネルの場合とは異なります。一歩下がって、全体的なデザインを見て、コードが行っていることの自然な分割を見つけてください。 それからあなたの仲間の一人に聞いてください 。
SRPは、ドグマとして従うと(ほとんどの設計原則と同様に)危険です。私の見解は、SOLID)を尊重することですが、特にその原則を引用して誰かが光よりも熱を放出しているときは、その強いカルトに注意してください。
あなたの質問を読んだとき、私はSRPが [〜#〜] yagni [〜#〜] に反対していると思っていました。
コントローラーの例を使用すると、要件neverが変更された場合にコントローラーを別個のクラスに分離することはほとんど意味がありません。いくつかの「サメ戦車」デモ、および/または別のプロジェクトでコントローラーロジックの一部を再利用する必要は決してないでしょう。彼らはすべて多分大きいです。
Robert Martin 詳細な例を示します ボウリングプロジェクトでコードを使用。この設計により、フレームの追跡とスコアの計算という2つの役割を持つクラスGame
が作成されます。
彼の本のペアプログラミング設計実験では、開発者の1人が結局、これらの個別の責任をGame
とScorer
に別個のクラスにリファクタリングすることを提案し、SRPを動機として挙げています。 Linuxプログラマーがすべてを1つの読み取り不可能な関数で実行することを好むという皮肉なコメントが行われています...
これは、SRPのYingとYangの良い例です。ゲームとスコアリングの責任のために別々のモジュールを用意することには、2つがより独立して進化できるという利点があります。おそらく、新しいプログラマーが、スコアリングのトリッキーなバグがコード内のどこにあるかを見つけることもできます(Scorer
すべてのコードが1つのモジュールにまとめられている場合など)など。これらのクラスは、理論的には、サービスを必要とする他のアプリケーションで再利用できます( Jarts 誰か?)。
しかし、マイナス面もあります。決して発生しない変更を予測することは、努力の無駄です。ボウリングのゲームのルールにどんな変化が起こるかもしれません!?理論的にはそれらは存在します(ねえ、45からの執行命令があるかもしれませんか?)そして、もしそれらが起こった場合、別々のモジュールを持っていることは確かにそれより良いでしょう?
悲しいかな、YAGNIは、変化が現れるまで、変化にエネルギーを浪費しないでください。それは過剰設計です。
最後に、SRP(および一般に責任主導の設計)はヒューリスティックです(つまり、SRPは過去に機能したように見えますが、適用することで利益が得られるという保証はありません)。誰がそれが報われるかをあなたに知らせるのに十分な研究をしていません。設計上の問題は難しく、独断的に「原理」を使用しようとすると失望につながります。
私は Principles Wiki がこれらのさまざまな設計原則間の関係を明らかにしようとするため、本当に興味深い(不完全ではあります)とわかりました。 SRPには 懸念の分離、カーリーの法則など、多くの関連する原則 があります。それらを読むことはトレードオフを理解するのにも役立ちます。
単一責任原則(SRP)
クラスは複数の責任を持つべきではありません。ビジネスコンテキストは、クラスにおける責任の分離のレベルも促進します。
注意:
SRP分析:たとえば、クラス内の各メソッドxを見て、「Car
」と言い、「Car
はx-ingの主な責任を負っていますか?」答えが「いいえ」の場合、メソッドはそこに属していない可能性があります。 object
ではなく、action
について尋ねます。