設計における静と動
設計には静的な側面と動的な側面があります。
静的な側面は、システムのある瞬間の状態を表現するもので、データ構造としてモデリングされます。
一方、動的な側面は、システムの状態がある状態から別な状態へと遷移する事象を表現するもので、ある種のトランザクション(DBのトランザクションとは限らない)とも言えるかと思います。
不揮発性のシステムを構築する場合はなんらかの方法で状態を再現できる必要がありますが、戦略として、前者の静的な状態を切り取って保持するのがステートソーシング、後者の動的な状態遷移を記録していくのがイベントソーシング、となります。
設計は、不変条件を守ることを主眼に行われます。即ち、状態内のあるデータとあるデータとの組み合わせが不正にならないことを保証するためのルール付けです。
静的側面からは、不正な状態の生成を拒否するなんらかの実装によってこれを実現しようとします。一方、動的な側面からは、状態の遷移を静的モデルに対して要求し、成功した場合と失敗した場合のそれぞれのシステムとしての挙動を制御します。また、処理の境界付けを行い、どこまでが一つのアトミックな処理であるのかを定義します。
データ構造に対する要求は機能/非機能を含め様々ケースがありうるため、その設計はこれがベスト、というものは無いと思います。重要なのは、何が目的でそのデータ構造が必要とされているのかを明確にすることです。それにより取りうる選択肢は変わるでしょうし、様々な要件の中から何を優先し何を切り捨てるか、という判断も変わります。
例えば、オンメモリで高速な演算が求められるケースであれば、適切なアルゴリズムが適用できるデータ構造の選択が重要でしょう。また、速度よりも、複雑なロジックを安全に管理したり、その拡張性が求められるようなケースであれば、また違った抽象化や効率的な保守が可能な構造を選択すべきなはずです。
ビジネス上の要求を度外視して、フレームワークや永続化層の都合に合わせたパターンにデータを押し込めるような設計は、後々様々な問題を引き起こすでしょう。
静と動の観点からシステムを見ると、参照と更新の分離のような戦略も比較的理解しやすいのではないでしょうか。
データの参照とは、ある瞬間のシステムの状態を切り取ってきて目的に合わせて整形して閲覧する行為です。閲覧するデータが最新であるとは限りません。なぜなら、ある瞬間のデータを切り取った時点で、そのあとに適用された変更は観測不能になっているからです。返却されたデータは閲覧している間に他のプロセスが変更しているかもしれません。
それに対して、データの更新とは、システムの現在の状態に対して、変更の要求の適用可否を判断し、適用可能であれば現在の状態から別な状態へと遷移させる行為です。注意すべき点は、変更を適用するための状態と適用後の状態との間に、他の変更が割り込むと、状態が破壊されうるということです。
何が許容できて、何が許容できないかは、コンテキスト次第で変わります。繰り返しになりますが、システムの目的を明確にし、適切な取捨の判断が重要です。