1

私は過去数日間DDDをよく読んでいて、誰かが自分のサイトにユーザーを登録する方法の確かな例を見つけることができなかったので、たくさん読んだ後、私はこれをまとめました。フィードバックをお願いします。それは完璧にはほど遠いと確信しているので、それは完全に間違っているかもしれませんが、ここにそれがあります:

RegisterController

$userMapper = $this->dataMapperFactory->build('user');
if($userMapper->fetchByUsername($username) !== NULL) {
    // Error: The chosen username already exists
}
else {

    if($userMapper->fetchByEmail($email) !== NULL) {
        // Error: The email address already exists
    }
    else {

        $userDO = $this->domainObjectFactory->build('user');
        // Set the properties of the $userDO object here with the ones
        // from the registration form

        // Insert the new user into the database            
        $userMapper->save($userDO);

    }

}

私は自分のFormValidationクラスですべてのフォーム検証を行ったので、プロパティを$ userDOオブジェクトに追加すると、すべて100%データベースに挿入する準備ができています(正しい長さ、タイプ、形式、範囲など)。コードはどのようになりますかあなたに見えますか?

私は正しい方向に進んでいると思います。コードを改善するためのヒントをいただければ幸いです。

また、彼らが選択したユーザー名がすでに使用されているかどうかを確認する方法はありますか?それを行うためのより良い方法はありますか?チェックするたびにオブジェクトを作成する代わりに?私が簡単にそれを行っていた古い方法のように:

SELECt COUNT(*) FROM users WHERE username = 'john'

ありがとう。

4

1 に答える 1

3

いくつかの理論関連の「何とか」:

ご存知かもしれませんが、MVCおよびMVCに着想を得たデザインパターンのコアコンセプトはSoCです。これらのパターンを主要な層(プレゼンテーション層とドメインモデル層)に分割することを指示します。

この場合、コントローラーの現在の構造にはアプリケーションロジック(相互作用ドメインロジックエンティティとストレージ抽象化)が含まれているのに対し、コントローラーはモデルレイヤーの状態(場合によっては現在のビュー)の変更のみを担当する必要があるため、重要です。ユーザー入力。

上記のSoCとSRPのボットに違反することになります。

注: WebベースのMVCバリエーションのコンテキストでは、「ユーザー」はWebブラウザーであり、その背後に座っている人ではありません。

代わりに、アプリケーションロジックをサービスにカプセル化する必要があります(@Gordonが述べたように)。完全に実現されたモデル層では、さまざまなサービスが、プレゼンテーション層がモデルと対話するためのパブリックなAPIのようなものになります。

ただし、ゴードンのリンクを解除しますが、サービスをもう少し広くすることをお勧めします。ユーザー登録の場合、私はそれを一部CommunityServiceまたは多分にしMembershipServiceます。モデル層に関する限り、ユーザーアカウント管理のすべての側面を処理する構造。

コードビット:

コントローラで使用する1つの方法は、次のようになります。

public function postUser( $request )
{
    $community = $this->serviceFactory->build('Community');
    $community->addUser( $request->getParameter('username'),
                         $request->getParameter('password'),
                         $request->getParameter('repeated_password'),
                         $request->getParameter('email') );
}

これは有効な方法ですが、問題の可能性にすでに気付いているかもしれません。ユーザー登録に必要なデータが最小限であっても、最終的にサービスに渡すパラメーターの量が多いため、使用が困難になります。

$requestサービスに引き継ぐことは有効な改善ではありませデメテルの法則に違反することになります。代わりに私は次のようなものをお勧めします:

$keys = ['username', 'password', 'repeated_password', 'email'];
$community->addUser( $request->getParameters( $keys ) );

getParameters()メソッドが実装される場所は次のようになります。

public function getParameters( $keys )
{
    $response = [];
    foreach( $keys as $parameter )
    {
        $response[ $parameter ] = $this->getParameter( $parameter );
    }
    return $response;
}

ドメインロジックと検証

ドメインオブジェクトのインスタンスが適切な値を受け取るFormValidationことを確認するために使用しているクラスがあるとおっしゃいました。実際、データ検証はドメインオブジェクトの責任の1つです。コードの重複を避けるために、別の検証クラスを使用することもできますが、それは依存関係であり、インスタンス間で共有するためにドメインオブジェクトのファクトリによって注入されます。User

注:私の個人的な経験では、検証のための重複は、ヌルチェック以外では非常にまれです。複雑な検証ルールセットはそれぞれ、1つの特定のドメインオブジェクトのフィールドを対象としています。それは、私の意見では、検証クラスを非常に冗長にします...複数のプロジェクト間で同じ検証クラスを共有することを期待しない限り。

コードフローは通常、ドメインオブジェクトからのデータを保存する必要がある場合、エラー状態を取得していないかどうかを確認し、エラーがある場合は、リダイレクト後に取得するために、実際にセッションにダンプします。 。

if ( $user->isValid() )
{
    $sqlMapper->store( $user );
}
else
{
    $sessionMapper->storeUser();
}

このユースケースでは、事前に検証された入力が実際に有害になります。

于 2013-01-05T21:07:16.610 に答える