Ruby on Railsの問題と取材

10596 ワード

私の最後の部分へようこそRuby on Rails Patterns and Anti-Patterns series . それはかなりのライドライティングとこれらのトピックのすべてを研究している.このブログ記事では、長年にわたってRuby on Railsアプリケーションを構築し、出荷する際に遭遇した最も一般的な問題について説明します.
私がここで行く考えは、コードのほとんどどこにでも適用されます.したがって、一般的なアイデアとして考えてください.モデルビューのコントローラパターンに関連するものではありません.あなたがRails MVCに関連したパターンと反パターンに興味があるならば、あなたはModel , View , and Controller ブログ柱.
それで、一般的な問題と離陸に飛び込みましょう.

利己的対象とデメテルの法則


The Law of Demeter グループの人々がDemeterプロジェクトで働いたとき、その名前を得たヒューリスティックです.アイデアは、彼らは一度に1つのメソッドを呼び出して、チェーンの複数のメソッド呼び出しをしない限り、あなたのオブジェクトは素晴らしいです.これが実際には以下のようになります.
# Bad
song.label.address

# Good
song.label_address
だから、今song オブジェクトはもはやアドレスがどこから来るかを知る必要はありませんlabel オブジェクト.あなたは、1つのメソッド呼び出しだけでチェーンに奨励されて、あなたが彼らの完全な情報を直接共有するのではなく、ヘルパーメソッドを通して、あなたのオブジェクトを「利己的」にします.
幸いにも、Railsでは、ヘルパーメソッドを書く必要はありませんdelegate ヘルパー
def Song < ApplicationModel
  belongs_to :label

  delegate :address, to: :label
end
あなたは、先に行くことができます、そして、デリゲートが受け入れるオプションで遊んでくださいdelegete's docs . しかし、アイデアと実行はかなり簡単です.DEMETERの法則を適用することにより、構造結合を減らす.力強くdelegate , あなたは、より少ない線で、そして、大きなオプションでそれをします.
Demeterの法則に非常に類似しているもう一つの考えはSingle-responsibility Principle (あるいは短い場合のsrp ).これは、モジュール、クラス、または関数は、システムの単一の部分の責任を負う必要があります.または別の方法で示します.

Gather together the things that change for the same reasons. Separate those things that change for different reasons.


人々はしばしばSRPの異なる理解を持つことができます、しかし、考えはあなたのビルディング・ブロックを一つのものに対して責任をおいておくことです.それはあなたのRailsアプリが展開するようにSRPを達成するために挑戦するかもしれませんが、リファクタリング時にそれを意識してください.
機能を追加して、LOCを増やすとき、私は人々がしばしば速い解決のために手を伸ばすとわかりました.それで、速いフィックスをつかんでください.

私は男を知っています。


Railsがホットな話題であった時代には、オープンソースのコラボレーションでブームが起こりました.新しいRubyの宝石が隅々まで飛び交うようになっていました.

