Upgrade to Pro — share decks privately, control downloads, hide ads and more …

命名から始めるSpec Driven

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Kurowi Kurowi
November 27, 2025

命名から始めるSpec Driven

Avatar for Kurowi

Kurowi

November 27, 2025
Tweet

Other Decks in Technology

Transcript

  1. ©2025 Kyash Inc. ©2025 Kyash Inc. 命名から始めるSpec Driven AIとの対話で用語を固める設計プロセス Hiroto

    Kuroiwa / 株式会社Kyash Nov. 27th, 2025 - 生成AIの実践知 〜 試行錯誤から組織への定着まで 〜 【Finatext × Kyash】
  2. ©2025 Kyash Inc. Spec Drivenのつらみ 仕様書の肥大化 大量のMarkdownファイル 過剰な設計プロセス 要件, 設計,

    タスクの重複 終わりのないエッジケースの考慮 二重メンテナンス 仕様書をレビュー コードもレビュー 現実とのズレ 既存コードや実際の要件との乖離
  3. ©2025 Kyash Inc. 進め方 アイデアを書き出す CONCEPT.md 煮詰まっていなくていいのでまずは設計方針を立てる 定義を生成し、曖昧さを炙り出す アイデアから定義となるコードを生成してもらう テーブル定義、構造体、オブジェクトなどやりやすい形式。

    「この型でいい?」「この制約で足りる?」を考える 重要なのは各要素が何を表すかをコメントまで書くこと 違和感を見つける 一貫性のない命名, 曖昧な表現, 増えすぎたENUMなど AIとの対話で違和感を解消 「この単語は適切?」「別の事象と混同しない?」「増えすぎているので分けるべきでは?」 アイデアがなくても「〜すべきでは?」と投げかける 設計の軸は自分で持ち、AIの引き出しを活用する 1 2 3 4 何度も往復する
  4. ©2025 Kyash Inc. 進め方 設計ドキュメントを更新 CONCEPT.md → DESIGN.md ブラッシュアップしたアイデアとコードに落とし込んだ定義を踏まえて作成 曖昧だったコンセプトを洗練された設計に昇華する

    ドメインモデルを作成 設計ドキュメントに基づいたドメインモデルの実装を依頼する 「貧血症にならないようモデルの振る舞いを意識して」と明示的に指示 5 6
  5. ©2025 Kyash Inc. 違和感の見つけ方(一例) 一貫性のある用語を使用しているか? 文脈が揃っていない用語はロジックも歪む 例: billing ↔ refund

    … 一見対称に見えるが文脈が違う 増えすぎていないか? 登場人物が増えるときはまず疑ってみる カラムが増える … 別のエンティティの責務ではないか? 区分値が増える … 別の概念を混ぜていないか? テーブルが増える … ドメイン境界を誤っていないか? ひとことで説明できるか? 説明が長くなったらブラッシュアップの余地がないか考える 定義にコメントを付けておくとコメントの肥大化で気づきやすい
  6. ©2025 Kyash Inc. 例1: 同じ文脈の言葉を使っているか? 初期設計の用語 ユーザーが支払うべき額 … billing_amount ユーザーに支払うべき額

    … refund_amount ユーザーが支払った額 … paid_amount ユーザーに返金した額 … refunded_amount 初期設計の違和感 違和感 billing ↔ refund: 対称的でない refund ↔ refunded: 違いが分かりづらい refund: お金が動いていないことが表現できていない paid: ユーザー, 会社, 誰が払った?
  7. ©2025 Kyash Inc. 例1: 同じ文脈の言葉を使っているか? AIとの対話 billing ↔ refund が対称的でなくて気持ち悪い。何

    か良い単語はない? いいですね。テーブル定義に落とし込んでください 会計用語で debit / credit があります。 debit は借方、credit は貸方で完全に対称です debited_amount: 請求権の発生額 credited_amount: 返金義務の発生額 collected_amount: 実際に回収した額 refunded_amount: 実際に返金した額
  8. ©2025 Kyash Inc. 例1: 同じ文脈の言葉を使っているか? 債権債務の発生 debited_amount 借方:請求権 credited_amount 貸方:返金義務

    ↔ ↔ 実際のお金の動き collected_amount 回収した額 refunded_amount 返金した額 ✓ 用語が対称的 → ロジックも対称的に ✓ 「発生」と「実際の動き」が明確に分離 結果 2層構造への整理
  9. ©2025 Kyash Inc. 例2: 増えすぎていないか 問題の発生 初期設計の決済集約がもつステータス REQUIRES_REFUND REQUIRES_COLLECTION COMPLETED

    新たな要件 「要対応の取引」を抽出するクエリが複雑化 Before : WHERE status <> 'COMPLETED' After : WHERE status NOT IN ('COMPLETED', 'REFUNDED', ...) COMPLETEDのうち「返金取引」を区別したい statusにREFUNDEDを追加します
  10. ©2025 Kyash Inc. 例2: 増えすぎていないか AIとの対話 COMPLETEDでない取引を抽出するケースが複 雑化しています。Statusに追加すべきでない可能 性はありませんか? おっしゃるとおり運用状態と最終結果は別の関心事で

    す (言語化) final_statusの追加を提案します _statusが増えていく未来が見えてイケていないで す。適切な一単語はありませんか? outcome, conclusion, verdict... outcomeにしましょう
  11. ©2025 Kyash Inc. 例2: 増えすぎていないか 結果 statusとoutcomeの分離 status … 現在の状態

    collection_due ↔ ↔ refund_due balanced requires_action outcome … 最終的にどうなったか collected / refunded reversed / voided written_off / escheated → 要対応 … status <> ‘balanced’ だけでシンプル → statusがbalancedになったときに確定 ✓ 関心事が分離されシンプルに
  12. ©2025 Kyash Inc. いろいろつきつめた結果 全usecaseがこれだけ func(uc *HandleEventUseCase) Execute( ctx context.Context,

    event PaymentEvent, ) error { nexus := repository.FindByOrigin(...) nexus.Apply(event) repository.Save(nexus) return nil } 10種類のイベントすべてがこのパターンに収束 言葉を詰めた結果、スペック駆動ツールが不要なほどシンプルに
  13. ©2025 Kyash Inc. なぜこうなったか 用語が対称 ↓ ロジックも対称 ↓ 複雑なロジックが減る 概念が明確

    ↓ モデルが「自分の状態を どう更新すべきか」を知っている 責務が整理 ↓ usecaseは 調整役に徹することができた
  14. ©2025 Kyash Inc. 既存システムへの適用 一見具体的な指示で始めても 記事にいいね機能を追加してください。 - likesテーブルを作成 (user_id, article_id,

    created_at) - POST /articles/:id/likes でいいね - DELETE /articles/:id/likes で取消 - いいね数はarticles.likes_countで管理
  15. ©2025 Kyash Inc. 既存システムへの適用 指示は具体的でも、用語と責務が曖昧なまま進むと継ぎ足しの設計に 追加要件でテーブルが増殖 自分:コメントにもいいねしたい AI:comment_likesテーブルを作成します (article_likesと別になった…) →

    抽象化(Likeable)を検討しなかった 振る舞いの置き場所がバラバラ 自分:いいねのロジックを共通化して AI:LikeService.execute(user, article)を作成します (さっきはUser.like(article)だったのに…) → 「誰がいいねする責務を持つか」を決めなかった 用語の衝突 自分:ブックマーク機能も追加して AI:Favoriteモデルを作成します (LikeとFavorite、何が違うの…?) → 「Likeとは何か」を定義しなかった
  16. ©2025 Kyash Inc. 命名から始めるアプローチ Step 1:用語を決める いいねする → like いいね取り消し

    → unlike (cancel? remove?) いいね済み → liked Step 2:ドメイン層の責務を考える Like(Entity) user_id, target_type, target_id Likeable(Interface) いいねされる対象が実装 Article, Comment などさまざまなものが対象になる LikeService 重複いいね防止 いいね数の集計ロジック Step 3:ここでスペック駆動 「LikeServiceを実装して。 Likeエンティティを作成し、 対象のlikesCountを インクリメントする」 用語と責務が決まっているので AIの実装が一貫する
  17. ©2025 Kyash Inc. DDDっぽいけどDDDではない やったことを振り返ると ・使う用語を統一した ・曖昧な概念を明確にした(statusとoutcomeの分離) ・モデルに振る舞いを持たせた DDDで言う「ユビキタス言語」と 「ドメインモデル」に近い

    ただし、本来の DDDとは違う DDDは 「ドメインエキスパートと開発者の協働」が核心 AIはドメインエキスパートではない AIは広く浅い知識を持っているだけ ビジネス上の正解はAIにはわからない それを決めるのは人間