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

科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

ソフトウェア エンジニアに本番コードの重要な部分をレビューするよう依頼すると、必ずリファクタリングが必要な 3 つの点を指摘するでしょう。では、なぜこれほど多くの悪いコード、脆弱なコード、または誤解されたコードが実稼働環境で実行され続けるのでしょうか?

答えは簡単です。エンジニアはそれに触れるのを恐れているからです。リファクタリング タスクは特定されてバックログに追加されますが、現在のスプリントに反映されることはほとんどありません。

これには多くの理由があります。コードは何年も前にチームを離れたエンジニアによって書かれたものである可能性があり、それを完全に理解している人は誰もいません。また、その機能がビジネスにとって重要な場合もあります。潜在的な機能停止や収益の損失に対して責任を負いたくない人はいません。

この投稿では、Scientist を使用して重要な Ruby 本番コードを自信を持って移行、リファクタリング、変更する方法を検討します。

しかし最初に、コードの問題を調査するためにテストを使用できないのかと疑問に思うかもしれません。

これが Rails テストの目的ですよね?

はい、そしていいえ。多くの場合、展開前にコードの変更に完全な自信を得るのは困難です。単体テストとシステムテストに合格します。行っても大丈夫ですよね?

現実には、現実の世界、つまり生産に代わるものはありません。データの品質が悪い場合、またはテストが欠落している場合はどうなりますか?新しいソフトウェアが実稼働スループットを処理するのに十分なパフォーマンスを発揮するかどうかは、どうすればわかりますか?

パブリック サービスを扱うチームは、「互換性のバグ」の問題に対処する必要があることに気づくことがあります。本番環境にしばらくの間バグが存在する場合、クライアントは一貫して不正な動作に依存するコードを作成する可能性があります。顧客はソフトウェアを予期しない方法で使用することがよくあります。

科学者と一緒に Ruby と Rails のプロダクションの変更を観察する

変更を確信するのに本番環境が最適な場合は、そこでコードがどのように動作するかを観察することを検討してください。 「本番環境でのテスト」という考え方は古典的なソフトウェア エンジニアリングの実践に矛盾するため、最初は怖く聞こえるかもしれません。

ただし、幸いなことに、Scientist gem を使用すると、Ruby と Rails でこれを行うのが簡単かつ安全です。科学者の名前は、与えられた仮説を検証するために実験を行う科学的方法に基づいています。この場合、私たちの仮説は、新しいコードがその役割を果たしているということです。

このアプローチを安全に採用できる理由は、実験で依然として既存のコードの結果が使用されているという事実に由来します。新しいコードは、精度とパフォーマンスの両方について、観察と比較の目的でのみ評価されます。実際のデータとパラメーターを使用してパフォーマンスを評価することで、前述したテスト カバレッジの懸念を軽減します。通常、実験では、本番環境への影響を最小限に抑えるために、選択したリクエストのサンプル レートを評価します。ただし、必要に応じてすべてのリクエストを評価できます。

ここで、Scientist が抽象化によってブランチでどのように動作するかを簡単に見てみましょう。

Ruby の Scientist における抽象化パターンによる分岐

科学者のアプローチは、Martin Fowler が「段階的な方法でソフトウェア システムに大規模な変更を加える」と説明した、抽象化による分岐パターンから始まります。

更新されるコードを分離するために抽象化レイヤーを導入します。この層は、実験がシステムの他の部分に対して透過的に行われるように、どの実装を使用するかを決定します。この手法は、コード パスを決定する機能フラグの使用に関連しています。

Github から生まれた Scientist gem は、実験を使用してこのパターンを実装します。既存のコードはコントロールと呼ばれ、新しい実装が候補となります。どちらのコード パスもランダムな順序で実行されますが、制御結果のみがクライアントに返されます。

Scientist を使用して Ruby サービスをリファクタリングする

指定された数値の最大の素因数を返す Ruby サービスを考えてみましょう。必要な候補セットを取り除き、サービスを高速化するための最適化を特定したと仮定します。

