4

見出しが示すように、3 つの構造のモデル (ドメイン オブジェクト、データ マッパー、およびサービス) を実装する際にいくつかの小さな問題が発生しています。

過去に誰かが私のサイトに登録していたとき、私は単純にそうしていました

$user->register($firstName, $lastName, $emailAddress, $username...);

そのメソッドは次のような手順で実行されます

1. Check if the form sent was valid.
2. Check if all the required fields were filled.
3. Check the if the lengths of strings were valid and the range of integers etc.
4. Check if the input is in the correct format (regex).
5. Check if the username is already taken and if the email address already exists
   in the database
6. etc. etc.

それはすべて正常に機能しますが、コードをより再利用可能でテスト可能にしたいので、そのようにすることから逃れようとしています。

さて、この3つの構造モデルでは、ドメインオブジェクトとデータマッパーはサービスを介して通信し、それらを互いに分離しておく必要があるため、ここにユーザーサービスの私の考えがあります

class UserService {

    public function register($firstName, $lastName, $email...) {

        $userDO= $this->domainObjectFactory->build('User');
        $mapper  = $this->dataMapperFactory->build('User');

        // Is this where I start doing my validation like in the steps above???
        // And if this is where I start doing my checks, when I get to the part
        // where I have to check if the username they want is already taken how
        // how do I do that check?

    }    

}

そして、実際にそれを実行するには、コントローラーから次のように実行します

$userService = $this->serviceFactory->get('user');
$result = $userService->register($_POST['firstName']....);

ロジック (if と else の) は、私のクラスのregister()メソッドに入れる必要がありますよね? UserServiceユーザー名が既に存在するかどうかなど、データベースがいくつかのチェックを行う必要がある段階に達したときにドメインオブジェクトに入ると、どうすればデータベースにアクセスできますか? ドメインオブジェクトはデータソースについて何も知らないはずなので、本当にわかりません。

ユーザー名や電子メール アドレスが既に存在するかどうかの確認や、実行する必要があるその他の小さなクエリの負荷など、小さなクエリのためにデータベースにアクセスする方法が必要です。

小さなクエリの負荷を実行する必要があるエンティティ/ドメイン オブジェクトがたくさんあります。過去に、モデルは任意のメソッド内からデータベースにアクセスでき、それらのクエリを実行できましたが、この 3 構造モデルでは許可されていないようです。方法がなければならないので、それを行う正しい方法は何かを知りたくてたまらない.

モデルが3つの構造に分割されたレイヤーであることがわかるまで、私はそれを飛ばしていました。

特に実生活での良い例など、正しい方向への助けやプッシュは大歓迎です。インターネットには、私の特定の問題に対するものが欠けているようです。

ありがとう。

4

2 に答える 2

1

私はあなたが今いるのと同じことを経験しています(この正確な問題-ユーザー登録/承認については十分面白いです)。

私が持っているアドバイスの 1 つは、モデルを 3 つのレイヤー (この場合は 3 つのクラス) だけに制限するべきではないということです。モデルは、SRP (単一責任の原則) の整合性を維持しながらジョブを完了するために、必要な数のクラスにする必要があります。

たとえば、UserTableGateway クラスを使用して UserDataMapper を補完し、UserCollection クラスを使用して潜在的なページネーション機能またはユーザーの一般的なリストを許可することもできます。これらはすべて、モデルと UserService レイヤーの一部になる可能性があります。

登録プロセスに固有のロジックについての質問に答えるには、はい、最も適切な場所は UserService クラスの登録メソッドです。

そうは言っても、ここでドメイン構造について考えてみてください。UserService は登録に最も適した場所ですか (さらに、ログイン、パスワードの回復、パスワードの変更など)?

おそらく、これらはアカウントに関連するまったく異なるモデルの一部である可能性があります。サービス クラスは次のようになります。

class Account 
{
    // Think of this as AccountService, it will have a number of collaborators,
    // including an Authenticator class for loggin in, a Session class for managing the session
    // and of course various persistence classes for storing the user, session and credentials


    public function register(UserInterface $user) {}
    public function login($email, $password) {}
    public function logout(UserInterface $user, $session_id) {}
    public function changePassword($user_id, $old_password, $new_password) {}
    public function recoverPassword($user_id, $email) {}
}

UserService が担当できる可能性があることが他にも多数あることを考えると、ユーザーのアカウントに関連するすべてを独自のサービス クラスに保持することは理にかなっています。

概念的には、アカウントはとにかくユーザーとは異なります。概念的に異なる場合は、独自のクラスに値します。

アカウント サービス クラスに必要な依存関係を取得することに関しては、複雑なシステム設計を理解しているこの段階では、私には理解できません。

于 2013-11-04T08:42:27.270 に答える
0

これは興味深い質問です。ユーザー データ マッパーには、いくつかの基準 (ユーザー名など) に基づいてユーザーを検索およびロードするためのメソッドがあると思います。したがって、この場合、提供されたユーザー名を持つユーザーを見つけようとすることで、UserService::register 内でチェックを行います (存在する場合)。


if ($mapper->findUserByUsername($username)) { 
    // username is already taken, handle this special case
}

ところで、あなたがこれを読んだかどうかはわかりませんが、非常に優れたガイドは Martin の Fowler の本である - Patterns of Enterprise Application Architectureです。多くの質問に対する適切な回答が見つかります。

于 2013-01-06T00:20:30.323 に答える