web-dev-qa-db-ja.com

フォーラムWebアプリケーションでユーザーとユーザープロファイルを表すために必要なドメインオブジェクト

Slim 3を使用してフォーラムWebアプリケーションのバックエンドを実装するための独自のフレームワークを記述できるように、MVCデザインパターンをしっかりと理解しようとしています。特に、 this を読んだ後=、そして thisthis に問いかける私は今、モデルがデータマッパー、サービス、ドメインで構成されるレイヤーであるべき方法を理解していると思いますオブジェクト。ただし、ドメインオブジェクトについてさらに質問があります。

この質問は私が尋ねた に与えられた回答から非常によく似た構造を持つ現時点で。ユーザーをフォーラムアプリケーションに登録するための基本的なモデルレイヤー構造があります。しかし、私の「ドメインオブジェクト」は現時点では実際には何も実行していないようです。ゲッターとセッターしかなく、おそらくそれなしで実行できます。

ユーザードメインオブジェクト:

class User
{
    private $id;
    private $email;
    private $username;
    private $password;

    public function __construct(Email $email, Username $username, Password $password)
    {
        $this->email = $email;
        $this->username = $username;
        $this->password = $password;
    }

    public function getId()
    {
        return $this->id;
    }

    public function setId(int $id)
    {
        $this->id = $id;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail(Email $email)
    {
        $this->email = $email;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function setUsername(Username $username)
    {
        $this->username = $username;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function setPassword(Password $password)
    {
        $this->password = $password;
    }
}

このユーザードメインオブジェクトは、ユーザーの登録時に入力される「ユーザー」SQLテーブルのオブジェクトを直接反映しています。実際、この作成されたユーザードメインオブジェクトがデータマッパーに渡され、渡されたユーザーオブジェクトのフィールドが抽出されてデータベースに挿入されます。

ユーザーオブジェクトを「ユーザー」テーブルに挿入する:

 private function insertUser(User $user) 
 {
      $sql = 'INSERT INTO users (email, username, password) 
              VALUES (:email, :username, :password)';

      $statement = $this->connection->prepare($sql);
      $statement->execute([':email' => $user->getEmail(),
                           ':username' => $user->getUsername(),
                            ':password' => $user->getPassword()]);

      $user->setId($this->connection->lastInsertId());

      return $user;
 }

このユーザードメインオブジェクトを作成する代わりに、ユーザーがフォームに入力した文字列を(検証とサニテーションの後に)直接渡すだけではないのでしょうか。現時点では必要ないようです。

ここで、ドメインオブジェクトとは何かについて混乱しています。ビジネスロジックを含める必要があることは理解していますが、フォーラムアプリケーションに必要なビジネスロジックを特定するのは困難です。たとえば、各ユーザーに、一般に公開されている独自のプロファイルページを用意して、問題のユーザーがログインしている場合にのみ編集および更新できるようにしたいと考えています。

元のユーザーテーブルとユーザードメインオブジェクトにリンクする新しいプロファイルテーブルと共に「プロファイル」ドメインオブジェクトを作成する必要がありますか?または、既存のユーザーテーブルとユーザードメインオブジェクトを拡張して、ユーザーがプロファイルを表示および更新できるプロパティとメソッドを持たせることはできますか?

これは設計の問題であり、主観的である可能性があることを理解していますが、ドメインオブジェクトに何を含める必要があるか(特に前のプロファイルの例の場合)、およびテーブルと結合する必要があるかどうかについてのアドバイスは役に立ちます。

私が目にする多くのチュートリアル thisなど には、データマッパーメソッドが含まれている単一のモデルオブジェクトがあり、これは正しくないと思われます。多くのチュートリアルでは、ORMを使用するフレームワークも使用しています。これは、すべてを最初から作成するために使用を避けようとしているものですが、私はSlim 3/4 PHPを使用しています。

3
SneakyShrike

MVCデザインパターンをしっかりと理解しようとしています

Model View Controller は、あり得ないほど単純なパターンです。モデル、ビュー、コントロールに焦点を当てたものがある限り、MVCを使用しています。パターンは非常に古く、それらがどのように通信するか、またはそれらをどのように分離する必要があるかについて誰も同意しません。 3つの責任を超えるものは、誰かの考えにすぎません。残りは標準化されていません。自分のコンテンツがどのように通信して分離されるかを理解してほしい場合は、「MVCを使用する」以上のことを言う必要があります。

ただし、ユーザーの「ドメインオブジェクト」は現時点では実際には何も実行していないようです。ゲッターとセッターしかなく、おそらくそれなしで実行できます。

これは真のオブジェクト指向オブジェクトではありません。これは、データ構造の周りのデバッグコード(ゲッターとセッター)の山です。真のカプセル化はありません。動作ロジックはありません。それは役に立たないということですか?いいえ。タイプセーフな方法で境界を越えてデータを移動するために必要なものです(タイプセーフが必要ない場合は、コレクションを使用してください)。しかし、それは真の目的ではありません。しかしそれはパターンです。 bean と呼ばれます。これらは、永続フレームワークの記述を容易にするために発明されました。彼らはあなたに本当のカプセル化や良いオブジェクトを作る方法を教えていません。

このユーザードメインオブジェクトは、「ユーザー」SQLテーブルのオブジェクトを直接反映しています...

それがまさにdomainオブジェクトではない理由です。 domainオブジェクトはリポジトリのスレーブではありません。これは、ドメインの独立した抽象化です。これはドメインからのアイデアであり、永続化のようなシステムの機械的な必要性ではありません。

IDがある場合、それはエンティティです。エンティティは永続化しない状態を持つことができます。

たとえを許せば、永続化されたエンティティは凍結乾燥されます。水を加えると、彼らは新しい特性と特徴で生き返ります。両方の形式で同じであることを主張しないでください。一方から他方へのカスタム変換があると非常に便利です。 ORMを使用する場合、それを実現するのは非常に困難です。

これは、エンティティが永続化表現の外側に生命を持っていると言っているだけです。

このユーザードメインオブジェクトを作成する代わりに、ユーザーがフォームに入力した文字列を(検証とサニテーションの後に)直接渡すだけではないのでしょうか。現時点では必要ないようです。

その通りです。オブジェクトには存在する理由があるはずです。真のオブジェクトは、変化して一緒に動く機能のバッグです。必要なユーザーフィールドをinsertUser()に渡して実行できます。 insertUser()をユーザークラスに移動して、オブジェクトの状態からフィールドを取得することもできます。

動作のないデータ構造(そのBean)に固執する唯一の理由は、データが異なるシステム間の境界を越える必要がある場合です。 insertUser()などの動作を適切なオブジェクトに移動できないようにする境界。

オブジェクト指向プログラミングで行うことの1つは、データの移動を停止し、代わりにそのデータと一緒に動作(関数/メソッド)を移動することです。問題は、あなたがいつもそれをすることができないということです。時々、データを移動する必要があります。それはあなたがデータ構造をめぐるときです。

3
candied_orange