Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

一般的なRubyonRailsの問題とポイント

RubyonRailsのパターンとアンチパターンシリーズの最後の部分へようこそ。これらすべてのトピックを書き、調査することは、かなりの乗り物でした。このブログ投稿では、RubyonRailsアプリケーションを構築して出荷するときに遭遇した最も一般的な問題について説明します。

ここで説明するアイデアは、コード内のほぼすべての場所に当てはまります。したがって、これらは、Model-View-Controllerパターンに関連するものではなく、一般的なアイデアと見なしてください。 Rails MVCに関連するパターンとアンチパターンに興味がある場合は、モデル、ビュー、およびコントローラーのブログ投稿を確認できます。

それでは、一般的な問題とポイントに飛び込みましょう。

セルフィッシュオブジェクトとデメテルの法則

デメテルの法則は、人々のグループがデメテルプロジェクトに取り組んだときにその名前が付けられたヒューリスティックです。オブジェクトは、一度に1つのメソッドを呼び出し、複数のメソッド呼び出しを連鎖させない限り、問題はありません。これが実際に意味することは次のとおりです。

# Bad
song.label.address
 
# Good
song.label_address

さて、song オブジェクトはアドレスがどこから来たのかを知る必要がなくなりました—アドレスはlabelの責任です 物体。 1つのメソッド呼び出しのみをチェーンし、オブジェクトを「利己的」にして、完全な情報を直接共有するのではなく、ヘルパーメソッドを介して共有することをお勧めします。

幸い、Railsでは、ヘルパーメソッド自体を作成する必要はありません。delegateを使用できます。 ヘルパー:

def Label < ApplicationModel
  belongs_to :song
 
  delegate :address, to: :song
end

先に進んで、デリゲートがデリゲートのドキュメントで受け入れるオプションを試してみることができます。しかし、アイデアと実行は非常に単純です。デメテルの法則を適用することにより、構造的な結合を減らすことができます。強力なdelegateと一緒に 、より少ない行で、優れたオプションが含まれています。

デメテルの法則に非常によく似たもう1つのアイデアは、単一責任の原則(または略してSRP)です。モジュール、クラス、または関数がシステムの単一の部分を担当する必要があることを示しています。または、別の方法で提示:

同じ理由で変化するものを集めてください。さまざまな理由で変化するものを分離します。

多くの場合、人々はSRPについて異なる理解を持っている可能性がありますが、アイデアは、ビルディングブロックに単一の責任を負わせることです。 Railsアプリが拡張するにつれてSRPを達成するのは難しいかもしれませんが、リファクタリングするときは注意してください。

機能を追加してLOCを増やすと、多くの場合、迅速な解決策を求められることがわかりました。それでは、クイックフィックスを入手してみましょう。

I Know a Guy(Ruby Gemが必要ですか?)

Railsが話題になった当時、オープンソースコラボレーションがブームになり、新しいRuby gemが隅々に出現しました(最近のすべての新しいJavaScriptライブラリのように、規模ははるかに小さいです)。

👆モジュール数からの情報。

とにかく、一般的なアプローチは、問題を解決するための既存の宝石を見つけることでした。

それは何も悪いことではありませんが、宝石をインストールする前に、少しアドバイスを共有したいと思います。

まず、次の質問を自問してください。

  • 宝石の機能のどの部分を使用しますか?
  • 「よりシンプル」またはより最新の同様の宝石はありますか?
  • 必要な機能を簡単かつ自信を持って実装できますか?

一連のgem機能全体を使用する予定がない場合は、実装を行う価値があるかどうかを評価します。または、gemの実装が複雑すぎて、もっと簡単に実行できると思われる場合は、カスタムソリューションを選択してください。

私が考えるもう1つの要素は、gemのリポジトリがどれほどアクティブであるかです。アクティブなメンテナはいますか?最後にリリースが行われたのはいつですか?

また、gemの依存関係にも注意する必要があります。依存関係の特定のバージョンにロックされたくないので、常にGemfile.specを確認してください。 ファイル。 gemバージョンを指定するRubyGemsの方法を参照してください。

宝石のトピックに取り組んでいる間、私が遭遇した関連するアイデアがあります。それは、Rails / Rubyの世界に適用される「ここで発明されていない」(またはNIH)現象です。次のセクションでそれが何であるかを見てみましょう。

ここでは発明されていません(結局、そのRuby Gemが必要なのかもしれません)

私のキャリアの中でいくつかの出来事で、私は人々(私を含む)が「ここで発明されていない」症候群に陥るのを経験する機会がありました。考え方は「車輪の再発明」に似ています。チームや組織は、制御できないライブラリ(gem)を信頼しない場合があります。信頼の欠如は、彼らがすでにそこにある宝石を再発明するきっかけになるかもしれません。

時々、NIHを体験することは良いことかもしれません。社内ソリューションを作成することは、特に他のソリューションよりも改善する場合に役立ちます。ソリューションをオープンソース化することにした場合、それはさらに良くなる可能性があります(Ruby on RailsまたはReactを見てください)。しかし、それのために車輪の再発明をしたいのなら、それをしないでください。ホイール自体はすでにかなり素晴らしいです。

