BETA

コード(ロジック)の重複と境界づけられたコンテキスト

投稿日:2019-07-15
最終更新:2019-07-19

私がドメイン駆動設計(DDD)に至った過程で、
言及していました境界づけられたコンテキストと
コードの重複についての考えを説明します

コード(ロジック)の重複に対してドメイン駆動設計(DDD)の考え方

開発をしていて、コードが重複することはよくあります。
ただ、このコードの重複をなくし、共通化するのは
一概にはよいことではありません。

よくあるのが、開発が進みコードが育つと、
コードの重複という冗長性をなくしたことで
かえって、開発しにくくなり、変更に弱くなってしまうことがあります。
よく言われる時期尚早な最適化ともいえます。

このコードの重複についてはDRY原則での紹介例が多いのですが、
実際のところ、DRY原則についてはソフトウェア開発の全てに
おいての重複を焦点としています。

DRY原則の考え方の適用ではコードだけに絞って、
考えてしまうのがよろしくないのです。

実際に過去、私の経験でも、DRY原則で、コードだけに考えを絞り、
コードの重複は駄目と考え、重複をなくしたことで、
かえって、変更に弱くなってしまったことがありました。

この問題に対して必要となるのは、開発対象となるシステムでの重複で
あるかどうかを判断する考えです。

その考えの一つとして、システムでの重複をどう判断すればいいかで、
ドメイン駆動設計(DDD)では関心事(ドメイン)から発生する
境界づけられたコンテキストという考え方があります。

コード(ロジック)の共通化とビジネスの要求

<?php  

class Notification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  

上記のコードは単純化していますが、通知の処理のコードです。
ある日、ビジネスの要求で内部(組織内)と
外部(組織外)に通知を行うことになりました。

<?php  

class InternalNotification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  
<?php  

class ExternalNotification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  

上記のコードはビジネスの要求である
内部と外部の通知を単純化してコードに反映しました。

しかし、InternalNotificationとExternalNotificationで、
Executeのコードの重複があります。
なので、コードの重複をなくし、共通化するとします。

<?php  

class InternalNotification {  

    function __construct() {  
    }  

    // 以降その他の処理  
}  
<?php  

class ExternalNotification {  

    function __construct() {  
    }  

    // 以降その他の処理  
}  
<?php  

class Common {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  

これも単純化して、CommonにExecute()を実装し、
コードの重複をなくしました。
恐らく、この時点では、問題ないのです。

問題となるのはビジネスの要求を反映していき、
開発がある程度進んだ段階です。

開発がある程度進んだ段階で、例えば、ビジネスの要求から、
通知で外部には伏せておきたい情報があり、
ある程度の実装が進み、処理の都合上で、
Execute()に実装するしかないとします。

<?php  

class Common {  

    function __construct() {  
    }  

    public function Execute() {  

        if (外部における条件式) {  
            // 実装の詳細  
        } else {  
            // 実装の詳細  
        }  
    }  

    // 以降その他の処理  
}  

今度はビジネスの要求から内部の通知で、
特定部署に対しては特別な処理がする必要が出てきて、
これも処理の都合上で、Execute()に
実装するしかないとします。

<?php  

class Common {  

    function __construct() {  
    }  

    public function Execute() {  

        if (外部における条件式) {  
            // 実装の詳細  
        } elseif (内部の特定部署における条件式)  {  
            // 実装の詳細  
        } else {  
            // 実装の詳細  
        }  
    }  

    // 以降その他の処理  
}  

外部と内部の通知の処理が混在し、
今後、このようなことが続いていくと、
変更に弱くなってしまうのは明白です。

では、どうすればよかったかの考えの1つとして
先程の境界づけられたコンテキストがあります。

関心事(ドメイン)と境界づけられたコンテキスト

境界づけられたコンテキストは関心事(ドメイン)を分割して、
境界線を引いた結果、出来上がったものというのがニュアンスとして
近いです。

先程の例ですと、内部と外部に分割して、
境界線を引き、通知は内部と外部が
別々のものとして持つとしたのが、
今回の場合での境界づけられたコンテキストです。

コードでは以下のように考えるとわかりやすいです。

<?php  

namespace Internal;  

class Notification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  
<?php  

namespace External;  

class Notification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
    }  

    // 以降その他の処理  
}  

namespaceでInternal(内部)とExternal(外部)で、
別個の境界付けられたコンテキストとします。

これですとビジネスの要求で外部の処理で変更があっても
通知があっても、内部への影響はありません。

<?php  

namespace Internal;  

class Notification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
        // 内部の通知の処理なので、外部の実装の詳細の変更の影響はない  
    }  

    // 以降その他の処理  
}  
<?php  

namespace External;  

class Notification {  

    function __construct() {  
    }  

    public function Execute() {  
        // 実装の詳細  
        // 外部の通知の実装の詳細を変更なので、内部の処理に影響を及ぼさない  
    }  

    // 以降その他の処理  
}  

関心事(ドメイン)と境界づけられたコンテキストについては、
NETのエンタープライズアプリケーションアーキテクチャ 第2版の
124ページから127ページでの説明が非常にわかりやすいです。
特にコードの重複がよいかどうかを悩んでいる方に、126ページの図は必見です。

取り上げた書籍

NETのエンタープライズアプリケーションアーキテクチャ 第2版

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@fubukiの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!