samedi 26 décembre 2020

Design pattern to reduce cyclomatic complexity


I have to send invoices to cutomers through the related customer's API.
Each customer chooses how to be contacted (email, fax, sms...).
My problem is that each time I add a new "contact type" I increase the cyclomatic complexity of my script.
Here is my code :
<?php

interface ExternalApi
{
    public function sendByEmail();
    public function sendByFax();
    public function sendBySMS();
    // more sending modes ...
}

class Api1 implements ExternalApi
{   
    public function sendByEmail()
    {
        echo __CLASS__." sending email<br>\n";
    }
    
    public function sendByFax()
    {
        echo __CLASS__." sending fax<br>\n";
    }
    
    public function sendBySMS()
    {
        echo __CLASS__." sending SMS<br>\n";
    }
}

class Customer
{
    public const EMAIL = 'email';
    public const FAX = 'fax';
    public const SMS = 'sms';
    public const EMAIL_AND_FAX = 'email_and_fax';
    public const PHONE = 'phone';
    public const PLANE = 'plane';
    public const BOAT = 'boat';
    public const SATELITE = 'satelite';
    public const CAB = 'cab';
    // more contact types...
    
    public ?string $contactType;
}

class Invoice
{
    public Customer $customer;
    
    public function __construct(Customer $customer)
    {
        $this->customer = $customer;
    }
}

class InvoiceSender
{
    private ExternalApi $api;

    public function __construct(ExternalApi $api)
    {
        $this->api = $api;
    }
    
    public function send(Invoice $invoice)
    {
        switch($invoice->customer->contactType) {
            case Customer::EMAIL :
                $this->api->sendByEmail();
                break;
            case Customer::FAX :
                $this->api->sendByFax();
                break;
            case Customer::SMS :
                $this->api->sendBySMS();
                break;
            case Customer::EMAIL_AND_FAX:
                $this->api->sendByEmail();
                $this->api->sendByFax();
                break;
            // more cases ...
        }
    }
}

$customer = new Customer();
$customer->contactType = Customer::EMAIL_AND_FAX;
$invoice = new Invoice($customer);
$api = new Api1();
$invoiceSender = new InvoiceSender($api);
$invoiceSender->send($invoice);

As you can see the switch statement of InvoiceSender::send is increased each time I add a new "contact type".
Do you know which design pattern could solve this problem ?

Aucun commentaire:

Enregistrer un commentaire