のんラボ

社内でドメイン駆動設計入門の読書会 #10

2020/05/05 2020/05/05 社内でドメイン駆動設計入門の読書会 #10

社内でドメイン駆動設計入門の読書会 #10

こんにちは。Nonです。

今回も会社で読書会をしている話をしようと思います。

内容は控えめに、ディスカッションの内容重視で書いていきたいと思います。

より具体的なコードや内容がみたい!という方は購入しましょう!

前回:会社でドメイン駆動設計入門の読書会 #9

読んでいる本

読んでいる本はこちらのドメイン駆動設計です。

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本


以前の記事でも言っていたように、業務でDDDを利用して開発することが多くなったのですが、DDDに精通している人が少ないという問題がありました。

そこで、その精通している人が読書会をしようかと誘ってくださいまして、是非にと参加させていただきました。

進行方法

読書会の進行方法は

  1. 今回読書の対象にする章を決める。
  2. 10〜20分間その章を読む
    1. 読み終わってしまった人は、もう一周読み直すか、次の章に進んでもらう
  3. その後40分間で、その章に対する疑問や考え方をディスカッションする
  4. 1〜3を毎週定期的に行う

という進行方向となっています。

社内で読書会をするのはこれが初めてなので、進行方法はもっといいのあったら教えて下さい。

今回読んだ内容

  • データの整合性を保つ
  • 整合性とは
  • ユニーキーに制約による防衛
    • ユニークキー制約を重複確認の主体としたときの問題点
    • ユニークキー制約との付き合い方
  • トランザクションによる防衛
    • トランザクションを取り扱うパターン
    • トランザクションスコープを利用したパターン
    • AOPを利用したパターン
    • ユニットおぶワークを利用したパターン
    • トランザクションが引き起こすロックについて
  • まとめ

ディスカッション

といっても今回はDDDというよりもトランザクションについての話題でしたので、メインとなる内容ではなさそうでした。

実装するときトランザクション処理どこではる?

というのはDDDについてよく知っている先輩の方からの質問でした。疑問を投げ掛けられるのは珍しかったのでびっくりしました。

私はアプリケーションサービスに貼るべきだと答えました。
実際、この本にもアプリケーションサービスに貼ってあるところがありましたし、ユースケース全体に貼るのが一番いいのかなと思っています。

copied.class ApplicationService
{
    public function process()
    {
        DB::beginTransaction();
        try {
            // 処理
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            // 処理
        }
    }
}

何故そのようなことを聞いたのか尋ねると。

コントローラーに貼るべき?

先輩はコントローラーに貼るべきなんじゃないのか?と疑問に思っていたようです。

DB::beginTransaction();この箇所はLaravelのファザードで書かれていますが、この時点でLaravelに依存しています。

それをとても嫌ったようです。私も言われてみれば確かにそうだなと思いました。言語は同じなもののクリーンアーキテクチャで依存をできるだけ剥がしているのに、わざわざlaravelのコードを使ってトランザクションを使うせいで依存が発生しています。

コントローラーはLaravel側で受け止めるので、そこで貼るべきなのでは?というのがその方の意見でした。

copied.class Controller
{
    private $useCase;

    public function __construct(ApplicationServiceInterface $useCase)
    {
        $this->useCase = $useCase;
    }

    public function __invoke()
    {
        DB::beginTransaction();
        try {
            $this->useCase->process();
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            // 処理
        }
        // 処理
    }
}

class ApplicationService
{
    public function process()
    {
        // ユースケース
    }
}

こうすれば依存しているのはLaravelの機能であるコントローラーです。
ユースケースに依存は発生していません。

でもユースケース内でトランザクション貼れてない

これもまた問題です。

  • トランザクションをフレームワーク依存にならないようになにか実装を行う
  • この本にかかれているAOPユニットオブワークを利用する

この辺が解決策になりそうです。

あとは最初からフレームワーク依存は諦める選択ですかね。フレームワークのアップデートについていけないコードになってしまう可能性はありますのでおすすめできませんが。

境界づけられたコンテキストとトランザクション

正直「境界づけられたコンテキスト」というのを完全に理解しているわけではないので、なんとも言えませんが、ある時ある方が

トランザクションを貼る目安として境界づけられたコンテキストを見るのは手法としてありじゃない?

といっていました。

集約(まだこの章では出てきていない)の単位でトランザクションは貼るべきというのはデータの整合性的に間違いないので、なにか関係が深そうではあります。

最後に

基本的になトランザクションをDDDでどのように使うべきかというのがこの章のお話だったと思います。

でも、他の本では結構深堀りして書かれているらしいので、重要なところでもあるというのがその雰囲気からわかります。今回は設計手法についての勉強なのでこれ以上深堀りはしませんが、気になる人は調べてみてもいいかもしれません。

次回はアプリケーションを1から組み立てるです。
また記事にしますので、その時はよしなに。

.