ただし、サービス所有者は、バグが持ち込まれていないことを確認したいと考えています。また、パフォーマンスの向上も観察したいと考えています。次のコードを導入し、このメソッドを呼び出すようにクライアントを変更します。

 

この時点では、use のみです。 (コントロール) 式が呼び出されます。実験を価値のあるものにするには、カスタム Experiment を定義します。 クラスを使用してそれを有効にし(以下では 100% の場合)、結果を公開します(この場合はログを記録するだけです)。 Scientist は素晴らしいデータを生成しますが、デフォルトではそれに対して何も行いません。その部分はあなた次第です。

 

実験の結果は記録され、フィードバックに基づいて時間をかけて改善することができます。新しいコードが要件を満たし、信頼性が高くなったら、サイエンス コードを新しい実装への委任に置き換えるだけで、新しい実装へのカットオーバーを実行できます。

LabTech が Ruby on Rails での科学者の実験を簡素化

Rails アプリケーションで LabTech gem を使用すると、Scientist を簡単に構成して結果を処理できます。

AppSignal を使用するアプリケーションは、Appsignal.instrument を使用できます。 Scientist イベントが完了するまでにかかる時間を追跡するためのカスタム インストルメンテーション ヘルパー。これをさまざまな実験コード ブロックにラップして、パフォーマンス タイムラインにイベントが表示されることを確認します。

さて、LabTech に戻ります。以下の Web ページでは、単純に因数分解する数値を受け入れます。

科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

コンソールにアクセスできれば、簡単に始めることができます。まず、LabTech gem を Gemfile に追加し、bundle install を実行します。 .

 

テーブルには結果と実験構成が保存されるため、データベースの移行を実行します。

 

LabTech モジュールが使用されることを除いて、抽象化レイヤーは同じです。完全なコードは GitHub で入手できます。

 

この時点では実験は無効になっているため、コンソールを使用して、すべての場合または一定の時間だけ有効にします。

 

これでテストを実行できるようになり、実験が評価されます。結果をテキストで表示するには、Rails コンソールから次のコマンドのいずれかを使用します。

 

数回の実行が成功し、1 回の製造エラーが発生した後の結果の概要の例を次に示します。成功と失敗の概要と、パフォーマンスの違いを示す ASCII グラフがあります。

 

Blade gem は、結果を簡単に分析するための優れた方法を提供します。インストールが簡単で、テーブルに対して SQL クエリを実行できるようになります。ここのクエリは、候補の実装が元の実装よりも大幅に高速であることを示しています。

科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

プライム ファクタリング サービスの例では、改善された実装における速度向上は、考慮すべきいくつかの考えられる要素を排除するヒューリスティックによってもたらされます。より大きな数値を検討して素因数を見つけると、その因数で割ったターゲットの数値に到達したら検索を停止できます。新しいコード パスは、これを実現するためにステートメントを 1 つ追加するだけです。

LabTech テーブルに対して Blade クエリを使用すると、実行時間の短縮も確認できます。

科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

Scientist のユースケースと制限

Scientist の最適な使用例には、検索、計算、副作用のないコードが含まれます。トランザクション更新や電子メールなどの外部統合を含むコードは、機能が 2 回 (古い実装と新しい実装の両方で) 実行されるため、モデルにうまく適合しません。

これは、いくつかの使用例を排除するため、簡単な制限ではありません。ただし、実験が成功にとって重要である場合には、いくつかの回避策があります。副作用が関連しているかどうか、または重複が問題であるかどうかを検討してください。たとえば、場合によっては、評価中に 2 通の電子メールが送信されるかどうかは問題ではない場合があります。別のオプションは、新しいコードで結果を決定しますが、結果を永続化しないことです。これにより、意味のあるパフォーマンス比較ができなくなります。ただし、正確性を検証することはできます。

その他の制限は、Scientist が戻り値に重点を置いていることに起因しています。場合によっては、単に応答にタイムスタンプが含まれているか、特定の要因が変化しているかにかかわらず、有効な結果が時間の経過とともに差異を示すことがあります。多くの場合、実験でカスタム比較ロジックを作成して、基本的な文字列比較を超える精度を検証できます。

