8


11

私は、アプリケーションを構築する際にできるだけRESTfulになろうとしていますが、確信が持てないことの1つは、ウィザード形式のワークフローを作成する方法、RESTfulで簡潔な方法です。

たとえば、複数ページの申し込み手続きを行います。

*オプション1:*ステップごとにコントローラーを作成し、ユーザーがそのステップに到達したとき(または戻ったとき)にnewまたはeditを呼び出すことができます。 step1_controller、step2_controllerなどで終わります。

オプション2: 1つのコントローラを作成し、パラメータ、セッション変数、ステートマシンなどを使ってサインアッププロセスのどこにいるかを追跡できます。 それで、私はsignup_controller / stepを持っているでしょうか?id = 1

最初のオプションは厳密にRESTですが、あまり簡潔ではなく、いくつかの追加のコントローラーで終わります。 2番目の選択肢はより簡潔ですが、RESTを無効にします。

より良い選択肢はありますか?

私はRuby on Railsで作業していますが、この質問はASP.NET MVCのような他のMVC実装にも当てはまります。

3 Answer


12


ここでいくつかのDDDロジックを適用すると、MVCの "M"が補完され、UIの状態(登録の進行状況)はアプリケーション層に属し、ドメイン層とインフラストラクチャ層(4層:UI、アプリケーション、ドメインとインフラストラクチャ) DDDの概念により、最初にコードでソリューションを解決する方法について「考える」ことができます。 これを踏みましょう…​

それはプログレスバーです

ここで維持したい状態は、登録のステップまたは進行状況です。 だから、私の最初のステップは、進捗状況や「ステップ」を文書化することです。 ステップ1:ユーザー名/パスの取得、ステップ2:Eメールの取得など。 この場合は、モデルを次のステップに「移動」するためのロジックを適用します。 ほとんどの場合、RegistrationService(RegistrationService.NextStep())のNextStep()メソッドを使用します。

ああ、でもApp層に属している

RegistrationServiceという名前のアプリケーション層にサービスを作成します。 ここにNextStep()というメソッドを配置します。 しかし、覚えておいて、ドメインはここでモデルの状態を保持しないでしょう。 この場合は、アプリケーション層に状態を集中させたいと思います。 したがって、この場合、NextStep()はモデルオブジェクトではなく(ドメインの責任の一部ではないため)、代わりにUIに作用します。 だから、あなたは登録プロセスの状態を保持するために何かが必要です。

ドメインモデルから離れて、ViewModelはどうですか?

そのため、UIの中で何かの状態を保持する必要があることがわかりました。 MVCはViewModelsと呼ばれる概念を可能にします(ASP.NET MVCでは、RoRがそれを呼んでいるのかわかりません)。 ViewModelは、ビューまたは部分ビュー、あるいはその両方によって表示されるモデルを表します。

ViewModelは、このオブジェクトの状態を保存するのに最適な場所です。 それをRegistrationProgressViewModel()と呼び、NextStep()メソッドを貼り付けます。 もちろんこれは、Application層がRegistrationProgressViewModelの位置を保持する必要があり、APplication層がNextStepアクションに基づいてその内部を変更することを意味します。 複雑な場合は、アプリケーション層にRegistrationProgressService()を作成し、その中にNextStep()を配置してロジックを抽象化します。

ViewModelを渡す方法は?

最後の部分は、そのオブジェクトの状態を追跡する方法です。 Webアプリケーションはステートレスなので、アプリケーション以外の方法で制御を維持する必要があります。 この場合は、1)ViewModelをシリアル化してクライアントにやり取りさせる、または2)ViewModelのサーバー側のコピーを保持し、何らかのタイプの識別子をやり取りする、のいずれかに戻ります。クライアントにそして戻って。

これは私自身ではまだ実行していないので、これは考えるのに良い例です。 #2の場合、このViewModelの状態を保存する最も安全で確実な方法は、インフラストラクチャ層を介して永続化することです(はい、APp層はインフラストラクチャ層と直接通信できます)。 それは私には大変な作業のように思われます。それは、消える可能性があり、私のDBに部分的な登録があるからです。

しかし、#2はユーザーの個人情報(ユーザー名、パスワード、電子メール、CC#など)をすべてサーバー側に保持し、やり取りしません。

最後に、答え!

それで、それを通り抜けた後に、我々は思いつきました:

  • アプリケーション層にRegistrationProgressViewModel()を作成します。

  • アプリケーション層で、NextStep(ViewModel vm)メソッドを使用してRegistrationProgressService()を作成します。

  • NextStep()が実行されると、インフラストラクチャ層を介してViewModelをデータベースに永続化します。

このようにして、ViewModelが更新され更新される(Authenticated、Verified、DBに永続化される)ので、ViewまたはUI自体で何を「step?id = 2」追跡する必要がなくなります。

それで、あなたの次の関心事はUIで「前進する」ことでしょう。 これは、ステップまたは名前付きステップを使用して、1つのコントローラーで簡単に実行できます。

申し訳ありませんが、私の言語がC言語であるため、以下にC#コードを書いています。

パブリッククラスRegistrationController:Controller {// http://domain.com/register public ActionResult Index(){return View(new RegistrationProgressViewModel);} }

// http://domain.com/register //そして、これは自分自身への投稿です。 以下のモデルの// "CurrentStep"プロパティの設定に注意してください。 //パブリックActionResultインデックス(RegistrationProgressViewModelモデル){

//ここのNextStep()のロジックは、// ViewModelの周囲のビジネスルールをチェックし、その正当性を検証し、妥当であれば// ViewModelの "CurrentStep"を増やし、最後にインフラストラクチャを介してviewmodelをDBに永続化//レイヤー。 // RegistrationProgressService.NextStep(model);

switch(model.CurrentStep){ケース2://ここでステップ2のビューを配線する。 ... ビュー(モデル)を返します。ケース3://ここでステップ3のビューを配線します。 ... ビュー(モデル)を返します。ケース4://ここでステップ4のビューを配線します。 ... ビュー(モデル)を返します。デフォルト://最初のページに戻る... ビュー(モデル)を返します。 }}}

これにより、モデルの内部状態を確認する「ビジネスロジック」がRegistrationProcessService.NextStep()メソッドに抽象化されることがわかります。

いい運動。 :)

最後に、あなたの "RESTful" URLは:/ registerへのきれいできれいなPOSTです。これはViewModelに特定のプロパティが埋められていることを期待します。 ViewModelが無効な場合、/ registerは次のステップに進みません。


7


私は実際にはワンショットウィザードでRESTを維持することについてそれほど心配していません。 RESTは最も重要なことだと思います。繰り返し可能なアクションでは、URLを基本的にブックマーク可能にして、いつ行っても同じデータビューに戻るようにします。 マルチステップウィザードでは、とにかくこのRESTの観点を破ることになる依存関係があります。 私の考えでは、潜在的に別々のアクションを持つ単一のコントローラーを持つこと、またはあなたがどのステップにいるのかを示すためにクエリーパラメーターを使うことです。 これは私がとにかく私がどうやって私のアクティベーションウィザード(複数のステップを必要とする)を構成したかということです。


1


答えは確かにとても良い選択肢ですが、私はまだ以下に与えられたアプローチを使います:

一見の価値があります。 私が言わなければならないけれども、ここに与えられた答えは私が時間があるときこのウィザードを作り直すことを私に考えさせる。