将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
多くの人がRailsフレームワークからRubyを学んでいますが、残念ながらこれはこの言語を学ぶ上で最悪の方法です。誤解しないでください:Railsは素晴らしく、多くの技術的な細部に触れることなく、Webアプリケーションを迅速かつ効率的に構築するのに役立ちます。
多くの人がRailsフレームワークからRubyを学んでいますが、残念ながらこれはこの言語を学ぶ上で最悪の方法です。誤解しないでください:Railsは素晴らしいもので、技術的な詳細に触れることなく、Webアプリケーションを迅速かつ効率的に構築するのに役立ちます。Railsは、物事をシンプルに動作させる「Railsマジック」をたくさん提供してくれます。初心者プログラマにとって、これは本当に素晴らしいことです。なぜなら、プロセスの中で最も楽しい瞬間は、「生きている!」と言えるとき、そしてすべてのパーツが組み合わさって、人々があなたのアプリを使うのを確認できるときだからです。私たちは「クリエイター」であることが好きです🙂 しかし、優秀なプログラマーと平均的なプログラマーを区別するものが1つあります。ツールを理解する」というのは、フレームワークが提供するすべてのメソッドやモジュールを知っているという意味ではなく、フレームワークがどのように動作するのか、「Railsマジック」がどのように起こるのかを理解するという意味です。そうして初めて、オブジェクトを使ってRailsでプログラミングすることに安心感を持てるようになります。オブジェクト指向プログラミングの基礎であり、複雑なRailsアプリケーションを簡単にする秘密兵器が、タイトルにもあるPORO(Plain Old Ruby Object)です。
その名の下にある本当のものとは?この偉大な秘密兵器は何なのか?それは、何も継承しないシンプルなRubyのクラスである。そう、ただそれだけなのだ。
クラス AwesomePoro
終了
あなたはアプリケーションを継続的に開発し、新しい機能を追加しています。そのような場所は、勇敢な開発者でさえ疫病のように避ける場所です。そのような場所が多ければ多いほど、アプリケーションを管理し開発するのは難しくなります。標準的な例は、新規ユーザーを登録するアクションで、このイベントに関連する他のアクションのグループ全体をトリガーします:
サンプル コード ユーザー登録の責任者は次のようになる:
class RegistrationController < ApplicationController
def create
user = User.new(registration_params)
if user.valid? && ip_valid?(registration_ip)
user.save
user.add_bonuses
user.synchronize_related_accounts
user.send_email
終了
終了
終了
よし、コード化できた、すべてうまくいった、でも......このコード、本当に全部でいいの?もっとうまく書けないだろうか?まず第一に、これはプログラミングの基本原則である単一責任を破っている。でもどうやって?そこで、すでに述べたPOROが役に立つ。RegistrationServiceクラスを分離すれば十分で、そのクラスはただ一つのこと、つまり関連するすべてのサービスに通知することだけに責任を持つ。サービスとは、上記ですでに取り上げた個々のアクションを指します。同じコントローラ内で必要なことは、RegistrationServiceオブジェクトを作成し、"fire!"メソッドを呼び出すことだけです。コードはより明快になり、コントローラの占有スペースも小さくなりました。また、新しく作成したクラスはそれぞれ1つのアクションを担当するだけなので、必要に応じて簡単に置き換えることができます。
クラス RegistrationService
def fire!(params)
user = User.new(パラメータ)
if user.valid? && ip_validator.valid?(registration_ip)
user.save!
after_registered_events(user)
終了
ユーザー
終了
private
def after_registered_events(user)
BonusesCreator.new.fire!(ユーザー)
AccountsSynchronizator.fire!(user)
EmailSender.fire!(user)
終了
def ip_validator
ip_validator ||= IpValidator.new
end
end
class RegistrationController < ApplicationController
def create
user = RegistrationService.new.fire!(registration_params)
end
エンド
しかし、Plain Old Ruby Objectは、コントローラだけでなく、アプリケーションにも使えるかもしれません。あなたが作成しようとしているアプリケーションが、月次課金システムを使用しているとしましょう。そのような請求書を作成する正確な日は、私たちにとっては重要ではありません。もちろん、各月の初日に日を設定し、この情報を "Date "クラスのオブジェクトに格納することはできますが、これは真の情報ではありませんし、アプリケーションで必要とするものでもありません。POROを使用すれば、"MonthOfYear "クラスを作成することができ、そのオブジェクトは、あなたが必要とする正確な情報を格納します。さらに、その中にモジュール "Comparable "を適用すると、Dateクラスを使用しているときと同じように、そのオブジェクトを反復したり、比較したりすることが可能になります。
クラス MonthOfYear
include 比較可能
attr_reader :年, :月
def initialize(month, year)
raise ArgumentError unless month.between?(1, 12)
年, 月 = 年, 月
終了
def (other)
[年, 月] [その他.年, その他.月].
end
終了
Railsの世界では、各クラスがモデル、ビュー、コントローラであるという事実に慣れています。また、ディレクトリ構造内の正確な位置も決まっています。では、私たちの小さなPORO軍団はどこに置けばいいのでしょうか?いくつかの選択肢を考えてみましょう。最初に思いつくのは、作成されたクラスがモデルでもビューでもコントローラでもない場合、それらをすべて「/lib」ディレクトリに置くべきだということです。理論的には、それは良いアイデアですが、しかし、すべてのPOROファイルが1つのディレクトリにあり、アプリケーションが大きくなる場合、このディレクトリはすぐに、開くのが怖い暗い場所になるでしょう。従って、間違いなく良いアイデアではありません。
オーサムプロジェクト
アプリ
├── コントローラー
モデル
ビュー
│
└──lib
サービス
1TP63トールポロはこちら
また、ActiveRecordモデルでないクラスに名前を付けて "app/models "ディレクトリに置き、他のクラスの処理を担当するクラスに名前を付けて "app/services "ディレクトリに置くこともできます。これはかなり良い解決策ですが、1つ欠点があります。新しいPOROを作成するときに、毎回、それがモデルなのかサービスなのかを決めなければなりません。新しいPOROを作成するときに、それがモデルなのかサービスなのかを毎回決めなければなりません。つまり、名前空間付きのクラスとモジュールを使う方法です。コントローラやモデルと同じ名前のディレクトリを作成し、その中にコントローラやモデルで使用するすべてのPOROファイルを置くだけです。
オーサムプロジェクト
アプリ
│ ├──controllers
│ ├─registration_controller
│ │ └─registration_service.rb
│ └─registration_controller.rb
モデル
│ ├──settlement
│ │ └──month_of_year.rb
│ │ └─settlement.rb
│ └──views
│
└─lib
この配置のおかげで、これを使うときにクラス名の前に名前空間を付ける必要がなくなります。より短いコードと、より論理的に整理されたディレクトリ構造を得ることができます。
POROを使うと、アプリケーションの単体テストがより速く、より簡単に書けるようになり、後で他の人に理解されやすくなるというのは、嬉しい驚きです。各クラスが1つのことだけを担当するようになったので、境界条件をより早く認識でき、適切なテストシナリオを簡単に追加できます。
記述 MonthOfYear do
subject { MonthOfYear.new(11, 2015) }.
it { be_kind_of Comparable }とする。
describe "新しいインスタンスの作成" do
it "正しい年と月で初期化する" do
期待 { described_class.new(10, 2015) }.to_not raise_error
終了
it "指定された月が正しくない場合にエラーを発生させる" do
expect { described_class.new(0, 2015) }.to raise_error(ArgumentError)
expect { described_class.new(13, 2015) }.to raise_error(引数エラー)
終了
終了
end
我々が提示した例は、POROを使うことでアプリケーションの可読性が向上し、よりモジュール化され、その結果、管理や拡張が容易になることを明確に示している。単一責任の原則を採用することで、必要に応じて特定のクラスを交換することが容易になり、他の要素に干渉することなく交換することができます。また、テストをよりシンプルかつ迅速に行うことができます。さらに、Railsのモデルやコントローラを短くまとめるのはずっと簡単です。