👆 インフォメーションModule Counts .
とにかく、一般的なアプローチは、あなたの問題を解決するために既存の宝石を見つけることでした.
何も間違っていませんが、宝石をインストールすることを決定する前にいくつかのビットのアドバイスを共有したいと思います.
まず、これらの質問を自分に問い合わせる
  • 宝石の機能のどの部分を使用するつもりですか?
  • そこには、より単純であるか、より最新のものである同様の宝石がありますか?
  • あなたは簡単に自信を持って必要な機能を実装できますか?
  • GEM機能の全配列を使用しない場合、実装を行う価値があるかどうかを評価します.または、宝石の実装が複雑すぎる場合は、より簡単に行うことができます信じて、カスタムソリューションを選ぶ.
    私が考えるもう一つの要因は、宝石の貯蔵所がどれくらい活発であるかについてです-活発な管理者がいますか?ときにリリースが起こった最後の時間だった?
    また、宝石の依存関係を気にする必要があります.依存性の特定のバージョンにロックされたくないので、常にチェックしてくださいGemfile.spec ファイル.相談するRubyGems way of specifying gem versions .
    私たちがGemsの話題についている間、私が遭遇したという関連した考えがあります.次のセクションでそれが何であるかについて見ましょう.

    ここでは発明されていない(結局はルビー宝石が必要なのか?)


    私のキャリアの2、3の出来事の中で、私は「発明されていない」症候群のために人々(私を含めて)を経験する機会がありました.アイデアは'ホイールを再発明'に似ています.時々、チームと組織は、彼らがコントロールすることができないライブラリ(Gems)を信頼しません.信頼の欠如は、彼らがすでにそこにある宝石を再発明するための引き金であるかもしれません.
    時々、nihを経験することは、良いことでありえます.特にあなたがそこの他の解決の上でそれを改善するならば、社内解決をすることはすばらしいことがありえます.あなたが解決策をオープンソースに決めるならば、それはよりよくありえます.しかし、あなたがそれのために車輪を再発明したいならば、それをしないでください.車輪自体はすでにかなり大きいです.
    このトピックは非常にトリッキーです、そして、あなたがそのような状況に巻き込まれるならば、あなた自身にこれらの質問をしてください:
  • 我々は既存のものより良い解決策を作ることができると確信していますか?
  • 既存のオープンソースソリューションが我々が必要とするものと異なるならば、我々はオープンソース貢献をして、それを改善することができますか?
  • さらに、我々はオープンソースソリューションの管理者になることができ、おそらく多くの開発者の生活を向上させることができますか?
  • しかし、時には、あなた自身の方法を移動し、ライブラリを自分で作成する必要があります.たぶん、あなたの組織はオープンソースライブラリをライセンスするのを好みません.しかし、あなたが何をしても、私は車輪を再発明するのを避けます.

    救命の救命士


    人々は、彼らが本来目指したより多くの例外を救出する傾向があります.
    このトピックは以前のコードよりも関連するコードです.それはいくつかの常識かもしれないが、それは時々のコードで見ることができます.例えば、
    begin
      song.upload_lyrics
    rescue
      puts 'Lyrics upload failed'
    end
    
    我々が我々が救いたい例外を指定しないならば、我々は我々が計画しなかった若干の例外を捕えます.
    この場合、問題はsong オブジェクトnil . その例外がエラートラッカーに報告されるとき、あなたはアップロードプロセスで何かが離れていると思うかもしれません.
    それで、安全であるために、例外を救出するとき、起こるかもしれないすべての例外のリストを得てください.何らかの理由ですべての例外を得ることができない場合、それは救助以上に救助の下に良いです.あなたが知っていて、後段で他を扱う例外を救ってください.

    あなたはあまりにも多くの


    このセクションでは、我々は別のWeb開発、関係データベースの問題を通過するつもりです.
    あなたは、1つの要求であまりに多くのSQL質問でウェブサーバを爆撃します.その問題はどうなっているのか.さて、1つのリクエストで複数のテーブルから複数のレコードを取得しようとすると起こります.しかし、最もしばしば起こることは悪名高いN + 1質問問題です.
    次のモデルを想像してください
    class Song < ApplicationRecord
      belongs_to :artist
    end
    
    class Artist < ApplicationRecord
      has_many :songs
    end
    
    私たちがジャンルと彼らのアーティストで歌のカップルを示すことを望むならば:
    songs = Song.where(genre: genre).limit(10)
    
    songs.each do |song|
      puts "#{song.title} by #{song.artist.name}"
    end
    
    コードのこの部分は、10曲を得るために1つのSQL質問を引き起こすでしょう.その後、1つの余分なSQLクエリは、各曲のアーティストを取得するために実行されます.それは11(11)クエリ合計です.
    我々がより多くの歌をロードするならば、シナリオを想像してください.
    あるいは、使用includes Railsから:
    songs = Song.includes(:artists).where(genre: genre).limit(10)
    
    songs.each do |song|
      puts "#{song.title} by #{song.artist.name}"
    end
    
    アフターincludes , どのように多くの曲を表示するに関係なく、我々は現在2つのSQLクエリを取得するだけです.どのようにきちんと.
    あまりにも多くのSQLクエリを診断する方法の一つは、開発中です.同様のSQLクエリのグループが同じテーブルからデータを取得するのを見るならば、何かFishyがそこにあります.だから、開発環境のSQLログを有効にすることを強く勧めます.また、柵支持verbose query logs クエリーがコード内から呼び出される場所を示します.
    ログを見ている場合はあなたのものではない、または何かもっと深刻な、試してみてくださいAppSignal's performance measuring and N+1 query detection . そこで、あなたの問題がN + 1質問から来るかどうかの優れた指標を得ます.以下のようになります.

    総括する


    このブログのポストシリーズを読んでくれてありがとう.私はあなたがこの面白い乗り物のために私に加わったことをうれしく思います、そこで、我々は一般的な問題に関してこの最終的なブログポストの前にRails MVCパターンの中にあるものを調査するためにRailsのパターンと反パターンを導入することから行きました.
    私はあなたがたくさん学んだ、または少なくとも改訂し、あなたが既に知っているものを確立願っています.それのすべてを暗記することについて強調しないでください.任意の領域でトラブルを抱えている場合は、常にシリーズに相談することができます.
    この世界(そして、特にソフトウェア工学)が理想的でないので、あなたは確かにパターンと反パターンの両方に遭遇します.それはあなたのいずれかを心配する必要はありません.
    マスタリングパターンとアンチパターンは、偉大なソフトウェアエンジニアになります.しかし、何がより良いものが完璧な解決策がないので、これらのパターンと金型を破るときに知っている.
    参加と読書のおかげで再び.次のいずれかでお会いしましょう-と歓声!
    P . S .あなたが彼らがプレスから降りるとすぐに、ルビー魔法のポストを読みたいならば.subscribe to our Ruby Magic newsletter and never miss a single post !
    Nikola JavaScriptとRubyで実用的なアドバイスと適用可能な知識を共有することによって、開発者は彼らの生産性を向上させます.