AIのための特別なアーキテクチャはいらない 0→1開発で実践した設計原則とガードレール
by
株式会社カミナシ
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
AIのための特別なアーキテクチャはいらない 0→1開発で実践した設計原則とガードレール カミナシ Tech Night #3
Slide 2
Slide 2 text
⾃⼰紹介 ● 名前: Shimmy ● 所属: 株式会社カミナシ ○ ソフトウェアエンジニア ○ カミナシで新規プロダクトを開発中 ○ TanStack Startを使ってFull TypeScriptで開発 ● その他: ○ 最近はポケポケに時間を取られています ○ AIのお陰で個⼈開発にまた⽕がついて、ゴリゴリコードを書いてます (AIが)
Slide 3
Slide 3 text
今⽇話すこと 1. AIの⼒を最⼤限引き出す設計条件 2. その設計を決定論的に守らせる仕組み
Slide 4
Slide 4 text
AIの⼒を最⼤限 引き出す条件
Slide 5
Slide 5 text
条件1: 関⼼の分離
Slide 6
Slide 6 text
Feature-First構成 関⼼事でディレクトリを分ける ● ある機能を修正したいとき、修正したい箇所がまとまって いると扱いやすい ● 1つの関⼼事がすべて1ディレクトリの中にあるのでAIの コンテキストに載せやすい ● 並列にAI開発しても関⼼ごと別に分ければコンフリクトし にくい
Slide 7
Slide 7 text
結合をバランスさせる 結合を「避ける」のではなく「バランスさせる」 ● 「結合の強さ」が⾼いなら「距離」を短く ○ -> Feature内部は⾼凝集 ● 「距離」が⻑いなら「結合」を弱く ○ -> Feature間は疎結合
Slide 8
Slide 8 text
Feature内のディレクトリ構成 ● domain/ ○ 純粋関数のみ ● infrastructure/ ○ DBアクセスなどI/O ● server/(api) ○ オーケストレーション domainとinfrastructureを組み⽴てる ● index.ts ○ Public API 外部に公開するものだけをexport
Slide 9
Slide 9 text
Featureを横断するケー ス
Slide 10
Slide 10 text
パターン1: shared/ 複数featureが使う共通ロジックを切り出す ● 純粋関数をsrc/shared/lib/に置く ● 依存⽅向は常に features/ → shared/
Slide 11
Slide 11 text
パターン2: routes/ 複数featureを組み合わせるページ ● 各featureのPublic APIをimportして統合する ● featureは互いの存在を知らない
Slide 12
Slide 12 text
条件2: 価値の⾼いテスト
Slide 13
Slide 13 text
テストの4つの柱 『単体テストの考え⽅/使い⽅』より ● 退⾏保護: バグを⾒逃さない ● リファクタリング耐性: 内部を変えても壊れない ● 迅速なフィードバック: すぐ結果がわかる ● 保守しやすさ: テスト⾃体がシンプル
Slide 14
Slide 14 text
出⼒値ベーステスト ● Inputを⼊れてOutputを検証する ● 内部実装に依存しない → リファクタリング耐性が⾼い ● モック不要でAIに書かせやすい ● テスト実⾏が速い → AIの試⾏錯誤ループが速く回る
Slide 15
Slide 15 text
domain層の純粋関数 ● Inputを受け取り、純粋関数を組み合わせて計算し、 Outputを返す ● DB参照なし、副作⽤なし、I/Oなし
Slide 16
Slide 16 text
domain層の関数のテスト ● テストはInputを組み⽴て 関数を呼び、Outputを検証するシンプルなもの ● モック不要、DI不要
Slide 17
Slide 17 text
Functional Core + Imperative Shell I/Oとロジックを分離し、副作⽤を端においやる ● Functional Core ○ domain/ : 純粋関数でビジネスロジック ● Imperative Shell ○ infrastructure/: DBアクセスなどI/O操作 ○ server/ : API層。組み⽴ててエンドポイントを提供する
Slide 18
Slide 18 text
設計を決定論的に 守らせる仕組み
Slide 19
Slide 19 text
なぜ「決定論的」的に守る必要があるか ● ルールを教えただけでは守らないことがある ● AIの出⼒速度に⼈間のレビューが追いつかない -> 決定論的に守る「ガードレールが必要」
Slide 20
Slide 20 text
ガードレールの条件 ● 決定的であること ○ AGENT.mdは確率的 → 守られないことがある -> 決定的なシステムが必 要 ● 速くフィードバックできること(Shift Left) ○ AIの試⾏錯誤ループの中でフィードバックしたい
Slide 21
Slide 21 text
静的解析 dependency-cruiser
Slide 22
Slide 22 text
dependency-cruiserで設計を強制する import⽂を静的解析して依存関係のルール違反を検出する ツール ● 設計思想をdependency-cruiserのルールとする ● 新規プロダクトでは12個のルールを定義
Slide 23
Slide 23 text
ルール定義①: 純粋なドメイン層 domain/からinfrastructure/やserver/をimportす るとエラー
Slide 24
Slide 24 text
ルール定義②: Feature間の疎結合 同⼀feature内はOK。別featureを直接importするとエラー
Slide 25
Slide 25 text
ルール定義③: Public API境界 index.tsを通さずにfeature内部を参照するとエラー
Slide 26
Slide 26 text
その他の静的解析ツール ● knip: 未使⽤コードを検出 ○ AI実装で⽣まれる未使⽤exportやファイルを⾃動検出 ● Biome: コード品質を統⼀ ○ any型禁⽌、⾮nullアサーション禁⽌、awaitされていないPromise検出
Slide 27
Slide 27 text
Git hooksで統合する
Slide 28
Slide 28 text
lefthook: コミット前に⾃動で弾く ● pre-commit: Biomeのチェック + dependency-cruiser ● pre-push: 型チェック + knip + テスト
Slide 29
Slide 29 text
開発フロー アウトプットではなく、プロセスを信頼できるものにす る 1. AIにコードを書かせる 2. git commit a. Biome + dependency-cruiser が⾛る b. 設計違反があればエラー c. → AIが⾃動修正 3. git push a. → 型チェック + knip + テスト が⾛る
Slide 30
Slide 30 text
まとめ
Slide 31
Slide 31 text
設計条件を振り返る ● 関⼼の分離 ○ 関⼼事ごとにファイルをまとめる ○ AIのコンテキストに載せやすく、並列開発でもコンフリクトしにくい ● 価値の⾼いテスト ○ domain層を純粋関数で構成し、出⼒値ベースの単体テストを書く ○ モック不要でリファクタリングに強い。質の⾼いテストを書きやすい構 造が整う ● 依存⽅向の決定 ○ 層ごとのルールを明確にする ○ AIが迷わず、静的解析で機械的に強制できる
Slide 32
Slide 32 text
設計を決定論的に守らせる dependency-cruiserで設計思想をガードレールに ● domain層から他の層をimportしたらエラー ● 別featureを直接importしたらエラー ● index.tsを通さずfeature内部を参照したらエラー knip + Biome も活⽤し、lefthookで確定的に実⾏
Slide 33
Slide 33 text
良い設計をちゃんと守る
Slide 34
Slide 34 text
株式会社カミナシ https://kaminashi.jp