コールバックの代替

1つ以上のサービスを作成するための注文の入力データに応じて、注文を作成できる鉄道アプリケーションを作成する必要があると仮定しましょう。これらのサービスのためにリソースを予約します。



処理中に、注文の状態が新規から完了に変わりますが、いくつかのサービスが作成され(データに応じて)、注文処理の終了までにそれらを起動して動作する必要があります。 簡単な例-セルのSIMカードを作成します。 音声通信、SMS-okおよびMMS-ok、モバイルインターネット(独自の料金設定)、留守番電話、発信者IDなどのサービスは、このSIMカードに「接続」されます。 契約(注文)の処理が終了するまでに、これらのサービスはすべて稼働しているはずです。 さらに、追加の結論を出すことができます。 契約し、他のモバイルインターネット料金などに切り替える これは、わかりやすくするために参照するロジックの例にすぎません。



大多数のプログラマーは、コールバックまたはトリガーでそのようなアプリケーションを作成し始めます。 新しい注文が作成され、新しい状態になり、サービスの作成などを開始するコールバックを切断します。 次に、これが絶対的な悪である理由を説明しようとします。



コールバックは制御されません



アプリケーションには10〜15個のコールバックがありますが、それらを何らかの方法で制御できます。 アプリケーションにモデルが追加されるとすぐに、コールバックの数が増えます。 1つのコールバックがデータを変更します。これにより、2番目のコールバックが機能し、他のデータが変更されます。3番目のコールバックが機能するなどです。 その結果、チェーン全体を復元し、何がなぜ発生したかを理解することは容易ではありません。 ループコールバックなどのオプションについては既に説明していません。1回目は機能し、2回目は機能しました... 10回目は機能し、その変更の結果、最初のコールバックが再び機能しました。 または、最初に動作し、次に3番目、5番目、2番目に動作します(ここでは番号付けは条件付きです-わかりやすくするためです)。 コールバックの制御されたシーケンスについても話していません。 それぞれ独自。



コールバック履歴



令状があります。 それは部分的に処理された後、アプリケーションの次の更新を展開しました-ロジックが変更されました-ユーザーがあなたに来て、同じ質問をします-「なぜそのような値があるのですか」。 ここで、現在のコードを理解するだけでなく、コールバックが機能するはずだったときに使用されたコードのバージョンを確認する必要があります。それ以外の前提があります。



論理バージョン



コールバックロジックを変更する必要があるとします。 たとえば、以前、ある条件が満たされると、あるタイプのサービスが作成され、現在は別のタイプのサービスが作成されていました。 ただし、すでに処理されている注文(古いロジックで開始され、まだ完全に処理されていない注文)の場合は、古いロジックを保存する必要があります。

コールバックは成長しています-新しいロジックを作成し、古いロジックを保持する必要があります。これは、たとえば特定の日付までに開始された注文に対して機能します。 ビジネスユーザーが、7年間「不完全」だった注文を処理しようとした場合がありました。 この間にどのくらいのロジックとコードが変更されたか-想像してみてください。



コールバックはひどく監視されています



ビジネスユーザーがあなたのところに来て、「このサービスにはなぜこんな価値があるのか​​」という質問をすると、最初の問題に直面します。データベースやログなどを見る必要があります。

どのコールバックが機能し、関心のあるデータを変更したかを把握することさえ非常に困難な作業になる可能性があり、その上で1日以上殺すことができます。 実際、ログをどれだけ掘り下げても、結果として、「このコールバックがこの理由とその理由で機能した」と仮定することしかできません。 ログがある場合でも、システムが成長するにつれて、仮定にどんどん滑り込んでいきます。 おそらくいくつかのコールバックが機能し、このモデルに同じ値を設定しました。 それは本当に悪いです 問題の分析、再現、除去の複雑さは指数関数的に増大します。



モデルにスナップ



コールバックの私の「お気に入り」の罪-それらはモデルにしっかりと結びついています。 今日、TypeAの注文があり、明日はTypeBの注文に置き換えられました-必要なコールバックが発生していません-注文処理チェーンが壊れています。 もちろん、修正することができます-技術的にはこれはコードエラーですが、実際には、このエラーが原則的に発生しないようにアプリケーションを構築する方が良いでしょう。

