あなたのウェブサイトは前進していて、あなたは急速に成長しています。 Ruby / Railsは最良のプログラミングオプションです。あなたのチームはより大きく、あなたはすでに「ファットモデル、シンドライバー」という概念を残しています( ファットモデル、スキニーコントローラー )Railsアプリケーションのデザインスタイルとして。ただし、それでもRailsの使用をやめたくはありません。
問題ない。今日は、OOPのベストプラクティスを使用して、コードをよりクリーンで、より分離され、分離する方法について説明します。
まず、アプリケーションがリファクタリングに適しているかどうかを判断する方法を見てみましょう。
これは、コードのリファクタリングが必要かどうかを判断するために私が通常自分自身に尋ねるメトリックと質問のリストです。
次のようなものを使用して、Rubyソースコードの行数を確認してください。
find app -iname '*.rb' -type f -exec cat {} ;| wc -l
このコマンドは、/ appフォルダー内の拡張子が.rbのすべてのファイル(rubyファイル)を検索し、行数を出力します。コメント行はこの合計に含まれるため、この数値は推定値にすぎないことに注意してください。
もう1つのより正確で有益なオプションは、タスクを使用することです レーキ stats
Railsは、コード行、クラス数、メソッド数、メソッドとクラスの比率、およびメソッドごとのコード行の比率の簡単な要約を公開します。
*bundle exec rake stats* +----------------------+-------+-----+-------+---------+-----+-------+ | Nombre | Líneas | LOC | Clase | Método | M/C | LOC/M | +----------------------+-------+-----+-------+---------+-----+-------+ | Controladores | 195 | 153 | 6 | 18 | 3 | 6 | | Helpers | 14 | 13 | 0 | 2 | 0 | 4 | | Modelos | 120 | 84 | 5 | 12 | 2 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 45 | 12 | 0 | 3 | 0 | 2 | | Bibliotecas | 0 | 0 | 0 | 0 | 0 | 0 | | Controlador specs | 106 | 75 | 0 | 0 | 0 | 0 | | Helper specs | 15 | 4 | 0 | 0 | 0 | 0 | | Modelo specs | 238 | 182 | 0 | 0 | 0 | 0 | | Petición specs | 699 | 489 | 0 | 14 | 0 | 32 | | Routing specs | 35 | 26 | 0 | 0 | 0 | 0 | | Vista specs | 5 | 4 | 0 | 0 | 0 | 0 | +----------------------+-------+-----+-------+---------+-----+-------+ | Total | 1472 |1042 | 11 | 49 | 4 | 19 | +----------------------+-------+-----+-------+---------+-----+-------+ Código LOC: 262 Prueba LOC: 780 Ratio Código a Prueba: 1:3.0
実際の例から始めましょう。
ジョギングする人々の天気を追跡するアプリケーションを作成するとします。メインページで、ユーザーは入力された時間を見ることができます。
各時間エントリには、日付、距離、期間、および追加の関連ステータス情報(天気、地形タイプなど)、および必要に応じて計算できる平均速度があります。
週あたりの平均速度と距離を示すレポートが必要です。入口の平均速度が合計の平均速度よりも速い場合は、SMSでユーザーに通知します(この例では、 Nexmo RESTful API SMSを送信します)。
メインページでは、次のようなエントリを作成するために、ジョギングしている距離、日付、時刻を選択できます。
estadísticas
ページもあります。これは基本的に週ごとのレポートで、1週間あたりの平均速度と距離が含まれています。
aplicación
のディレクトリ構造これに似ています:
⇒ tree . ├── assets │ └── ... ├── controllers │ ├── application_controller.rb │ ├── entries_controller.rb │ └── statistics_controller.rb ├── helpers │ ├── application_helper.rb │ ├── entries_helper.rb │ └── statistics_helper.rb ├── mailers ├── models │ ├── entry.rb │ └── user.rb └── views ├── devise │ └── ... ├── entries │ ├── _entry.html.erb │ ├── _form.html.erb │ └── index.html.erb ├── layouts │ └── application.html.erb └── statistics └── index.html.erb
モデルについては説明しませんUsuario
それは異常なことではないので、私たちはそれを使っているので モットー 認証を実装します。
Entrada
モデルに関しては、アプリケーションのビジネスロジックが含まれています。
それぞれEntrada
Usuario
に属します。
入力ごとに次の属性の存在を検証しますdistancia
、períodode_tiempo
、fecha_hora
およびestatus
。
エントリを作成するたびに、ユーザーの平均速度をシステム内のすべてのユーザーの平均と比較し、SMSを介してユーザーに通知します。 Nexmo (外部ライブラリを使用する場合を示したかったのですが、Nexmoライブラリの使用方法については説明しません)。
Entrada
に注意してくださいモデルには、ビジネスロジックだけではありません。また、いくつかの検証と呼び出しも処理します。
entries_controller.rb
株式を持っています クルーエル メイン(更新なしですが)。 EntriesController#index
現在のユーザーのエントリを取得し、作成日でレコードを並べ替えます。EntriesController#create
新しいエントリを作成します。 EntriesController#destroy
の明白なまたは責任について議論する必要はありません。 :
ながらstatistics_controller.rb
週次レポートの計算を担当しますStatisticsController#index
ログインしたユーザーのエントリを取得し、#group_by
を使用して週ごとにグループ化します。クラスにあります 列挙可能 Railsで。次に、いくつかのプライベートメソッドを使用して結果を装飾してみてください。
ソースコードは自明であるため、ここではビューについてあまり説明しません。
以下は、ログインしたユーザー(index.html.erb
)のエントリを一覧表示するビューです。これは、入力ハンドラーでインデックスアクション(メソッド)の結果を表示するために使用されるパターンです。
render @entries
を使用していることに注意してくださいパーシャル、共有コードをパーシャルパターンにする_entry.html.erb
コードを保持できるように ドライ と再利用可能:
同じことが_forma
にも当てはまります。部分的。 (新規および編集された)アクションで同じコードを使用する代わりに、再利用可能な部分フォームを作成します。
週報ページの見方についてstatistics/index.html.erb
いくつかの統計を示し、いくつかのエントリをグループ化することにより、ユーザーの毎週のアクティビティについてレポートします。
そして最後に、 ヘルパー 入力の場合、entries_helper.rb
、2つ含まれます ヘルパー readable_time_period
およびreadable_speed
これにより、属性が読みやすくなります。
これまでのところ、それほど複雑なことはありません。
あなたのほとんどは、これをリファクタリングすることは原則に反していると主張することができます 接吻 そしてそれはシステムをより複雑にするでしょう。
では、このアプリは本当にリファクタリングする必要がありますか?
絶対に 番号 、ただし、サンプル目的でのみ検討します。
結局のところ、次のセクションと、アプリケーションがリファクタリングを必要としていることを示す特性を見ると、この例のアプリケーションはリファクタリングの有効な候補ではないことが明らかになります。
構造パターンを説明することから始めましょう MVC Railsで。
それは通常、https://www.toptal.com/jogging/show/1
のようなリクエストを行うことによって検索エンジンから始まります。
Webサーバーは要求を受信し、rutas
を使用します。何を定義するかcontrolador
使用する。
個人財務勘定科目表
コントローラーは、ユーザーリクエスト、データ配信、Cookie、セッションなどを分析してから、modelo
を尋ねます。データを取得します。
modelos
これらは、データベースと通信し、データを保存および検証し、ビジネスロジックを実行し、手間のかかる作業を行うRubyクラスです。ビューは、ユーザーが見ることができるものです:HTML、CSS、XML、Javascript、JSON。
Railsライフサイクルリクエストのシーケンスを表示したい場合は、次のようになります。
私が達成したいのは、POROを使用して抽象化を追加し、create/update
アクションのパターンを次のようなものにすることです。
そして、アクションについてはこれに似たものlist/show
:
POROの抽象化を追加することで、責任間の完全な分離を保証します 鎌 、Railsが完全には習得していないもの。
新しいデザインを実現するために、以下のガイドラインを使用しますが、これらは手紙に従わなければならない規則ではないことに注意してください。それらは、リファクタリングを容易にする柔軟なガイドラインと考えてください。
ActiveRecordモデルには、関連付けと定数を含めることができますが、それ以外は含めることができません。 つまり、呼び出し(サービスオブジェクトを使用してそこに呼び出しを追加する)と検証(使用する)はありません。 フォームオブジェクト モデルの名前と検証を含めるため)。
コントローラを薄層として保持し、常にサービスオブジェクトを呼び出します。 ロジックを含めるためにサービスオブジェクトを呼び出し続けたいのに、なぜコントローラーを使用するのか疑問に思う人もいるかもしれません。さて、コントローラーは持っているのに良い場所です ルーティング HTTP、パラメーター解析、認証、コンテンツネゴシエーション、正しいサービスまたはエディターオブジェクトの呼び出し、例外のキャッチ、応答のフォーマット、および正しいHTTPコードステータスの返送。
クエリ オブジェクトで作成する必要があります クエリ 。 オブジェクトメソッド クエリ オブジェクトを返す必要があります。 ハッシュ または アレイ 、ただしActiveRecordアソシエーションではありません。
使用を避ける ヘルパー 、デコレータをより適切に使用します。 どうして?の一般的な問題 ヘルパー Railsでは、それらを非の束に変えることができるということです OO 、スペース名を共有し、互いにオーバーラップします。しかし、それははるかに悪いことです、あなたがポリモーフィズムを使用できないという事実は ヘルパー Rails-コンテキストやタイプごとに異なる実装を提供し、ヘルパーをバイパスまたはサブ分類します。種類は ヘルパー Railsでは、特定のユースケースではなく、一般的にユーティリティメソッドに使用する必要があります。プレゼンテーションロジックのモデル属性をフォーマットする方法。それらを軽く、簡単にフォローできるようにしてください。デコレータ/デリゲートの方が優れています。**なぜですか?結局のところ、心配はRailsの一部のようであり、乾燥する可能性があります( 乾かす )複数のモデル間で共有される場合のコード。ただし、より大きな問題は、懸念がモデルオブジェクトをよりまとまりのあるものにしないことです。コードだけがより適切に編成されています。つまり、モデルAPIに実際の変更はありません。
抽出してみてください 貴重なアイテム モデルの コードをよりクリーンに保ち、関連する属性をグループ化します。
始める前に、何か他のことについて話し合いたいと思います。リファクタリングが始まると、通常、次のように疑問に思うことになります。 「それは良いリファクタリングですか?」
責任をより分離または分離しているように感じる場合(コードと新しいファイルを追加することを意味する場合でも)、これは良いことです。結局のところ、アプリケーションを切り離すことは非常に良い習慣であり、適切な単体テストを簡単に行うことができます。
ロジックをコントローラーからモデルに移動するなどのことについては説明しません。これは、Rails(通常はSkinnyコントローラーとFATモデル)を快適に使用できることを前提としているためです。
この記事を簡潔にするために、テストの方法については説明しませんが、これはテストすべきではないという意味ではありません。
それどころか、あなたはすべきです 常にテストから始める 先に進む前に、物事が順調に進んでいることを確認します。これは何かです 必須、 特にリファクタリングを行う場合。
Windowsに最適なコマンドライン
その後、変更を実装し、テストがコードの関連部分を通過することを確認できます。
まず、価値のあるオブジェクトは何ですか?
マーティンファウラー 説明:
値オブジェクトは、お金や日付範囲オブジェクトなどの小さなオブジェクトです。それらの重要な機能は、参照セマンティクスではなく、値セマンティクスに従うことです。
概念がそれ自体の抽象化に値し、その平等が価値観ではなくアイデンティティに基づいている状況に陥ることがあります。この例としては、Rubyの日付、URI、パス名などがあります。貴重なオブジェクト(またはドメインモデル)の抽出は非常に便利です。
なぜわざわざ?
値オブジェクトの大きな利点の1つは、コードの表現力を高めるのに役立つことです。コードはより明確になる傾向がありますが、少なくとも、適切な命名規則がある場合はそうなる可能性があります。値オブジェクトは抽象化されているため、コードがより明確になり、エラーが少なくなります。
もう1つの利点は 不変性 。オブジェクトの不変性は非常に重要です。値オブジェクトで使用できる特定のデータセットを格納するとき、私は通常、データが操作されるのが好きではありません。
これはいつ役に立ちますか?
この質問に対する完全な答えはありません。あなたにとって最善のこと、そして与えられた状況で最も理にかなっていることをしてください。
これ以外にも、その決定を下すのに役立つガイドラインがいくつかあります。
メソッドのグループが関連していると思うなら、まあ、貴重品はもっと高価です。この表現力は、値オブジェクトが特徴的なデータセットを表す必要があることを意味します。これは、平均的な開発者がオブジェクトの名前を見るだけで推測できます。
これどうやってやるの?
貴重品は特定の規則に従う必要があります。
この例では、属性を抽象化するために、値オブジェクトEntryStatus
を作成しますEntry#status_weather
およびEntry#status_landform
このように見える独自のクラスに:
注:これは単なるPORO(Plain Old Ruby Object)であり、ActiveRecord::Base
から継承されません。属性のリーダーメソッドを定義し、起動時にそれらを割り当てています。また、()メソッドを使用してオブジェクトを照合するために、同等の組み合わせを使用します。
モデルを変更できますEntry
作成した値オブジェクトを使用するには:
メソッドを変更することもできますEntryController#create
それに応じて新しい値オブジェクトを使用するには:
Serviceオブジェクトとは何ですか?
Serviceオブジェクトの役割は、ビジネスロジックの特定のスペースでコードを保持することです。スタイルとは異なり 「ファットモデル」 、少数のオブジェクトに多くのメソッドが含まれている場合、必要なすべてのロジックに対して、サービスオブジェクトを使用すると、それぞれが固有の目的を果たす多くのクラスが生成されます。
どうして?メリットは何ですか?
引き離します。 サービスオブジェクトは、オブジェクト間の分離を強化するのに役立ちます。
可視性。 サービスオブジェクト(適切な名前が付けられている場合)は、アプリケーションの機能を示します。 servicesディレクトリを調べて、アプリケーションが提供する機能を確認できます。
ドライ 変更を受け入れます。 私はサービスアイテムをできるだけシンプルで小さく保ちます。他のサービスオブジェクトと一緒にサービスオブジェクトを作成し、それらを再利用します。
テストスイートをクリーンアップして高速化します。 これらのサービスは、エントリポイント(呼び出されるメソッド)を持つ小さなRubyオブジェクトであるため、すばやく簡単にテストできます。複雑なサービスは他のサービスと複合されているため、テストを簡単に分離できます。また、サービスオブジェクトを使用すると、Rails環境全体をロードせずに、関連するオブジェクトを簡単に取得できます。
一方で、完璧なものはありません。サービスオブジェクトの欠点の1つは、小さなアクションごとにやり過ぎになる可能性があることです。このような場合、コードが複雑になり、単純化されない可能性があります。
いつサービスオブジェクトを抽出する必要がありますか?
ここにも決まったルールはありません。
通常、サービスオブジェクトは、中規模から大規模のシステムに最適です。標準のCRUD操作を超えて、適切な量のロジックを備えたシステムです。
したがって、コードの一部がディレクトリに属していない場合は、コードを追加する場所で、コードを再検討して、サービスオブジェクトに移動した方がよいかどうかを確認することをお勧めします。
Serviceオブジェクトをいつ使用するかについてのいくつかのポインタを次に示します。
サービスオブジェクトをどのように設計する必要がありますか?
サービスオブジェクトのクラスの設計は、必要がないため、比較的簡単です。 宝石 あなたは学ぶべきではありません DLS 新しいですが、可能であれば、多かれ少なかれ、すでに持っているソフトウェア設計スキルに頼ることができます。
通常、私は次のガイドラインと規則を使用してサービスオブジェクトを設計します。
app/services
。強力なビジネスロジックドメインには、サブディレクトリを使用することをお勧めします。たとえば、ファイルapp/services/report/generate_weekly.rb
定義しますReport::GenerateWeekly
一方app/services/report/publish_monthly.rb
Report::PublishMonthly
を定義します。ApproveTransaction
、SendTestNewsletter
、ImportUsersFromCsv
。StatisticsController#index
を見ると、コントローラーにグループ化されたメソッドのグループ(weeks_to_date_from
、weeks_to_date_to
、avg_distance
など)に気付くでしょう。それは良いことではありません。 statistics_controller
の外部で週次レポートを生成する場合は、その影響を考慮してください。
この例では、Report::GenerateWeekly
を作成します。 StatisticsController
からロジックレポートを抽出します。
だからStatisticsController#index
今ではきれいに見えます:
Serviceオブジェクトパターンを適用することで、複雑で特定のアクションを中心にコードをグループ化し、より小さく明確なメソッドの作成を促進します。
宿題: 使用を検討してください 貴重なオブジェクト WeeklyReport
Struct
の代わりに 。
オブジェクトとは クエリ ?
オブジェクト クエリ クエリデータベースを表すPOREです。アプリケーションのさまざまな場所で再利用できると同時に、クエリロジックを非表示にすることができます。また、テスト用の優れた絶縁ユニットも提供します。
複雑なSQL / NoSQLクエリを独自のクラスに抽出する必要があります。
各オブジェクト クエリ 基準/ビジネスルールに基づいて一連の結果を返す責任があります。
この例では、クエリはありません( クエリ )複雑なので、オブジェクトを使用します クエリ それは効率的ではないでしょう。ただし、デモンストレーションの目的で、クエリをReport::GenerateWeekly#call
で抽出します。作成しますgenerate_entries_query.rb
:
そしてReport::GenerateWeekly#call
で、置き換えましょう:
def call @user.entries.group_by(&:week).map do |week, entries| WeeklyReport.new( ... ) end end
と:
def call weekly_grouped_entries = GroupEntriesQuery.new(@user).call weekly_grouped_entries.map do |week, entries| WeeklyReport.new( ... ) end end
オブジェクトパターン クエリ (クエリ)は、コントローラーを細く保ちながら、モデルロジックをクラスの動作に厳密に関連させておくのに役立ちます。彼らはただの プレーンな古いRubyクラス 、オブジェクト クエリ ActiveRecord::Base
から継承する必要はなく、クエリの実行のみを担当する必要があります。
次に、新しいサービスオブジェクトへの新しいエントリを作成するロジックを抽出します。規則を使用して、CreateEntry
を作成しましょう:
そして今、私たちのEntriesController#create
以下のとおりであります:
def create begin CreateEntry.new(current_user, entry_params).call flash[:notice] = 'Entry was successfully created.' rescue Exception => e flash[:error] = e.message end redirect_to root_path end
今、物事はより面白くなり始めています。
ガイドラインでは、モデルに関連付けと定数を含めることに同意しましたが、それ以外は何もありません(検証や呼び出しはありません)。それでは、吹き出しを削除して、代わりにShapeオブジェクトを使用することから始めましょう。
ShapeオブジェクトはPORO(Plain Old Ruby Object)です。データベースと通信する必要がある場合は、コントローラー/サービスオブジェクトのコマンドを実行します。
なぜShapeオブジェクトを使用するのですか?
アプリケーションをリファクタリングする必要がある場合は、主な単一責任であることに留意することをお勧めします( 鎌 )。
鎌 クラスが持つべき責任に関して、より良い設計上の決定を下すのに役立ちます。
たとえば、データベーステーブルモデル(RailsのコンテキストではActiveRecordモデル)は、コード内の一意のデータベースレコードを表すため、ユーザーが行うことを気にする必要はありません。
これがShapeオブジェクトの出番です。
Shapeオブジェクトは、アプリケーションで形状を表す役割を果たします。したがって、各入力フィールドはクラスの属性として扱うことができます。これらの属性がいくつかの検証ルールを満たしていることを検証でき、「クリーンな」データを適切な場所に渡すことができます(たとえば、データベースモデルまたはクエリ検索ビルダー)。
Shapeオブジェクトはいつ使用する必要がありますか?
これにより、すべてのフォームロジック(命名規則、検証など)を1か所にまとめることができます。
Shapeオブジェクトを作成するにはどうすればよいですか?
ActiveModel::Model
(Rails 3では、代わりに名前、変換、検証を含める必要があります)。あなたが使用できることに注意してください 宝石 改革 、ただしPOROを続行して、entry_form.rb
を作成します。これは次のようになります:
そして、変更しますCreateEntry
Formatオブジェクトの使用を開始するにはEntryForm
:
class CreateEntry ...... ...... def call @entry_form = ::EntryForm.new(@params) if @entry_form.valid? .... else .... end end end
注意: ServiceオブジェクトからShapeオブジェクトにアクセスする必要はなく、コントローラーから直接Shapeオブジェクトを呼び出すことができると言う人もいます。これは有効な引数です。ただし、明確なフローが必要なため、常にServiceオブジェクトからFormオブジェクトを呼び出します。
以前に同意したように、モデルに検証と呼び出しを含めたくありません。 Shapeオブジェクトを使用して検証を抽出しました。ただし、まだいくつかの呼び出しを使用しています(after_create
モデル内Entry
compare_speed_and_notify_user
)。
モデルから呼び出しを削除したいのはなぜですか?
Rails開発者 彼らは通常、テスト中に電話の痛みに気づき始めます。 ActiveRecordモデルをテストしていない場合は、アプリケーションが大きくなり、呼び出しを呼び出したり回避したりするためにより多くのロジックが必要になるため、後で痛みに気付くようになります。
después_*
呼び出しは、主にオブジェクトの保存または続行に関連して使用されます。
フォーム知覚のゲシュタルト原則
オブジェクトが保存されると、オブジェクトの目的(責任など)が実行されます。したがって、オブジェクトが保存された後も呼び出しが呼び出されているのが見える場合、これらはおそらく責任のあるオブジェクト領域から抜け出そうとしている呼び出しであり、それが問題に遭遇したときです。
この例では、入力ドメインに関係のないSMSをユーザーに送信しています。
この問題を解決する簡単な方法は、呼び出しを関連するサービスオブジェクトに移動することです。結局のところ、対応するユーザーにSMSを送信することは、サービスオブジェクトに関連していますCreateEntry
エントリーモデルではありません。
これを行うことで、シャットダウンする必要がなくなります。compare_speed_and_notify_user
私たちのテストで。これを簡単な問題にし、SMSを送信せずにエントリを作成し、クラスに固有の責任を持たせることで、優れたオブジェクト指向設計に従います( 鎌 )。
だから今CreateEntry
これに似たものです:
コレクションは簡単に使えますが ドレーパー ビューモデルとデコレータについては、これまでと同じように、この記事ではPOROを使用します。
必要なのは、装飾されたオブジェクトのメソッドを呼び出すクラスです。
使用できますmethod_missing
これを実装するには、標準のRubyライブラリSimpleDelegator
を使用します。次のコードは、SimpleDelegator
の使用方法を示しています。ベースデコレータを実装するには:
% app/decorators/base_decorator.rb require 'delegate' class BaseDecorator なぜ_h
メソッド?
このメソッドは、ビューコンテキストのプロキシとして機能します。デフォルトでは、ビューコンテキストはビュークラスのインスタンスであり、これはActionView::Base
です。あなたはアクセスすることができます ヘルパー 次のようにビューの:
_h.content_tag :div, 'my-div', class: 'my-class'
より便利にするために、メソッドを追加しますdecorado
a ApplicationHelper
:
module ApplicationHelper # ..... def decorate(object, klass = nil) klass ||= '#{object.class}Decorator'.constantize decorator = klass.new(object, self) yield decorator if block_given? decorator end # ..... end
今、私たちは移動することができます ヘルパー EntriesHelper
デコレータへ:
# app/decorators/entry_decorator.rb class EntryDecorator そして、readable_time_period
を使用できます。およびreadable_speed
次のように:
# app/views/entries/_entry.html.erb - +
- +
リファクタリング後の構造
最終的にファイルが増えましたが、それは必ずしも悪いことではありません(これを覚えておいてください。最初から、この例はデモンストレーション目的であり、 番号 必然的にリファクタリングの良いユースケースでした):
app ├── assets │ └── ... ├── controllers │ ├── application_controller.rb │ ├── entries_controller.rb │ └── statistics_controller.rb ├── decorators │ ├── base_decorator.rb │ └── entry_decorator.rb ├── forms │ └── entry_form.rb ├── helpers │ └── application_helper.rb ├── mailers ├── models │ ├── entry.rb │ ├── entry_status.rb │ └── user.rb ├── queries │ └── group_entries_query.rb ├── services │ ├── create_entry.rb │ └── report │ └── generate_weekly.rb └── views ├── devise │ └── .. ├── entries │ ├── _entry.html.erb │ ├── _form.html.erb │ └── index.html.erb ├── layouts │ └── application.html.erb └── statistics └── index.html.erb
結論
このブログ投稿ではRailsに焦点を当てていますが、RoR(Ruby on Rails)はサービスオブジェクトや他のPOROに依存していません。このアプローチは、 フレームワークウェブ 、モバイルまたはコンソールアプリ。
使用する場合 MVC アーキテクチャとしては、ほとんどの変更がアプリケーションの他の部分に影響を与えるため、すべてがくっついて速度が低下します。また、ビジネスロジックをどこに配置するかを考える必要があります。モデル、コントローラー、またはビューのどこに配置する必要がありますか?
単純なPOROを使用することで、ビジネスロジックをモデルまたはサービスに移動しました。モデルまたはサービスはActiveRecord
から継承しません。これは、サポートするより明確なコードがあることは言うまでもなく、すでに利益になっています。 鎌 より高速なユニットテスト。
クリーンなアーキテクチャでは、アプリケーションの動作を簡単に確認できるように、構造の中央/上部に使用ボックスを配置しようとします。また、モジュール化されて分離されているため、変更の採用が容易になります。方法を示したと思います プレーンな古いRubyオブジェクト さらに抽象化すると、懸念事項が分離され、テストが簡素化され、クリーンで保守可能なコードの作成に役立ちます。
関連: Ruby on Railsの利点は何ですか?プログラミングの20年後。 Railsを使用する