「連想配列」と「ドメインモデル」の違い

こんにちは。エキサイト株式会社の三浦です。

エキサイトは昔からPHPがよく使われてきましたが、特に古いコードだとその中で連想配列が頻繁に利用されています。 一方で最近ではエキサイト内でもドメイン駆動設計が考慮されることが増え、連想配列ではなくドメインモデルが利用されることが増えてきました。

ここでは、「連想配列」と「ドメインモデル」の違いはなんなのか、簡単に説明していきます。

連想配列とドメインモデルの共通点

連想配列もドメインモデルも、「1~複数のデータを格納する」という役割は共通です。 例えば「記事」のデータだと、タイトル・本文・公開日など複数のデータの複合で成り立っています。 こうしたデータについて、それぞれ別々に変数に入れるのではなく、連想配列やドメインモデルといった形でまとめて保存することで、取り扱いを容易にすることができます。

連想配列

$article = [
    'title' => '記事タイトル',
    'story' => '記事本文',
    'publishDate' => '2021-01-01 00:00:00'
];

ドメインモデル

class Article {
    private $title;
    private $story;
    private $publishDate;
    
    public function __construct($title, $story, $publishDate) {
        $this->title = $title;
        $this->story = $story;
        $this->publishDate = $publishDate;
    }

    public function getTitle() {
        return $this->title;
    }

    public function getStory() {
        return $this->story;
    }

    public function getPublishDate() {
        return $this->publishDate;
    }
}

$article = new Article('記事タイトル', '記事本文', '2021-01-01 00:00:00');

連想配列とドメインモデルの違い

では次に、連想配列とドメインモデルの違いを、それぞれの利点から見ていきます。

連想配列の利点

連想配列の利点は、何と言ってもその使いやすさかと思います。 上記の例を見て分かる通り、同じデータを入れるのでも、ドメインモデルに比べて連想配列を使うほうが圧倒的に簡単にコードを書くことができます。

ドメインモデルの利点

入りうるデータが確定している

連想配列は簡単にコードを書くことはできますが、その反面好きな時に好きなようにデータを入れることができるため、どんなデータがその連想配列に入っているかが分かりにくくなってしまっています。 連想配列を使っている場合、今どんなデータが入っているかを確認するため、要所要所で var_dump を使うという方も多いのではないでしょうか。 その点ドメインモデルは、最初にクラスを作る段階で入れるデータを決めているため、どの時点であっても入りうるデータは確定しています。

IDEの補完が効く

ドメインモデルのようにプロパティやメソッドを通してデータを取得するようにすることで、IDEが補完を効かせてくれます。 連想配列だと文字列でキーを指定することになり、どうしてもtypoや勘違いによるミスが起こりえますが、ドメインモデルで書くことによってそのリスクを大幅に減らすことができます。

ドメインルールを入れることができる

例えば「タイトルは100文字以内でなくてはならない」といったルールがあったとしましょう。 記事データがいろいろなところで使われる場合は、連想配列を使っているといろいろな場所で下記の条件を書く必要が出てくるかもしれません。

// これを、コードのいろいろな場所で書く必要があるかも
if (100 < mb_strlen($article['title'])) {
    // エラー処理を書く
}

その場合、今後「タイトルは120文字以内でなくてはならない」というルールに変わった際は、この条件が書かれているすべての部分を探し出し、修正する必要があります。 エンジニアであれば一度は体験したという方も少なくないと思いますが、これは非常に大変な作業です。

一方ドメインモデルを使うと、モデルそのものにルールを書くことができます。


class Article {
    private $title;
    private $story;
    private $publishDate;
    
    public function __construct($title, $story, $publishDate) {

        // Articleモデルを作成するときにのみチェックすれば良い
        if (100 < mb_strlen($title)) {
            // エラー処理を書く
        }

        $this->title = $title;
        $this->story = $story;
        $this->publishDate = $publishDate;
    }

    public function getTitle() {
        return $this->title;
    }

    public function getStory() {
        return $this->story;
    }

    public function getPublishDate() {
        return $this->publishDate;
    }
}

このように、ドメインモデル生成時に必ずチェックするようにすれば、ルールを書く部分が1箇所だけで済み、仮にルールが変更になっても修正が非常に容易です。

最後に

以上のことから、多少最初書くのが面倒であったとしても、ドメインモデルを使うようにしたほうが利点が大きいのではないでしょうか。 またこれは、ドメイン駆動設計の概念でもあります。 今後新しく連想配列を使う機会があったら、ぜひドメインモデルで書いてみることをおすすめします。