PHP Mentors — Debasish Ghosh氏のブログ記事「ドメイン駆動設計:可変性の管理」を翻訳しました

1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

Debasish Ghosh氏のブログ記事「ドメイン駆動設計:可変性の管理」を翻訳しました

ドメイン駆動設計が、今、世界的に盛り上がりを見せています。2016年1月には、Domain-Driven Design Europeが開催されるそうです。このイベントのスピーカー&ワークショップ講師の1人として、Jim Coplien氏の名前が載っています。Jim Coplien氏は、日本だと、「組織パターン」の著者として、また、DCIアーキテクチャの人として有名ですが、ドメインエンジニアリングの研究者でもあります。

Eric Evans氏のDDD本は、サブタイトルが、「ソフトウェアの核心にある複雑さに立ち向かう」となっています。複雑さとは何か、それを管理する技術とは何か、古くて新しい問題です。Jim Coplien氏の著作「マルチパラダイムデザイン」では、ドメインとは何か、どのように設計を行うべきかについて書かれています(残念ながら絶版です。)

Debasish Ghosh(デバシッシュ・ゴーシュ)氏のDDDとマルチパラダイムデザインを関連付けたブログ記事「Domain Driven Design : Managing Variability」を翻訳しました。以下に掲載します。(※デバシッシュ氏は、ScalaMatsuri2016応募されています!)。

Note Debasish Ghosh氏は書籍「実践プログラミングDSL」(原著: DSLs in Action)の著者として知られています。彼は現在Functional and Reactive Domain Modelingを執筆中です。こちらは2016年春に出版予定だそうですが、MEAPを利用して一足先に読むこともできます。


ドメイン駆動設計:可変性の管理

原文URL:http://debasishg.blogspot.jp/2006/09/domain-driven-design-managing.html

2006年9月18日(月)

Springのユーザーたちが、ドメイン駆動設計について語り始めました。彼らはきちんと取り組んでおり、良い議論をしています。2006年に行われたSpringOneでは、ドメイン駆動設計に関する3つのセッションがありました。 AOPの人として知られているRamnivas Laddad氏(最近「Interface 21」メンバーに加わりました)は、DIとAOPが、DDDの最も良いところを引き出すのに有効であること―最小限のサービス層、豊かなドメイン層、流れるようなインターフェイスについて発表しました。 「Interface 21」とGrailsで知られるSteven Devijver氏は、サービス層にある複雑性を管理するためにデザインパターンを利用することについて語り、リッチなドメインモデリングに関する議論を行いました。 レイヤー化、AOP、IoC等による関心の分離のような重要なアスペクトについて彼は強調しました。 不変性は、モデルの正当性を維持するために重要であること。 つまり、クラスはイミュータブルに作り、できるだけ外部へ漏れ出さないように制御に努めること。 実装の内部をさらけ出してはならないこと―パブリックなセッターはNGであること。 要するに、ドメインモデルは、ドメインエキスパートが話せるドメインの言語にだけ公開されているべきだということです。 インターフェイスとパブリックな契約が、ユビキタス言語を語るように作ること。 ドメインモデリング技法に関する別のセッションでは、「Interface 21」のKeith Donald氏が、ドメインの蒸留、ドメインモデルの中に獲得した知識を抽象化するためのテクニックについて話しました。 全体を通して、SpringユーザたちはDDDファンのイベントを楽しんでいるようでした!

可変性!可変性!

ドメインモデルを、柔軟に、生成的(ジェネレ―ティブ)に作るということは、モデルにおいて可変性を管理することに尽きます。 そのモデルの可変部分をうまく管理することによって、より構成しやすく、カスタマイズしやすく、柔軟にすることができるようになります。 以前の記事では、ジェネレーターとしてはたらいて基盤を提供する構成の知識について書きました。 構成の知識を最大限に活用するのがこの可変性です。 設計のアスペクト、固有の実装、ライフサイクル、スコープの決まったインスタンス、アルゴリズム、ストラテジー等は、Java / C++のコードベースの中で埋没させたくはないものなのです。

ストラテジーパターンで示すと…

ここ数年、ストラテジーパターン実装の多くのバリエーションが、モデルの可変性を管理するために使われてきたと思います。 GOFは C++ で2つのバリエーションを検討しています。 1つは、実行時ポリモーフィズムと仮想関数を使うもの、もう1つは、テンプレートとコンパイル時ポリモーフィズムを使うものです。 それぞれにメリットがあり、特定のコンテキストにある特定の問題を解決するのに用いることができます。

下記スニペットに、ストラテジーデザインパターンを実行時ポリモーフィズムで適用して、繰延利息計算(accrual calculation)ドメインプロセスを外部化するやり方を示します。

