プログラミング・ハーネス
SimpleModelingでは、Scalaを中心としたプログラミングの仕組みを、AIによる開発のハーネスとして利用します。第6回では、モデル (Model)の直接実行とコード生成を前提に、AIが補う連携コードや業務固有の処理を、型・合成規則・共通API・検査によってどう支えるかを説明します。
プログラミング・ハーネスの役割
プログラミング・ハーネスは、AIが使う実装の構造や操作 (Operation)を定め、誤りや逸脱 (deviation)を抑える仕組みです。値の取り違え、共有状態への依存 (Dependency)、失敗時の扱い漏れなどを、個別の注意だけに頼らず防ぐことを目的とします。
既存機能を適切に再利用することで、AIが独自に設計・実装する範囲を減らします。追加が必要なコードには、誤りが入りにくい構造と適合を確認する条件を与えます。この二つの働きによって、AIの判断と修正の負担を抑えます。
SimpleModelingでのプログラミング・ハーネスの全体像
第5回で示したリファレンス・アーキテクチャでは、モデル、生成コード、共通の実行基盤、AIの補完コードが役割を分担します。ここでは、モデルで定めた仕様が型付きAPIを介して補完コードへ引き継がれる流れを示します。
モデル由来の型から再利用とグルーコードへつなぐ
補完コードから共通基盤の操作を利用する
保存、外部通信、非同期実行や障害対応などを支える機構は共通基盤が担い、補完コードは公開されたAPIを通じて利用します。業務処理の記述と実行管理を分担した上で、補完コードに型、純粋関数と合成規則、部品の検査を適用します。以降では、それぞれが担当する制約 (Constraint)を具体的に説明します。
値の取り違えと扱い漏れを型で検出する
型によって、同じ形式の値を業務上の意味で区別し、処理結果として取り得る種類を定められます。値の取り違えと場合分けの不足を例に、AIが生成するコードへどのような条件を適用できるかを見ます。
番号や数量の意味をプログラムでも保つ
状態や結果の種類を扱い漏らさない
処理結果の種類を代数的データ型(ADT)で定め、パターンマッチで場合分けすると、新しい結果を追加した際の扱い漏れを検出できます。例えば、在庫予約に「受付停止」を加えたとき、網羅性の警告をビルドエラーとして扱う設定によって、対応していない呼出し箇所を確認できます。
何でも受け取る場合分けは追加を隠すため、レビューの対象にします。AIが成功時の処理だけを生成した場合も、網羅性検査で不足を返せます。状態 (State)の種類も型で表せますが、許される状態遷移は状態機械 (StateMachine)の規則で確認します。
型による証明を実務の検査へつなぐ
カーリー=ハワード対応は、型を命題、型を持つプログラムをその命題の証明として捉える考え方です。基本的には、直観主義命題論理の証明と単純型付きラムダ計算のプログラムが対応します。関数の型A → Bは「Aが成り立つならBが成り立つ」という命題に対応します。
これらの例では、業務上の区別や接続条件を型へ表し、その条件を満たさないコードをコンパイラで検出しています。型で保証できる範囲が広がるほど、個別の検証やAIレビューで繰り返し確認する条件を減らせます。通常のScalaの型検査で停止性や業務全体の振る舞い (Behavior)まで証明するわけではありませんが、生成・修正のたびに同じ条件を機械的に適用できることは、実務上の効果になります。
参考文献:Philip Wadler, Propositions as Types, Communications of the ACM 58(12), 2015。https://homepages.inf.ed.ac.uk/wadler/papers/propositions-as-types/propositions-as-types.pdf
純粋関数と合成規則で実装の構造を制約する
高度な合成規則を採用する理由
クラウド・ネイティブなアプリケーションでは、負荷の変動や部分的な障害 (defect)に対応しながら応答を維持する必要があります。リアクティブ宣言は、そのための四つの特性として、応答性、耐障害性、弾力性、メッセージ駆動を整理しています(https://www.reactivemanifesto.org/)。
非同期処理や障害対応を業務コードごとに実装すると、処理の順序や失敗時の制御を個別に管理する必要があります。共通基盤が提供する型付きの操作を、モナド (monad)とアプリカティブ (applicative, アプリカティブ・ファンクター)によって依存関係や独立性に沿って組み合わせることで、複雑な実行制御 (Execution Control)を個別に記述する範囲を減らします。リアクティブな特性を支えるのは実行基盤であり、合成規則はその機構を業務コードから利用するために用います。
計算に隠れた状態への依存を持ち込ませない
関数の内部で現在時刻や変化する価格表を参照すると、同じ引数でも結果が変わります。必要な日時、価格表、規則の版を引数へ集め、データを不変に保つことで、同じ入力から同じ結果を得る純粋関数として計算できます。業務規則の評価でも、事実を取得する処理と、固定した事実に規則を適用する計算を分けます。
Consequenceで結果とエラー処理の規則を揃える
Textus/CNCF (Cloud Native Component Framework)では、関数の処理結果をConsequenceで表します。正常な結果には値の型を持たせ、失敗にはエラーの分類、原因、対処の方向などを構造化したConclusionを保持します。結果の接続とエラーの解釈に共通の体系を適用するため、AIが関数ごとに異なる失敗の表現を作ることを抑えられます。
UoWとFree Monadで操作の記述と実行を分ける
Consequenceで結果と失敗の扱いを揃えても、保存や外部呼出しをどこで実行し、その実行を誰が管理するかは別に定める必要があります。Textus/CNCFでは、UoW(Unit of Work)が一連の操作の実行単位と共通の実行管理を担います。Free Monadで操作を記述・合成し、実際の実行をUoWの共通機構へ渡すことで、業務処理の組立てと実行管理を分けます。
UoWの操作を型付きの内部DSLで記述する
UoWで実行する処理をFree MonadとConsequenceで組み立てる
Free Monadでは、UoWで実行する操作を、その場で実行せずにプログラムの記述として組み合わせます。操作の入出力と接続条件を型で検査し、この記述を組み立てる関数を純粋に保つことで、組立て中の副作用や隠れた状態への依存を抑えます。この組合せによって、外部操作を含むプログラムにも、型による接続の保証と、純粋関数として局所的に推論できる構造を適用します。
この操作の記述にConsequenceの合成規則を組み込むことで、計算と外部操作を同じ結果・失敗の体系でつなぎます。Free Monadは操作の記述と合成、Consequenceは結果と失敗の扱いを担当します。実装上は、操作をUnitOfWorkOp、Free MonadによるプログラムをProgramで表し、ConsequenceTによってConsequenceの結果・エラーの規則をプログラムへ組み込んでいます。
インタープリタは記述されたプログラムを解釈し、UoWの共通実行経路で操作を実行して、結果をConsequenceで返します。操作の組合せや実際の応答はテスト (Test)で確認します。非同期実行、通信 (Communication)、障害対応、資源管理などを含む実行基盤がリアクティブな特性を支え、その詳細は第7回で扱います。
型付きの操作を純粋に組み立て、結果と失敗をConsequenceで扱い、実行管理をUoWへ委ねます。この分担によってAIが個別に作り込む制御を減らし、検査・レビューで分担への適合を確認することで、プログラミング・ハーネスとして機能します。
部品の構造と業務上の意味を検査する
型と操作の規則に適合したコードについても、部品の責務 (Responsibility)や要求との整合性を確認します。CARの構造検査、依存関係の確認、テスト、モデルに基づくレビューが、言語の型だけでは扱えない条件を補います。
CARの契約で部品構成からの逸脱を検査する
CARは、Component (コンポーネント)、Service、Operationなどの契約と、実装、依存関係、説明を検査可能な構造にまとめます。car-lintがその構造と公開契約について機械化された規則を確認することで、AIが追加したコードを部品としての適合検査へ載せられます。型の合う関数を作るだけでなく、決めた部品構成へ収める条件がハーネスとして働きます。
共通機構が担う処理を個別実装から外す
共通機構が担う処理をAIが重ねて実装していないかも確認します。検査済みの入力の再検査や、基盤が管理する処理への独自の再試行は、不要な分岐や二重実行を生むことがあります。入力の型と標準APIの契約を確認の基準にします。
依存関係の検査では、公開APIを経由しない呼出しを確認します。レビューでは、追加した防御処理が業務上必要か、共通機構の保証と重複していないかを確認します。これにより、必要な業務上の確認を保ちながら、定めた実装構造への適合を検証します。
診断を修正へつなぎ、変更の発散を抑える
参照
用語集
- Scala
-
Undefined
- シンプルモデリング (SimpleModeling)
-
SimpleModelingは、KnowledgeからDomain Modelを構成し、CMLで形式化し、CozyとAIによって実行可能ソフトウェアへ実現し、Textus上で動作させる、モデリング中心のソフトウェア開発方法論と技術体系です。
- モデル (Model)
-
Modelとは、対象を特定のPurposeとConcernに基づいて選択し、理解、判断、検証、構築に利用できる形で表した抽象です。対象そのものではなく、目的に必要な要素、関係、意味を保持する表現です。
- 逸脱 (deviation)
-
計算値や観測値が、基準値や真値から外れている状態。観測可能な量的ずれを表す。
- 依存 (Dependency)
-
UMLにおけるDependencyは、ClientとなるModel Elementの仕様または実装が、Supplierとなる別のModel Elementの定義へ意味的または構造的に依存することを表すDirected Relationshipです。
- 操作 (Operation)
-
UMLにおけるOperationは、関連するBehaviorを呼び出すための名前、型、Parameter、Constraintを定めるClassifierのBehavioral Featureです。Operationは呼び出し契約を定め、MethodなどのBehaviorがその実現を担います。
- エラー (error)
-
汎用的な表現として用いられる用語。ソフトウェア工学では多義的に使われ、バグや障害全般を指す。SimpleModeling では広義のラベルとして使用し、個別には Mistake・Defect・Fault・Failure・Deviation に整理する。
- Cozy Modeling Language (CML)
-
CML(Cozy Modeling Language)は、オブジェクト・モデルのうち、プログラム生成と実行へ接続する実行可能モデルを記述するSimpleModelingの形式モデリング言語です。
- Cozy
-
Cozyは、CMLと各種DSLで記述されたModelを解析し、プログラム、設定、文書などの実現成果物へ変換するSimpleModelingのツールチェーンです。
- Textus
-
Textusは、SimpleModelingによって実現されたソフトウェアを動作させるための実行基盤です。アプリケーションに共通する実行、運用、連携の機構を提供します。
- 型 (Type)
-
Undefined
- 制約 (Constraint)
-
UMLにおけるConstraintは、一つ以上のModel ElementのSemanticsの一部を宣言するため、自然言語または機械可読言語で表した条件または制限です。評価結果はBooleanであり、評価は副作用を持ちません。
- 状態 (State)
-
UMLにおけるStateは、ある不変条件が成立している状況をモデル化したものです。Objectの現在のStateによって、受け付けられるEventやOperation、成立するConstraint、次に可能なTransitionが変わります。
- 状態機械 (StateMachine)
-
UMLにおけるStateMachineは、Eventの発生によって起動されるTransitionでStateのグラフをたどり、システム要素のevent-driven Behaviorを表すBehaviorです。
- 振る舞い (Behavior)
-
UMLにおけるBehaviorは、そのContextとなるBehaviored Classifierが時間とともにどのようにStateを変えるかを定める仕様です。可能な実行、創発する振る舞い、または特定の実行例を表せます。
- 仕様確認 (verification)
-
Verification(仕様確認)とは、規定された設計仕様や要求仕様に対して、実装が一致しているかを確認する行為である。
- 障害 (defect)
-
成果物(設計書、仕様書、コードなど)に存在する不完全さや不足。要求や仕様を満たさず、修正や置換が必要となる状態。ISO/IEC 24765 に基づく。
- モナド (monad)
-
モナド(monad)は、値を文脈付きのコンテナで包み、連続的な計算の連鎖を安全に構築するための抽象です。 flatMap(bind)とpure(unit)の2つの操作を中心とし、逐次処理・状態管理・エラー伝播などを関数型スタイルで記述するための構文的枠組みを提供します。
- アプリカティブ (applicative, アプリカティブ・ファンクター)
-
アプリカティブ(applicative)は、文脈内の関数と文脈内の値を組み合わせて評価する抽象です。 pure と ap または mapN などの操作によって、依存関係のない複数の計算を並列的・独立的に合成するスタイルを提供します。
- 実行制御 (Execution Control)
-
Undefined
- Cloud Native Component Framework (CNCF)
-
Cloud Native Component Framework(CNCF)は、クラウド・アプリケーションを構成するコンポーネントを、単一かつ一貫した実行モデルで実行するためのフレームワークです。 Component / Service / Operation という構造を中核とし、command、server(REST / OpenAPI)、client、script といった異なる実行形態から、同一の Operation を再利用できることを特徴とします。 ログ、エラー処理、設定、配備といったクラウド・アプリケーションに必要な品質属性をフレームワーク側に集約することで、コンポーネントはドメイン・ロジックの実装に集中できます。 CNCF は、文芸モデル駆動開発および AI 支援開発を前提に、「何を実行するか」と「どのように呼び出すか」を分離するための実行基盤として設計されています。
- 内部DSL (internal DSL)
-
内部DSL(Internal DSL)は、ホスト言語の構文と型システムを利用して構築されるドメイン特化表現です。 ホスト言語の文法範囲内で設計されるため、既存の型検査やツール群をそのまま活用でき、実行可能で保守性にも優れます。 Scalaでは、関数・型クラス・マクロ・拡張メソッドを組み合わせて柔軟なDSLを設計できます。
- 永続化 (Persistence)
-
Undefined
- テスト (Test)
-
Testとは、指定した条件で対象を実行または評価し、観測した結果を期待する結果やConstraintと比較して、要求または契約への適合を確認する活動とその仕様です。
- 通信 (Communication)
-
Undefined
- 責務 (Responsibility)
-
Responsibilityとは、ObjectまたはRoleが、何を知り、判断し、行い、守るべきかを表す義務です。構造上の情報だけでなく、規則とBehaviorの所有を定めます。
- コンポーネント (Component)
-
責務・契約・依存関係を明示的に定義し、再利用可能で交換可能な単位としてカプセル化されたソフトウェア構成要素。論理モデルでは抽象構造単位として、物理モデルでは実装・デプロイメント単位として扱われる。
- 妥当性確認 (validation)
-
Validation(妥当性確認)とは、システムや機能が利用目的や要求仕様に対して妥当であるかを確認する行為である。
- 生成出力 (generated output)
-
生成AIが知識表現生成プロセスを通して出力する成果物。 文書・コード・要約・構造化データなどを含む。