Sandi Metz開発者ガイドライン

今年の1月、 Sandi MetzRuby Roguesポッドキャストで開発者向けのルールを紹介しました。 同じ頃、私のチームと私は新しいプロジェクトを始めました。 この記事では、これらのルールを新しいプロジェクトに適用することで得られた経験について説明します。



ルール



  1. クラスには100行を超えるコードを含めることはできません。
  2. メソッドは5行のコードより長くすることはできません。
  3. メソッドに4つを超えるパラメーターを渡すことはできません。 ハッシュ値もパラメーターと見なされます。
  4. コントローラは、1つのオブジェクトのみをインスタンス化できます。 したがって、ビューは変数の1つのインスタンスのみを認識でき、このオブジェクトにのみメッセージを送信する必要があります( @object.collaborator.value



    無効です)。





ルールを破るとき



サンディを言い換えると、「正当な理由がある場合、またはプログラミングパートナーが承認した場合にのみ、規則を破ることができます。」 プログラミングパートナーまたはコードをレビューしている人から許可を得る必要があります。



これを不変のルール番号0とします。



100個の文字列クラス



プライベートメソッドが多数あるという事実にもかかわらず、クラスを短くすることは簡単でした。 このため、クラスの非常に一般的な責任を定義し、発行するコードを理解する必要がありました。



これは仕様にも適用されます。 この制限を超えるスペックファイルが見つかった場合がありました。 彼は、私たちがあまりにも多くの機能をテストしていることを理解するのを助けてくれました。 このファイルを、機能に重点を置いたいくつかの仕様に分割することが決定されました。



100行の制限を超えた場合、git diffは必ずしも表示されないという結論に達しました。



メソッドごとに5行のコード



メソッドの5行の制限は、最も興味深いルールに従ってください。

「if」、「else」、「end」も考慮されることに同意しました。 2つのブランチを持つ 'if'ブロックでは、各ブランチは1行に収まる必要があります。



例:



 def validate_actor if actor_type == 'Group' user_must_belong_to_group elsif actor_type == 'User' user_must_be_the_same_as_actor end end
      
      





5行は、「else」と「elsif」を使用しないことを保証します。



ブランチごとに1行という制限があるため、適切に設計された名前のプライベートメソッドを使用して、目的の結果を達成する必要がありました。 プライベートメソッドは優れたドキュメントです。 非常に明確な名前が必要であるため、どのコードを強調表示する必要があるかを考えさせられました。



メソッドごとに最大4つの引数



Railsでこのルールを適用することは、特にビューでの優れたテストになりました。



'link_to'や 'form_for'などのビューヘルパーは、正しく機能するために多くのパラメーターを必要とする場合があります。 もちろん、渡される引数の数を制限する努力をしましたが、より良い方法が見つからない場合はルール0に戻ってそれらを残すことがありました。



コントローラー内の最大1つのオブジェクトのインスタンス



新しいプロジェクトに着手する前に、このルールは私たちを最も驚かせました。 多くの場合、ページごとに複数のタイプのオブジェクトが必要でした。 たとえば、ホームページでは、アクティビティフィードと通知カウンターが必要でした。



この問題は、Facadeデザインパターンを使用して解決しました。 そして、それはこのように見えました:



app / facades / dashboard.rb:



 class Dashboard def initialize(user) @user = user end def new_status @new_status ||= Status.new end def statuses Status.for(user) end def notifications @notifications ||= user.notifications end private attr_reader :user end
      
      





app / controllers / dashboards_controller.rb:



 class DashboardsController < ApplicationController before_filter :authorize def show @dashboard = Dashboard.new(current_user) end end
      
      





app / views / dashboards / show.html.erb:



 <%= render 'profile' %> <%= render 'groups', groups: @dashboard.group %> <%= render 'statuses/form', status: @dashboard.new_status %> <%= render 'statuses', statuses: @dashboard.statuses %>
      
      





'Dashboard'クラスは、相互作用するユーザーオブジェクトを配置するための共通のインターフェイスを提供し、そのオブジェクトをプレゼンテーションテンプレートに既に渡します。



コントローラーで変数をメモしても、この制限に影響しないことに同意しました。 そして、テンプレートで使用することを意図しているという事実を反映するために、未使用の変数に下線の形でプレフィックスを追加することに同意しました。



 def calculate @_result_of_expensive_calculation ||= SuperCalculator.get_started(thing) end
      
      





前例のない成功!



私たちは最近、実験が成功したことを認識し、研究メーリングリストに掲載し、これらのルールをベストプラクティスガイドに含めました。



All Articles