## 2025-09-07 - コミットメッセージに何を載せるべきか - Whyまで書くのか、冗長になりすぎないか - 何から作業進めるか、悩む - とりあえず、ユースケースを実装できるようにやっていくしかないか・・・ - プラハチャレンジって名前だし、 - 課題 = challenge - 自分の課題の実装状況 = task とかにしたほうがよかったかなあ - ドメインサービスをどこに置くか - domain/[entity]/services に置くか、 - domain/servicesに置くか - → 複数集約をまたいだドメインルールの実装なので、entityのサブディレクトリに配置すると循環依存になってしまう。 - → domainのサブディレクトリに置こう - 集約の範囲について - student集約にtaskを持たせると何がよいか? - student生成時に80個のtaskを生成する、といった処理に整合性をもたせられる - 課題のstatusを変更できるのは本人だけ、といったルールを、studentドメインモデルから実行できるので、仕様とコードの対応付けがやりやすい - taskとstudentは、ライフサイクルが一致している - studentが退会するとtaskの役割も終わる - studentの更新のたびに、紐づく全てのtaskを更新し直さないといけない。 - Taskが80個と多いため、Studentをリポジトリから取得するたびに80個のTaskもロードすると、パフォーマンスが懸念されます。これは、インフラ層(リポジトリの実装)で遅延読み込み([[Lazy Loading]]) を採用することで解決可能です。 - team集約にstudentを持たせると何が良いか? - teamの増減の処理と、studentの所属チームの処理に整合性をもたせられる - ただし、teamに存在していないstudentをどう扱うのか?が難しい? - studentがどのチームにも属していないといけなくなるのでは? - 集約を用いない場合、何が良いか? - 自由度が高い - 各エンティティの操作に制約がない - 逆に、ドメインサービスが増え、ドメインモデル貧血症になる - ドメインサービスが増えると、1トランザクションでどのように操作するかが実装者に依存した形になる? - [集約の実装とlazy loading](https://emonkak.hatenablog.com/entry/2017/10/01/113453) - [DDDになぜ失敗するのか DDDのトリレンマ](https://zenn.dev/dorarep/articles/6e8dbdd517487c) - このように以下の3つの要素のうち2つしか選ぶことができないというのが、DDDのトリレンマです。 - 完全性:ドメインモデル内でドメインロジックが完結している - 純粋性:ドメインモデルはドメインモデルかプリミティブ型にしか依存しない - 性能:リソース使用量が大きすぎない - 3つの要素のうち2つしか選ぶことができない、つまりDDDで開発する上でこのトリレンマから何を選び何を捨てるのか常に判断を迫られることになります。 - これに対し元記事では、性能を捨てるのは現実的でなく、完全性より純粋性を優先させる方が良いと結論づけられています。 - そこで[Domain model purity and lazy loading](https://enterprisecraftsmanship.com/posts/domain-model-purity-lazy-loading)では、遅延読み込みを用いることでAggregateのパフォーマンスを損なうことなくより大きな集約を操作できるとしています。要するにデータが必要になったタイミングでDBリクエストを実行することで、性能を保ちつつ集約を大きくすることができます。 - chouプログラミングでも遅延読み込みの話が出ているっぽい ## 2025-09-10 - 自分の思考フローはcommit → issue, pull requestの番号で紐づけて説明できるようにしたい - commitは1行で~~ということをした。を説明 - 細かい前提条件とか、実装する時に考えていたバックヤードとか、懸念点とか、そういった部分はissueに切り出しておく? - あまりに関係ない情報だったりするので、それはpull request単位で切れば良さそう - そのpull requestの中から、変わらない概念、ドメイン知識などがあれば、その部分は別途リンクで意味合いを明示する形がよい? - pull requestで一区切りの実装は終わったけど、それに付随してあたらしいTODOが生まれた時ってどうするんだろう - studentを作るドメインサービスを用意しました。ただし、これを利用するインフラ層の処理はトランザクションを考慮して、taskの保存に失敗したときは studentもロールバックできるようにしてください・・・みたいな - [PullRequestの説明をなんども書き直す](https://scrapbox.io/nota-private-sample/PullRequest%E3%81%AE%E8%AA%AC%E6%98%8E%E3%82%92%E3%81%AA%E3%82%93%E3%81%A9%E3%82%82%E6%9B%B8%E3%81%8D%E7%9B%B4%E3%81%99) - ブランチの切り方、mainとfeatureブランチで運用したほうがやりやすいかも - 全ての実装をプルリクの単位でcommitしたいわけじゃなければ、devが取り残される - github codespacesのターミナル、もっといい感じにしておきたい - curlしてでてきたjsonの配列とか、パースして出力してほしい - query-serviceとuse-caseに分けてapplicationに置くのはCQRSの考え方らしい - queryは読み取り, use-caseは書き込み・状態変更 - queryはペイロード/DTOを返すことに特化する - ドメインエンティティを介さず、データベースから直接プレゼンテーション層が必要とする形式でデータを取得するため、パフォーマンス上有利になる場合があります。 - lintはpre-commitに設定しておきたいなぁ コードベースが大きくなるならなおさら - 管理者って概念、ドメインモデルでどう扱うんだろう - DBの都合でuserTypeみたいなのを付与すると、studentの永続化のときに、ドメインモデルに入っていないstudent.userTypeみたいなのが要求されて詰む - インフラ層の実装で、task.length=0みたいなときってどうする?明らかにエラーな時のハンドリングをインフラ層においておくべきか - drizzle/get-database.tsの型も理解できるようにしておくと良さそう - `PostgresJsDatabase` - 下の感じでthis.databaseからtransactionとかinsertとかselectとか引っぱり出せるっぽい ```ts import type { Database } from "../../libs/drizzle/get-database"; export class PostgresqlStudentRepository implements IStudentRepository { constructor(private readonly database: Database) {} ``` - commitログ、fixとaddの違いが分かりにくいな - fixでもありaddでもある、みたいな場合がたまにある - 機能修正にあたり、このメソッドを追加した、みたいな・・・ - 本来ならaddの時点で考慮しとけ、みたいなのはfixになるのかなぁ - Conventional Commitsに沿ったほうがよさそう - commitログ、漢字が多いと何やってるかぱっと分からんくなる - あと、粒度が細かすぎると逆に何やっているか分からない - command実行したよ~ぐらいの、機能実行単位のコミットがいいんだろうなあ