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

AI駆動開発の現在地 〜職種の壁を越えて、我々は何をすべきか〜 / ai-driven-dev...

Avatar for 中村翼 中村翼
July 25, 2025
560

AI駆動開発の現在地 〜職種の壁を越えて、我々は何をすべきか〜 / ai-driven-development-3-layer

Avatar for 中村翼

中村翼

July 25, 2025
Tweet

Transcript

  1. ログラスのAIツールの歩み 6 2月 エンジニア全員に Cursor、一部に Devinを配布。 Cursor道場開始 4月 エンジニアだけではな くPdM・デザイナーま

    で波及 時間軸 6月 Claude Codeが全 エンジニア使える状 態 Claude CodeでPdM が機能リリース。デザ イナーがプロトタイプを 作る 6~7月
  2. © 2025 Loglass Inc. • レビュープロセスの破綻 ‐ 3⼈チームで1⼈10PR/⽇を上げた場合、30PR/⽇のレビューが必要とな る •

    タスク供給の限界 ‐ 毎⽇30PR分のタスクを継続的に供給する必要がある • AI⽣成コードの品質 ‐ コード品質の⼀貫性、保守性、拡張性が担保されているか不明確 AI駆動開発の課題
  3. © 2025 Loglass Inc. AI駆動開発の課題 // AIが⽣成しがちな問題のあるコード例 class OrderService {

    // 問題1: 在庫チェックなし fun createOrder(customerId: String, items: List<OrderItem>): Order { val order = Order( id = generateOrderId(), customerId = customerId, items = items, total = calculateTotal(items), status = OrderStatus.PENDING ) // 在庫減算を後で⾏う(在庫切れの可能性無視) items.forEach { item -> reduceStock(item.productId, item.quantity) } return saveOrder(order) } // 問題2: 割引計算の論理的制約無視 fun applyDiscount(order: Order, discountRate: Int): Order { // 負の割引率や100%超の割引を許可 val discountAmount = order.total * discountRate / 100 // 結果が負になる可能性を考慮せず return order.copy( total = order.total - discountAmount, appliedDiscount = discountAmount ) } }
  4. © 2025 Loglass Inc. なぜこのようなことが起きるのか? AI駆動開発の課題 1. 表⾯的な要件のみに注⽬ AIが⾒ているもの ‧注⽂を作成する

    ‧商品価格 × 数量で計算する ‧割引を適⽤する AIが⾒落としているもの ‧在庫の整合性 ‧計算の論理的制約 ‧同時実⾏制御 ‧データの原⼦性 ‧ビジネスルールの例外ケース
  5. © 2025 Loglass Inc. なぜこのようなことが起きるのか? AI駆動開発の課題 2. ハッピーパスへの集中 // AIが想定する理想的なケース

    val product = products[productId] // 商品は必ず存在 product.stock -= quantity // 在庫は⼗分にある val subtotal = price * quantity // 正の値同⼠の掛け算 AIの思考:「正常ケースで動けば要件を満たしている」 現実: 異常ケース、境界値、競合状態が存在する
  6. © 2025 Loglass Inc. なぜこのようなことが起きるのか? AI駆動開発の課題 3. 暗黙的な制約の理解ができない ⼈間の暗黙の前提(AIには⾒えない) ‧「在庫は決してマイナスになってはいけない」

    ‧「価格や数量は正の値であるべき」 ‧「計算結果は論理的に整合していなければならない」 ‧「同時実⾏時にデータ競合してはいけない」
  7. © 2025 Loglass Inc. Discovery (発⾒) 開発者‧QA‧PdMなど関係者全員でユース ケースを取り上げ、具体的な「例」を出し 合い、仕様や要求の認識を揃える Formulation

    (定式化) 発⾒した「例」を⾃動化できる⽅法 (Gherkin記法など) で誰でも読める形に落と しこむ Automation (⾃動化): 定式化したシナリオ を⾃動テストとして実装し、CI/CDで常に検 証できるようにする BDDとは 33 https://cucumber.io/docs/bdd/#three-practic es
  8. © 2025 Loglass Inc. BDDとは 「Aの時はBになる」を事前に定義す ることで、AIが何をすべきか明確に なる Scenario: 複数商品のまとめ買い割引

    Given 以下の商品が登録されている | 商品名 | 価格 | 在庫 | カテゴリ | | ノートPC | 80000 | 5 | 電⼦機器 | | マウス | 3000 | 10 | 電⼦機器 | | キーボード | 8000 | 8 | 電⼦機器 | | 本 | 2000 | 20 | 書籍 | And まとめ買い割引が以下のように設定されている | カテゴリ | 商品数 | 割引率 | | 電⼦機器 | 3個以上 | 15% | | 書籍 | 5冊以上 | 10% | When ⽥中さんが以下の商品をカートに追加する | 商品名 | 数量 | | ノートPC | 1 | | マウス | 2 | | キーボード | 1 | | 本 | 3 | Then 注⽂が確定される And 注⽂⾦額が以下のように計算される | カテゴリ | ⼩計 | 割引適⽤ | 割引後⾦額 | | 電⼦機器 | 94000 | 15% | 79900 | | 書籍 | 6000 | なし | 6000 | | 配送料 | | | 1000 | | 合計 | | | 86900 | 振る舞いを定義する
  9. © 2025 Loglass Inc. 形式⼿法とは // 基本シグネチャ:商品 sig Product {

    id: one String, // 商品ID(厳密に1つ) name: one String, // 商品名(厳密に1つ) price: one Int, // 価格(厳密に1つ) stock: one Int, // 在庫数(厳密に1つ) category: one Category, // カテゴリ(厳密に1つ) tags: set Tag, // タグ(0以上) seller: one Seller // 販売者(厳密に1つ) } 基本⽂法 - シグネチャ
  10. © 2025 Loglass Inc. 形式⼿法とは sig Customer { // 必須情報(厳密に1つ)

    customerId: one String, email: one String, registrationDate: one Date, // オプション情報(0または1つ) phoneNumber: lone String, // 複数可能な情報(1つ以上) addresses: some Address, // 住所は最低1つ必要 // 任意の複数情報(0以上) paymentMethods: set PaymentMethod, // ⽀払⽅法は任意 } 基本⽂法 - 多重度
  11. © 2025 Loglass Inc. 形式⼿法とは // 確定した注⽂の商品数量合計が在庫を超えない fact InventoryConstraintsReadable {

    all p: Product | { let confirmedStatuses = Confirmed + Processing + Shipped + Delivered let confirmedItems = {oi: OrderItem | some o: Order | oi in o.items and o.status in confirmedStatuses} let productItems = {oi: confirmedItems | oi.product = p} let totalQuantity = sum oi: productItems | oi.quantity totalQuantity <= p.stock } } 基本⽂法 - 制約条件
  12. © 2025 Loglass Inc. 形式⼿法で発⾒する暗黙的なルール: 割引の併⽤ルール fact DiscountCombinationRules { all

    o: Order | all oi: o.items | { // BDD: 「まとめ買い割引が適⽤される」 // 疑問: セール価格との併⽤は? (o.categoryDiscountRate > 0) implies { // パターン1: セール価格を基準にカテゴリ割引 oi.appliedPrice = oi.product.salePrice // oi.individualDiscount = (salePrice * categoryRate) / 100 // パターン2: 定価を基準にカテゴリ割引(セール無効) // oi.appliedPrice = oi.product.regularPrice // パターン3: より有利な⽅を選択 // let categoryTotal = regularPrice * (100 - categoryRate) / 100 // let saleTotal = salePrice // oi.appliedPrice = min[categoryTotal, saleTotal] } } }
  13. © 2025 Loglass Inc. もしこんな状況があったら... Given ノートPCに10%の個別割引クーポンが適⽤可能 And 電⼦機器のまとめ買い割引15%も適⽤可能 When

    両⽅の条件を満たす注⽂をする Then どちらの割引が適⽤される? 暗黙的なルール ‧まとめ買い割引が適⽤される場合、個別商品の割引クーポンは無 効 ‧顧客に有利な⽅を⾃動選択するのか? ‧明⽰的に選択させるのか?
  14. © 2025 Loglass Inc. 形式⼿法で制約をかける この制約は以下を保証する 1. 二重割引の防止 : まとめ買い15%

    + 個別10% = 25%割引は発生しない 2.システムの一貫性 : 1つの注文に1つの割引のみ適用 3.最適化の自動判定 : システムが顧客に最も有利な割引を選択 fact DiscountExclusivity { all o: Order | // まとめ買い割引と個別商品割引は重複適⽤されない o.hasCategoryDiscount = true implies all oi: o.items | oi.individualDiscount = 0 }
  15. © 2025 Loglass Inc. 形式⼿法とは 制約を定義することで 曖昧な要求「まとめ買い割引が適⽤される」    ↓ 形式⼿法で変換 ↓

    厳密な制約「どの条件でどの割引を排他的に適⽤するか」 形式⼿法により、BDDでは表現できない「暗黙的なビジネスルール」を数学的 制約として明⽰化。AIが迷わず⼀貫した実装を⽣成できる環境を構築。
  16. © 2025 Loglass Inc. 型 例: 割引の同時適⽤を型で制限 sealed class DiscountSystem

    { object None : DiscountSystem() data class CategoryDiscount( val discounts: Map<ProductCategory, CategoryDiscountInfo> ) : DiscountSystem() data class IndividualDiscount( val itemDiscounts: Map<String, DiscountRate> ) : DiscountSystem() // CategoryDiscount と IndividualDiscount の同時適⽤を型レベル で防⽌ }
  17. © 2025 Loglass Inc. 型 例: オーダーの処理順序を型で制限 sealed class OrderStatus

    { object Pending : OrderStatus() data class Confirmed(...) : OrderStatus() data class Shipped( val previousState: Confirmed // 必ずConfirmedから遷移 ) : OrderStatus() data class Delivered( val previousState: Shipped // 必ずShippedから遷移 ) : OrderStatus() // 不正な状態遷移を型レベルで防⽌ // × Pending → Delivered (中間状態のスキップ) は不可能 }
  18. © 2025 Loglass Inc. 型 例: 商品種別による適⽤ルールを型で制限 sealed interface Product

    { // 共通プロパティ val id: ID<Product> val name: ProductName val code: ProductCode // 商品タイプによる分岐 val productType: ProductType get() = when (this) { is PhysicalProduct -> ProductType.PHYSICAL is DigitalProduct -> ProductType.DIGITAL is ServiceProduct -> ProductType.SERVICE } }
  19. © 2025 Loglass Inc. メリット: コンパイル時の完全性保証 // これはコンパイルエラーになる val order

    = Order( status = OrderStatus.Delivered( previousState = OrderStatus.Pending // 型エラー ) ) // 正しい状態遷移のみ可能 val confirmed = OrderStatus.Confirmed(...) val shipped = OrderStatus.Shipped(previousState = confirmed) val delivered = OrderStatus.Delivered(previousState = shipped)
  20. © 2025 Loglass Inc. メリット: 不正なビジネスロジックの排除 // 実⾏時まで発⾒されない危険なコード fun applyDiscount(order:

    Order) { // 両⽅の割引を同時適⽤ applyCategoryDiscount(order) applyIndividualDiscount(order) // バグ } // 型安全な実装 fun applyDiscount(system: DiscountSystem): Price = when(system) { is DiscountSystem.None -> originalPrice is DiscountSystem.CategoryDiscount -> applyCategory(system.discounts) is DiscountSystem.IndividualDiscount -> applyIndividual(system.itemDiscounts) // 同時適⽤は型システムにより不可能 }
  21. © 2025 Loglass Inc. メリット: AIによる安全なコード⽣成 // AIが⽣成するコード例 fun processOrder(order:

    Order): OrderResult = when (order.status) { is OrderStatus.Pending -> validateAndConfirm(order) is OrderStatus.Confirmed -> prepareShipment(order) is OrderStatus.Shipped -> trackDelivery(order) is OrderStatus.Delivered -> completeOrder(order) // 全てのケースが強制的にハンドリングされる }