このトピックは非常に注意が必要です。このような状況に陥った場合は、次の質問を自問してください。

  • 既存のソリューションよりも優れたソリューションを作成できると確信していますか?
  • 既存のオープンソースソリューションが必要なものと異なる場合、オープンソースに貢献して改善することはできますか?
  • さらに、私たちはオープンソースソリューションのメンテナーになり、多くの開発者の生活を改善できるでしょうか?

しかし、場合によっては、自分のやり方でライブラリを自分で作成する必要があります。おそらくあなたの組織はオープンソースライブラリのライセンスを好まないので、あなたはあなた自身のものを構築することを余儀なくされています。しかし、あなたが何をするにしても、車輪の再発明は避けたほうがいいと思います。

ライフガードオンデューティー(過剰救助の例外)

人々は当初の目的よりも多くの例外を救う傾向があります。

このトピックは、前のトピックよりもコードに少し関連しています。一部の人にとっては常識かもしれませんが、コードに時々見られます。例:

begin
  song.upload_lyrics
rescue
  puts 'Lyrics upload failed'
end

救済したい例外を指定しない場合、計画していなかったいくつかの例外をキャッチします。

この場合、問題はsongである可能性があります オブジェクトはnilです 。その例外がエラートラッカーに報告されると、アップロードプロセスで何かがおかしいと思うかもしれませんが、実際には、まったく異なる何かが発生している可能性があります。

したがって、安全のために、例外をレスキューするときは、発生する可能性のあるすべての例外のリストを取得するようにしてください。何らかの理由ですべての例外を取得できない場合は、過剰に救助するよりも過少に救助する方が適切です。知っている例外を救出し、後の段階で他の例外を処理します。

質問が多すぎます(SQLクエリが多すぎます)

このセクションでは、別のWeb開発であるリレーションデータベースの問題について説明します。

1回のリクエストでSQLクエリが多すぎるWebサーバーを爆撃します。その問題はどのように発生しますか? 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

このコードは、1つのSQLクエリをトリガーして10曲を取得します。その後、1つの追加のSQLクエリが実行され、各曲のアーティストが取得されます。これは合計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の後 、表示する曲の数に関係なく、SQLクエリは2つしか取得できません。なんてきれいだ。

あまりにも多くのSQLクエリを診断できる1つの方法は、開発中です。同じテーブルからデータをフェッチしている同様のSQLクエリのグループを見ると、何か怪しいことが起こっています。そのため、開発環境でSQLログをオンにすることを強くお勧めします。また、Railsは、コード内のどこからクエリが呼び出されたかを示す詳細なクエリログをサポートしています。

ログを確認することが目的ではない場合、またはもっと深刻なことをしたい場合は、AppSignalのパフォーマンス測定とN+1クエリ検出を試してください。そこで、問題がN+1クエリに起因するかどうかの優れた指標が得られます。以下は次のとおりです。

まとめ

このブログ投稿シリーズをお読みいただきありがとうございます。一般的な問題に関するこの最後のブログ投稿の前に、Railsでのパターンとアンチパターンの紹介から、Rails MVCパターン内にあるものの調査まで、この興味深い乗り物に参加していただき、ありがとうございます。

あなたがたくさんのことを学んだか、少なくともあなたがすでに知っていることを修正して確立したことを願っています。すべてを暗記することを強調しないでください。どこかで問題が発生した場合は、いつでもシリーズを参照できます。

この世界(特にソフトウェアエンジニアリング)は理想的ではないため、パターンとアンチパターンの両方に確実に遭遇します。心配する必要はありません。

パターンとアンチパターンをマスターすると、優れたソフトウェアエンジニアになります。しかし、完璧な解決策はないため、これらのパターンや型をいつ壊すかを知ることで、さらに良い結果が得られます。

参加して読んでくれてありがとう。次はまた会いましょう—そして乾杯!

P.S。 Ruby Magicの投稿をマスコミから離れたらすぐに読みたい場合は、Ruby Magicニュースレターを購読して、投稿を1つも見逃さないでください。


  1. 一般的なスキャナーの問題、トラブルシューティングのヒントと解決策

    時間の前にプロジェクトを完了することほど悪いことはありませんが、「スキャンまたは印刷が遅い」問題のためにプロジェクトを遅れて提出します。同様に、スキャナーに関する他の問題は、ユーザーにフラストレーションを引き起こす可能性があります。今日のコラムでは、いくつかの主要なスキャナーハードウェアの問題に焦点を当てました。 トラブルシューティングの方法と解決策とともに。 スキャナーの問題、トラブルシューティング、解決策 機器の品質は非常に重要であり、場合によっては、新品の傷のないプラスチック製のキャリアでさえ、スキャンの品質を低下させる可能性があります。常に稼働していることを確認する方法は次のと

  2. Ruby on Railsとは何ですか?なぜそれが役立つのですか?

    Ruby on Rails(RoRの場合もある)は、最も人気のあるオープンソースのWebアプリケーションフレームワークです。 Rubyプログラミング言語で構築されています。 Railsを使用すると、単純なものから複雑なものまで、アプリケーションの構築に役立ちます。Railsで実行できることには制限がありません。 フレームワークとは何ですか? フレームワークは、ソフトウェアを作成するときに使用する特定の構造を提供するコード、ツール、およびユーティリティのコレクションです。 この構造により、コードがより整理されます。 正しく使うことを学ぶと、作業が簡単になります。 レールは正確に何を