class AccrualCalculation {

    private CalculationStrategy strategy;

    // セッターインジェクション
    public void setStrategy(CalculationStrategy strategy) {
        this.strategy = strategy;
    }

    // ストラテジーへの委譲
    public BigDecimal calculate(...) {
        return strategy.calculate(...);
    }
}

interface CalculationStrategy {
    BigDecimal calculate(...);
}

class DefaultCalculationStrategy implements CalculationStrategy {
    public BigDecimal calculate(...) {
        // 実装
    }
}
// 構成の知識を通して可変性を外部化する
<bean id="calcStrategy" class="com.x.y.DefaultCalculationStrategy"/>

<bean id="accrual" class="com.x.y.AccrualCalculation">
  <property name="strategy">
    <ref bean="calcStrategy"/>
  </property>
</bean>

ジェネリクスを使って実装した同じパターンと比べてみましょう。 繰延利息計算クラスがストラテジーでパラメーター化されるように設計しています。

class AccrualCalculation<S extends CalculationStrategy> {
    private S strategy;

    // ストラテジーへの委譲
    public BigDecimal calculate(...) {
        return strategy.calculate(...);
    }
}

// 使い方
interest = new AccrualCalculation<DefaultCalculationStrategy>().calculate(...);

トレイトテクニックのelse-if-then型(この名前、いいですね!)は、C++コミュニティで使われており、拡張性を持たせつつ型レベルで可変性を管理することができます。 トレイトクラスとトレイトテンプレートは、メタプログラミング能力に秀でていただけではなくて、様々なC++アプリケーションの開発に使われてきました。 コンパイル時ストラテジーの別なバリエーションとして、Alexandrescu氏のポリシーベース設計があります。 ポリシークラスは、実装をいくつでも持つことができ、コンパイル時ストラテジーをドメインモデルにプラグインするのに最適な選択肢を提供してくれます。

ストラテジーデザインパターンは、最適な機構を提供することで、ドメインモデルにおける粗粒度の可変性をカプセル化します。 ストラテジーの実装をIoCコンテナやその他のジェネレーターへと外部化することにより、モデルがプラガブルであるようにします(構成の知識として)。

細粒度の可変性とテンプレートメソッド

テンプレートメソッドデザインパターンは、アルゴリズム、ストラテジーといった細粒度の可変性を、共通性フレームワークの範囲内でプラグインすることを目的としています。 ドメインプロセスの大きなレベルでのフローが不変である場合、モデルでこのパターンを使います。 こまごました物をカスタマイズできるように、フックをかけて外部化するわけです。 私はルールベースの大規模な金融アプリケーションをモデリングした時に、このパターンをうまく効果的に活用できました。 下記は、テンプレートメソッドデザインパターンを使って、細粒度の可変性を実装するサンプルです。 ここで、繰延利息計算アルゴリズムはfinalであり、フックの箇所は派生クラスによって追加されます。 フックは基底クラスの抽象メソッドとして管理されます。

abstract class AccrualCalculation {
    public final BigDecimal calculate(...) {
        // フック
        int days = calculateAccruedDays(...);
        if (days != 0) {
            // 不変のロジック
            } else {
            // フック
            boolean stat = isDebitAccrualAllowed(...);
            if (stat) {
                // 不変のロジック
            }
            // 不変のロジック
        }
    }

    protected abstract int calculateAccruedDays(...);
    protected abstract boolean isDebitAccrualAllowed(...);
}

負の可変性

Jim Coplien氏は、設計、分析領域において、この用語を著作マルチパラダイムデザインの中で初めて紹介しました。 共通の継承階層にまとめられるメンバー群にあるうちの一部のメンバーが、他の点においては共通であるのに、一部の点でだけは基底クラスの仮定を破壊してしまうような時、これを負の可変性と呼びます。 Cope(訳注:James O. Coplien のこと)は、負の可変性は、基礎である共通性を侵害してバリエーションのルールを壊す、ルールの例外になる、と述べています。 負の可変性を実装するためのテクニックは少なくありません。 たとえば、C++ におけるテンプレートの特殊化や、条件コンパイル等です。 ブリッジデザインパターンもこの問題をうまく扱えることが知られています。 Coplien の「マルチパラダイムデザイン」に、負の可変性について詳しく書かれています。 この師範の深い洞察をぜひ読んでみて下さい。 実務の場で、ドメインモデルが負の可変性の振る舞いを示すことはよくあります。 そのようなとき、適したパターンやイディオムを使って、正しく取り扱う必要があります。

参考文献

関連記事

ddd practical.ddd design multiparadigm.design

See more posts like this on Tumblr

#ddd #practical.ddd #design #multiparadigm.design