Vegas Engineering by FORBIS 記事一覧
← 記事一覧へ戻る
Architecture ・ 第13回

業務ルールを"関数"で差し込む — チェック関数(DCF)と導出関数(DDF)の設計

検証と派生計算を、コードの海に埋めず「差し替え可能な関数」として登録する。定義駆動の書き込みエンジンの心臓部。

Vegas 開発チーム ・ 2026-07-03 ・ 読了 8分

WHYルールを本体から剥がす

通販基幹のような業務システムでは、書き込み処理の周囲に膨大な業務ルールが張り付く。「この項目が変わったら送料を再計算する」「登録日時が無ければ受け付けない」「配送先を請求先からコピーする」——こうしたルールをエンジン本体の分岐として書き連ねると、コードは急速に読めなくなり、ルールを一つ足すたびに全体を壊す恐怖と戦うことになる。

定義駆動の書き込みエンジンでは、この問題を「業務ルールを2種類の小さな関数として外から差し込む」という設計で解く。エンジン本体はルールの中身を知らない。何が登録されているかだけを見て、必要なものを呼び出す。ルールは資産として独立して増えていく。

DCF / DDF2種類の関数

差し込む関数は役割で2種類に分かれる。

どちらも evaluate(入力) → {結果} という統一インターフェースを持つ。エンジンから見れば両者は「呼べば結果を返す箱」でしかなく、この均質さが差し替え可能性の土台になる。DCFはゲート、DDFは生成——役割は対照的だが、外形は同じという点が重要だ。

変更検知 変わった項目 関数を選定 重複排除・依存解決 DCF 検証 可否ゲート DDF 導出 再帰的に解決 反映 派生の派生
図:変更検知→関数選定→DCF検証→DDF導出(再帰)→反映のパイプライン。エンジンはルールの中身を知らず、登録された関数を順に駆動するだけ。

HOWエンジンの駆動

実行の流れはシンプルだ。エンジンは「変更された項目」を起点に、それに反応するはずの関数を洗い出してタスク化する。同じ関数が複数の項目から呼ばれても重複は1つに畳み、関数間の依存関係を解決してから順に走らせる。

DDFの実行は再帰的になる点に注意したい。送料を導出した結果、割引の前提が変わり、別のDDFが新たに必要になる——こうした「派生の派生」を、対象がなくなるまで解決し続ける。DCFは値を変えないため通常は先に評価してゲートを固め、DDFで値を作っていく。

CODE2つの関数の骨格

rules/functions.pyPython
class RegisteredAtCheck(DCF):
    # DCF: 登録日時の必須チェック(ゲート)
    triggers = ["registered_at"]

    def evaluate(self, data):
        if not data.get("registered_at"):
            return {"ok": False,
                    "errors": ["registered_at is required"]}
        return {"ok": True, "errors": []}


class ShippingFeeDerive(DDF):
    # DDF: 送料と割引の導出(値の生成)
    triggers = ["subtotal", "region"]

    def evaluate(self, args):
        base = fee_for(args["region"])
        # 一定額以上は送料無料(派生の派生を誘発しうる)
        fee = 0 if args["subtotal"] >= FREE_LINE else base
        return {"data": {"shipping_fee": fee}}

TRADE-OFF得るものと払うもの

この設計の利点は明確だ。ルールを単位でテスト・追加・差し替えでき、エンジン本体に手を入れずに業務を変えられる。関数が自己完結しているため、AIに「この1関数を丸ごと生成して」と頼みやすいのも実務上大きい。

一方で払う代償もある。関数が増えるほど実行順序と依存関係の管理が難しくなり、依存の循環や解決漏れは追跡が厄介だ。処理が多数の小関数に分散するためデバッグ時の見通しが悪く、どの関数がどの値を書いたかを追う仕組みが要る。さらにDDFが状態を書き換える以上、関数間の副作用を制御しないと、実行順によって結果が変わる不安定さを招く。小さく差し替えられる自由と、全体を俯瞰しにくくなる不透明さは表裏一体である。

TAKEAWAY

業務ルールをDCF(検証ゲート)とDDF(値の導出)という統一インターフェースの小関数に切り出せば、エンジン本体を触らずにルールを増減・差し替えできる。代償は実行順序・依存・副作用の管理コスト。自由度と俯瞰性のトレードオフを、依存解決とトレースの仕組みで埋めるのが設計の勘所。