状態ごとにモデルを分割する

2023-03-11#dart

ドメインモデリングにおいて状態をどのように扱うか考えることが増えてきたので、以下のような状態を持つブログ記事を例にとって、どのような方法がありうるか考えてみる。

以下、コンストラクタは省略する。

フラグ

class Article {
  final Id id;
  final Id? userId;
  final Title title;
  final DateTime? publishedAt;
 
  final bool isDraft;
  final bool isPublished;
  final bool isArchived;
 
 
  void publish({required DateTime publishedAt}) {
    if (isDraft) {
      isDraft = false;
      isPublished = true;
      this.publishedAt = publishedAt;
    }
  }
 
  void archive() {
    if (isPublished) {
      isPublished = false;
      isArchived = true;
      userId = null;
    }
  }
}

enum

class Article {
  final ArticleStatus status;
  final Id id;
  final Id? userId;
  final Title title;
  final DateTime? publishedAt;
}
 
enum ArticleStatus {
  draft,
  published,
  archived;
}

状態ごとにクラスを分割

class DraftArticle {
  final Id id;
  final Id userId;
  final Title title;
 
  PublishedArticle publish({required DateTime publishedAt}) {
    return PublishedArticle(
      id: this.id,
      userId: this.userId,
      title: this.title,
      publishedAt: publishedAt,
    );
  }
}
class PublishedArticle {
  final Id id;
  final Id userId;
  final Title title;
  final DateTime publishedAt;
 
  ArchivedArticle archive() {
    return ArchivedArticle(
      id: this.id,
      title: this.title,
      publishedAt: this.publishedAt,
    );
  }
}
class ArchivedArticle {
  final Id id;
  final Title title;
  final DateTime publishedAt;
}