手続き的凝集

 このサンプルコードでは、、手続き的凝集のクラスが複数の異なる責務を担当している状況を示します。

 OrderProcessingクラスが注文処理、顧客情報の更新、請求書の生成という異なる責務を持っています。
このようなクラスは手続き的凝集を示しており、下記のような問題が発生します。

保守性の低下
 特定の責務に関する変更を行う際に、他の責務に影響を与える可能性があります。例えば、注文処理に関する修正が、顧客情報の更新に問題を引き起こす可能性があります。
再利用性の低下
 特定の処理を他の部分で再利用する場合、クラス全体を再利用せざるを得ないため、不要なコードや責務も含まれることになります。
テストの困難さ
 単一のクラスに複数の責務が含まれるため、各責務に対する単体テストを行うのが難しくなります。
<?php

class OrderProcessing
{
    public function processOrder($orderData)
    {
        // 注文処理の論理
    }

    public function updateCustomerInfo($customerData)
    {
        // 顧客情報の更新処理
    }

    public function generateInvoice($orderData)
    {
        // 請求書の生成処理
    }
}
                    
<?php

$orderProcessor = new OrderProcessing();
$orderData = /* 注文データ */;
$customerData = /* 顧客情報 */;
$orderProcessor->processOrder($orderData);
$orderProcessor->updateCustomerInfo($customerData);
                    

手続き的凝集の改善例

 解決策として、それぞれの責務に特化したクラスを作成し、各クラスが単一の責務を担当するように設計することが考えられます。
このように設計を改善することで、手続き的凝集の問題を克服できます。
改修の際には、クラスを分割し、それぞれのクラスが特定の責務を担当するように設計することが重要です。例えば、OrderProcessingクラスを以下のようなクラスに分割できます。

  • OrderProcessorクラス: 注文処理に特化
  • CustomerInfoUpdaterクラス: 顧客情報の更新に特化
  • InvoiceGeneratorクラス: 請求書の生成に特化

 下記の改善された設計において、各クラスは単一の責務を担当しており、クラス間の結合度が低く、変更が特定の責務に関連付けられます。
このような設計は保守性が高く、テストも容易に行えます。

<?php

class OrderProcessor
{
    public function processOrder($orderData)
    {
        // 注文処理の論理
    }
}
                    
<?php


class CustomerInfoUpdater
{
    public function updateCustomerInfo($customerData)
    {
        // 顧客情報の更新処理
    }
}
                    
<?php

class InvoiceGenerator
{
    public function generateInvoice($orderData)
    {
        // 請求書の生成処理
    }
}
                    
<?php

$orderProcessor = new OrderProcessor();
$customerInfoUpdater = new CustomerInfoUpdater();
$invoiceGenerator = new InvoiceGenerator();

$orderData = /* 注文データ */;
$customerData = /* 顧客情報 */;

$orderProcessor->processOrder($orderData);
$customerInfoUpdater->updateCustomerInfo($customerData);
$invoiceGenerator->generateInvoice($orderData);
                    

Tips

 動詞で名付けられたクラスは、一般的にそのクラスが特定の操作やプロセスを実行することを示しています。
クラス名そのものがプロセスに焦点にされているため、その性質上手続き的凝集になりやすい傾向にあります。
このようなクラスは、操作やプロセスを単一の責務として持つべきで、手続き的凝集を避けるために注意が必要です。

 また、手続き的凝集を避けるために、クラス名が特定の操作やプロセスを示さないようにすることも一つのアプローチです。
クラス名が動詞ではなく、名詞またはドメインに焦点を当てたものであると、手続き的凝集を回避しやすくなります。