綺麗な設計を身に付けるためのSandi Metzルール
Webアプリやモバイルアプリの受託開発やコンサルティングを行うthoughtbot社のブログにて、Sandi MetzルールというRubyプログラマ向けのルールが紹介されていました。
このルールは、プログラマーでありPractical Object-Oriented Design in Rubyという書籍も執筆しているSandi MetzさんがRuby Roguesポッドキャストに出演した際に紹介していたものです。
そのルールは以下の通りです。
- クラス内のコードが100行を超えてはならない
- メソッド内のコードが5行を超えてはならない
- 4つより多い引数をメソッドに渡すようにしてはならない(ハッシュによるオプションもパラメーターとみなす)
- コントローラーではただ1つのオブジェクトだけをインスタンス変数化できる
- ビューは1つのインスタンス変数を参照し、そのオブジェクトに対するメッセージ送信のみを行うことができる(
@object.collaborator.value
は許可されない)
- ビューは1つのインスタンス変数を参照し、そのオブジェクトに対するメッセージ送信のみを行うことができる(
項目は少ないですが、方向性としてはThoughtworksアンソロジーという書籍で紹介されていた「オブジェクト指向エクササイズ」に通じるものがあります(あちらはJavaが主な対象でした)。
4つのルールとは別に、このルールを破ってもよい場合として、
- 適切な理由があると考えられる場合
- ペアプログラミングのパートナーやコードレビュアーが許可した場合
がルール0として挙げられています。
thoughtbotでは実際のプロジェクトにこのルールを適用してみたそうで、以下のような知見が得られたようです。
- ルール1 クラス内のコードが100行を超えてはならない
- Single Responsibility Principle(単一責任の原則)を徹底するようになる
- テストも100行以内に収めることを心がけたことで、1つのファイルで多くの機能をテストしすぎていたものを、よりフォーカスの定まった個別のテストに分割できた
- ルール2 メソッド内のコードが5行を超えてはならない
- メソッドを5行に収めるために、
「if〜else〜elsif〜end」のようにelseとelsifを合わせて使うことを避けるようになった(コメントで誤訳のご指摘をいただきましたので修正します。原文の意図は、if〜else〜endやif〜elsif〜endは使うけども、それらの組み合わせは5行を超えてしまうので使わない、ということのようです)else
やelsif
- 条件分岐で1行を使うのではなく、適切な名前のついたプライベートメソッドを作ってそれを呼ぶようになった
- コード片をプライベートメソッドとして抽出することで、命名が行われ、説明としても役立つようになった
- メソッドを5行に収めるために、
- ルール3 4つより多い引数をメソッドに渡すようにしてはならない(ハッシュによるオプションもパラメーターとみなす)
- Railsのビューヘルパーメソッドはとても多くの引数を要求するため、よい解決法が見つからない場合は、ルール0に立ち返り引数をそのままとした
ルール4については、実際のコードを例に詳しく説明がされています。
ルール4を適用すると、1つのコントローラーが1つのオブジェクトだけをビューに引き渡すように設計することになりますが、実際のプロジェクトでは必ずしも1つのコントローラーが1つのものを表示するとは限りません。
例えば、「トップページにアクティビティフィードと通知の数を表示する」といったようなケースも頻繁にありえます。thoughtbotではこのようなケースにFacadeパターンを適用し、アクティビティフィードと通知の数を内包したダッシュボードクラスを定義することで、コントローラーとビュー間のやり取りを単純化させることにしたようです。
詳細は、実際のコード例を見れば一目瞭然だと思いますので、ぜひ元のブログ記事も参照してみてください。
有益な記事をご紹介いただきありがとうございます。
僭越ながらひとつ気になったので指摘させてください。
原文> Five lines ensured that we never use else with elsif.
なので、「elseやelsifを使うのを避ける」のではなく、「elsifは使わない」ですね。
(if…else…endでちょうど5行に収まるというニュアンスなのだと思います。)
iTakeshi
2013/05/20 at 22:48
ご指摘どうもありがとうございます。
確かに、おっしゃるとおりの意味合いが正しかったようですので本文を修正いたしました。
junya
2013/05/21 at 00:28
elsifも使わないわけではなくて、if ~ elsif ~ else ~ endまでいくと7行で5行に収まらないので、elseをelsifと一緒に使わなくなったということですね。elsif1回で5行の例は出ています。
TN
2013/05/21 at 09:21
TNさん、ご指摘ありがとうございます。
その通りですね。if〜elseと、if〜elsifのいずれかのみのパターンは許容される、というように本文を修正しておきました。
junya
2013/05/21 at 11:06
アドバンストコミュニケーションテクノロジー's Blog でリブログ& コメント:
キツイ感じがするが、心がけてみよう。
act2012bl
2013/05/20 at 23:59
[…] 綺麗な設計を身に付けるためのSandi Metzルール | A-Listers […]
2013年Rubyの話題を一挙に振り返るまとめ | Engine Yard Blog JP
2013/12/29 at 15:38