最後に、LabTech の制限は、この記事の執筆時点では Rails 7 に移植されていないことです。

科学者による Rails での効果的な実験のためのベスト プラクティス

実験を実装するときは、次の項目を考慮してください。

  • Rails プロジェクトでは、Scientist をイニシャライザまたは Rails LabTech gem のようなラッパーで構成できます。ほとんどの Rails アプリケーションにはすでにデータベースがあるため、LabTech は ActiveRecord を利用して結果を保存します。
  • 開発やテストの速度低下を避けるため、実験はステージング環境と本番環境でのみ有効にしてください。
  • 本番環境への潜在的な影響を最小限に抑えるために、一定の割合のリクエストに対してのみテストを実行します。 LabTech は、実験を有効にするときのオプションのパラメータとしてこれをすぐにサポートします (最初はデフォルトで無効になっています)。 Pure Scientist を使用すると、このロジックは実験の enabled? で簡単にコーディングできます。 メソッド。
  • 一部のロジックはリソースを大量に消費するため、低いサンプリング レートから始めるとよいでしょう。結果に自信が持てるようになったら、評価されるリクエストの割合を増やしてください。
  • コンテキスト属性を追加して、結果を最大限に活用できます。実験コンテキストは、データのシンボルキー付きハッシュに設定でき、その後、公開された結果で利用できるようになります。
 

まとめ:科学者と一緒に Ruby アプリを観察および監視する

この投稿では、Scientist gem を使用して実稼働環境で Ruby コードを変更、移行、リファクタリングする方法を検討しました。

私たちは、Branch by Abstraction パターンにおける Scientist の起源を調べてから、リファクタリングに飛び込みました。次に、LabTech が結果の収集と Scientist の構成にどのように役立つかを見ていきました。

次に、Scientist のいくつかの制限について触れた後、最後にいくつかのベスト プラクティスの概要を説明します。

システム内で何が起こっているかを観察し監視する必要があります。 Scientist を開発プロセスに統合すると、より自信を持って Ruby コードに重要な変更を加えることができます。

コーディングを楽しんでください!

追記Ruby Magic の投稿を報道後すぐに読みたい場合は、Ruby Magic ニュースレターを購読して、投稿を 1 つも見逃さないようにしてください。

科学者による重要な Ruby on Rails コードのリファクタリング:実証済みのアプローチ

ダレン・ブルマー

ダレンは、書かれた言葉を通じてインスピレーションを与え、複雑なことを理解しやすくすることを楽しんでいます。彼の興味は科学と物理学、そしてそれらの両方を理解するのに十分な数学です。彼は高品質のコンテンツとテクノロジー ソリューションを作成しており、それについて時折ツイートしています。

Darren Broemmer によるすべての記事


  1. ViewComponentGemの紹介

    Reactに触発されたViewComponentsは、ビューをレンダリングするためのマークアップを構築するために使用されるRubyオブジェクトです。 ViewComponentは、Railsで再利用可能、テスト可能、およびカプセル化されたビューコンポーネントを構築するためのフレームワークです。通常、再利用可能なビューは、パーシャルを使用してRailsで作成され、必要に応じてさまざまなビューでレンダリングされますが、ViewComponent gemの導入により、パーシャルをビューコンポーネントと交換できるため、より多くの利点が得られます。これらの利点について詳しく見ていきましょう。 いつ、なぜ

  2. 実証済みの技術で Ruby と Rails のバグを迅速に解決

    ソフトウェアのバグは、破壊的で、とらえどころがなく、不快で、侵入的である可能性があります。実際、開発者は問題を見つけて修正するためにエジソンの粘り強さを必要とすることがよくあります。 しかし、開発者に必要な資産は根性だけではありません。コードをデバッグするための情報も必要です。問題の症状と影響は何ですか?その頻度はどれくらいですか?浸透性?来歴?バグの証拠と成果物 (コア ダンプ、スタック トレース、ログ、テスト ケース) は非常に貴重です。 Ruby と Rails 開発者が問題の証拠を収集して調査するためにすぐに利用できるいくつかのテクニックとツールを見てみましょう。データは粘り強さに