次に、2つの注文状態(新規および完了、関連するコールバック)を配置します。 ロジックを複雑にする必要があります-ロジック処理中にコールバックを追加します。 例えば、失敗、処理-そしてそれらにいくつかのコールバックを追加します。 注文は、その処理中に数回失敗する可能性があり、数回処理に入る可能性があります-毎回コールバックが機能します。

その後、失敗後のロジックが異なり、再処理ステータスが表示され(たとえば)、ロジックがさらに大きくなることがわかりました。 コールバックの数は増え続けています。 注文が支払われるかどうかに留意する必要があります。これらは、異なるモデルパラメーターに関連付けられたコールバックです。 注文が支払われていない間(支払済み-注文の1つのフィールド、ステータス-別の)サービスは開始できません。 -あなたは、まだほとんど支払われていない注文などの新しい状態を思いつき始めます。 -新しい状態を作成し始めると、それらにロジックを追加できます。 条件の組み合わせ(有料/処理済み、未払い/処理済みなど)がますます増えています。 コールバックはますます難しくなっています。



ロジック分離なし



説明しようと思います-あなたがモバイルインターネットサービスを持っているとしましょう。 このサービスが開始された最初の注文があり、次に2番目の注文がありました-関税計画を変更します-サービスは本質的に同じですが、異なるように請求され、異なるインターネット速度などを持っています コールバックでは、最初の注文に関連付けられたロジックを2番目の注文に関連付けられたロジックから分離することはできません。すべてがサービスモデルに関連付けられています。

さらに-簿記があります-ビジネスロジックが注文の支払いに関連し、インターネットを提供する必要がある技術部門があります-それは異なるビジネスロジックを持っています-そしてそれらは実際に隔離されるべきです。 コールバックでは、すべてが注文のモデルに取りつかれています。会計と技術部門の処理を分離することはすでに不可能です。 簿記は、複数の支払い(複数の「プロセス」)でサービスに支払うことができ、技術部門は、同じサービスを提供するために技術サポートと一部のサービス操作を数回実行できます。 。



結論は簡単です。アプリケーションのロジックをモデルに結び付けるべきではありません。



代替案



最初に理解する必要があること-ビジネスロジックがある場合は、モデルではなくそれを添付する必要があります。 注文処理のフローがあります-これは、モデルの代わりにこれらすべてが関連付けられているエンティティが必要であることを意味します。 巧妙さなしでは、このエンティティを「プロセス」と呼びます。



すべてのビジネスロジックは、オプションとして、オペレーションの形でプロセスに関連付けられています。 つまり 技術的には、順序を変更したプロセスを開くことができます-そして、それらが作成されたとき、それらがどのように機能したか、どのユーザーが関与したか、何が変更され、何が行われたのか、どの操作が機能したのか(そしてなぜ)-を確認します 推測だけでなく、プロセスの正確な履歴も必要です。 プラス-まだ完了していないプロセスを確認できるようにすることをお勧めします-プロセスの一部として実行できる他の操作。 プロセスで何かが壊れた場合-データ/コードを修正する必要があります-コンソールを介してオブジェクトの状態を変更して、コールバックが機能し、プロセスがさらに進むように、プロセスをさらに開始できるようにします。



次に-ユーザーはプロセスに関与します。 コールバックのアプリケーション(ユーザーが実際にロジックからスローされる)が何らかの順序になり、一部のデータが変更された場合、コールバックが発動し、順序がさらに処理されます。 プロセスの場合、「ユーザー操作」などの概念を導入できます。また、プロセス中に特定のユーザー操作を待機し、プロセス中に次のユーザー操作が作成および実行されると言うことができます。 「ユーザー」操作の一部として、ユーザーは複数のモデルのデータを変更できます。



次に、プロセスの何らかの種類の構成が必要です-含まれる操作、操作の依存関係などを指定する機能



プロセスと操作には独自のデータスコープが必要です-プロセスのみが必要とするデータをモデルにロードできない中間プロセス変数。 その結果、モデルはよりシンプルで簡単になります。



これまでのところ、私はそこで停止します。 トピックが興味深い場合は、さらに書くことがあります。 誰が気にしますか-gem rails_workflowを参照して質問してください。



All Articles