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

Rubyでのジャンクドロワークラスの回避

Rubyはオブジェクト指向言語であるため、世界をオブジェクトのセットとしてモデル化する傾向があります。 2つの整数(xとy)は点であり、線には2つあると言います。

このアプローチはしばしば有用ですが、1つの大きな問題があります。これは、データの1つの解釈を他のすべてよりも優先します。 xとyは常に点であり、セルまたはベクトルとして機能する必要はないことを前提としています。

セルが必要な場合はどうなりますか?ええと、Pointがデータを所有しています。したがって、セルメソッドをPointに追加します。時間の経過とともに、ゆるやかに関連するメソッドのジャンクドロワーであるPointクラスになります。

ジャンクドロワークラスは非常に一般的であるため、私たちはそれらを避けられないものとして受け入れ、開発への「リファクタリング」ステップに取り組むことがよくあります。しかし、そもそも問題を回避できたらどうでしょうか?

Web開発の最初のルールは、私たちが話し合わないことですユーザークラス

戦闘で強化されたプロダクションRailsアプリの中心には、Userと呼ばれるクラスの巨大な怪物があります。 。

それは常に無邪気に始まります。ユーザーにログインを許可したい。ユーザー名とパスワードを保存する必要があるため、クラスを作成します。

class User
  attr_accessor :username, :password, :email, :address

  def authenticate!(password)
    ...
  end
end

それは非常にうまく機能するので、最終的に人々はあなたにお金を与えたいと思うでしょう。 「わかりました。ユーザーは基本的にサブスクライバーと同じものなので、いくつかの属性といくつかのメソッドを追加するだけです。」

class User
    ...

    attr_accessor :payment_processor_token, :subscription_plan_id, ...etc

    def charge_cc
      ...
    end
end

すごい!今、私たちはいくつかの本当のお金を稼いでいます! CEOは、営業チームが簡単にSalesForceにインポートできるように、ユーザーの連絡先情報を含むVCardをエクスポートできるようにすることを決定しました。 vimを起動する時間:

class User
    ...

    def export_vcard
      ...
    end
end

何をしましたか?

まず、認証を処理することだけを目的としたUserクラスから始めました。メソッドと属性を追加することで、ユーザー/サブスクライバー/連絡先のフランケンシュタインハイブリッドになりました。

なぜこれを行うのでしょうか?開発者としての自分を尊重しませんか?私たちの両親は私たちを十分に愛していませんでしたか?それとも、このデータが本当に であると信じて、失敗に備えたのでしょうか。 物、物?

ユーザー名、パスワード、メールアドレスの組み合わせがユーザーであると言うのはなぜですか?なぜ加入者ではないのですか?または連絡先?またはSessionHolder?

データについての真実は、それがデータであるということです

データは単なるデータです。今日、あなたはそれをボーイフレンドのように扱う必要があるかもしれません。明日は元カレかもしれません。

これは、Elixirのような関数型言語が採用するアプローチです。データは、Rubyのハッシュ、配列、文​​字列などのような単純な構造で格納されます。データを処理する場合は、データを関数に渡します。結果はその関数から返されます。

単純に聞こえますが、このアプローチにより、関心の分離を非常に簡単に異なるモジュールに分けることができます。

これは、Elixirでユーザーシステムを構築する方法の漫画です:

my_user = %{username: "foo", password: ..., phone: ..., payment_token: ...}
my_user = Authentication.authenticate(my_user)
my_user = Subscription.charge(my_user)
my_user = Contact.export_vcard(my_user)

データはコードとは別のものであるため、そのデータを特権的に解釈するモジュールはありません。

Rubyに戻す

このアプローチはElixirで非常にうまく機能するので、Rubyで採用してみませんか? Userの作成を妨げるものは何もありません データの単純なラッパーに変換し、すべてのビジネスロジックをモジュールにプルします。

class User
  attr_accessor :username, :password, :email, :address
end

module Authentication
  def self.authenticate!(user)
    ..
  end
end

module Subscription
  def self.charge(user)
    ..
  end
end

module Contact
  def self.export_vcard(user)
    ..
  end
end

Userを作成することもできます 構造体にクラス化するか、コードを追加して(一種の)不変にします。

だから何?

これは些細な変化のように見えますか?ポイントは何ですか?

これまで見てきたように、典型的なOOアプローチには、経年変化に伴う問題があります。特定のクラスが所有していると言うことによって データの場合、そのデータを他の方法で使用する必要があるときに問題が発生します。

ただし、モジュラーアプローチでは、動作を追加しても問題はありません。必要な方法でデータを解釈する新しいモジュールを作成するだけです。データと機能が完全に分離されているため、これを行うのは簡単です。

その他のアプローチ

ジャンクドロワーの問題を防ぐための他のアプローチがあります。従来、オブジェクト指向プログラミングでは、継承と慎重なリファクタリングを介してそうしようとしました。 2012年、SandiMetzはRubyでの実用的なオブジェクト指向の設計を公開しました。 これにより、多くの人が依存性注入を使用してオブジェクトの作成を開始するようになりました。さらに最近では、関数型プログラミングの人気により、Rubyistは不変の「データオブジェクト」を実験するようになりました。

これらのアプローチはすべて、クリーンで美しいコードを作成するために使用できます。ただし、クラスが通常データを所有しているという事実は、クラスが何であるかの間で常に緊張関係があることを意味します クラスがデータをどのように処理するか。

ジャンクドロワーの問題を回避する上でこれらのアプローチが成功したのは、データをコードから切り離した結果だと思います。


  1. Ruby開発者向けのデータ構造の概要

    データ構造とは何ですか? データ構造は、データを整理してアクセスするための特定の方法です。 。 例: 配列 二分木 ハッシュ さまざまなデータ構造がさまざまなタスクに優れています。 たとえば、辞書(単語と定義)や電話帳(人の名前と番号)のようなデータを保存する場合は、ハッシュが最適です。 利用可能なデータ構造を知る 、およびそれぞれの特徴 、より優れたRuby開発者になります。 それがこの記事で学ぶことです! 配列について 配列は、プログラミングについて読み始めたときに最初に学習するデータ構造です。 配列は、オブジェクトがギャップなしで次々に格納される連続したメモリのチャン

  2. Ruby2.6の9つの新機能

    Rubyの新しいバージョンには、新しい機能とパフォーマンスの改善が含まれています。 変更についていきますか? 見てみましょう! 無限の範囲 Ruby 2.5以前のバージョンは、すでに1つの形式の無限範囲をサポートしています( Float ::INFINITY を使用) )、しかしRuby2.6はこれを次のレベルに引き上げます。 新しい無限の範囲 次のようになります: (1..) これは、(1..10)のような終了値がないため、通常の範囲とは異なります。 。 使用例 : [a, b, c].zip(1..) # [[a, 1], [b, 2], [c, 3]] [1,2,3,