When refactoring and old class in PHP, I noticed that it contained a lot of business logic and thus was not allowing code reuse. So I thought about composition in order to achieve horizontal code reuse (since inheritance permits only vertical reuse) and the possibility to do Dependency Injection eventually. DI gives then the possibility to use Mock Services in order to test the classes.Basically, that class permits sending SMS using the API of a third-party and we have hundreds of APIs we need to deal with, so this is why the idea of horizontal code reuse would be useful.When we send an SMS, we need to:Send an HTTP request to some URL provided by the Carrier with the right body contents (phone number, SMS title, SMS content and other information, depending on the carrier) and in the right format (XML, JSON, SOAP, depending on the carrier)Log the sent SMS*in the database (phone number, title, contents, delivery_status). The table where it is logged is used for tracking all sent SMSses. Also, we attach a delivery_status code (1 for delivered, -1 for not delivered) because some carriers send us then a Delivery Report (by requesting a script on our end) if the phone acknowledges the delivery.Log the sent SMS specifically for that Carrier in another dedicated table that contains more fields than (phone_number, title, message, delivery_status). Those fields could be used in the future for special purposes.I decided to separate the logic in mainly three classes:LoggerService: Class that logs the sent sms informations in the database (also logs the carrier-specific sent sms informations)RequestMaker: Trait that simply makes HTTP requests and returns the result without any further processingSerializerService: Service that serializes the body of the request (converts from a dictionary of parameters to a specific format required  by the carrier like XML or JSON, etc.). XMLBodySerializer is one implementation of that service. JsonBodySerializer is another.SmsSender: The core class that is using the RequestMaker trait and the two other services in order to perform an API call to the specific carrier's API. If a carrier named MyCarrier exists, we would have a MyCarrierSender class inheriting SmsSender. The main task of that class would be to build the right request body and to pass it to the serializer, then to the request maker which will call the API. Finally, the class should fill the sent SMS DTO that will the be logged using the LoggerService currently in use.Do you think it is a good idea to adopt this design? In other words, does it meet the goals of:Decoupling business logicCode reusingPermitting testabilityHere is an implementation of the architecture:interface SmsSender {    public function initServices(        ILoggerService $resultLoggerService, // That Logs information about sent SMS in the databse        IBodySerializer $serializerService, // Request Body Serializer        );    public function sendText(        $msisdn,        $title=,        $text=,        $options=array());}trait RequestMaker {    public function makeGet($url, $params=array());    public function makePost($url, $params=array(), $body);    public function buildUrl($url, $params=array());    public function request($url, $method=null, $params=array(), $body=array());}interface IResultLoggerService {    // Logs the SMS sent to the database    public function logResult($sms2Dto);    // Logs sent SMS specific informations for that Carrier    public function logInMt($specificMtDto);}/*** Request Body Serializer (XMLBodySerializer, JSONBodySerializer implements it) that serializes the body of the request*/interface IBodySerializer {    public function serialize($data);    public function parse($response);}/** *  Example of an SMS Sender for a specific Carrier*/class MyCarrierSmsSender implements SmsSender {   use RequestMaker;   public function __construct() {        $this->initServices(            new MyCarrierLoggerService(),            new XMLBodySerializer() // Will use XML for communication with the carrier's API        );    }    protected function preSend($msisdn, $title, $text, $options) {        /**        * Performs some verifications, prepares some variables        * ....        */        // Example :        $sentSms = new Sms2Dto();        $sentSms->setMsisdn($msisdn);        // etc.        $this->setSms2(); // Set the Sent SMS DTO    }    public function sendText($msisdn, $title, $body, $options = array()) {        $this->preSend($msisdn, $title, $body, $options);        $data = {             // .... prepare request data        }        // Serialize data using the injected service        $raw_data = $this->getSerializerService()->serialize($data);        // Call request() from the RequestMaker trait        $raw_result = $this->request($url, array(), $raw_data, POST);        // Deserialize API's response         $result= $this->getSerializerService()->parse($raw_result);        // Interprets API's response and returns a SUCCESS or FAIL status code        $status = $this->interpretResult($result);        $this->postSend($status);        return $status;    }    protected function postSend($status) {        if($status == SUCCESS) {              // Log sent SMS              $this->getLoggerService()->logResult($this->getSms2Dto());              // Log specific sent SMS by this carrier (contains more useful and specific info to that carrier)              $this->getLoggerService()->logInMt($this->getMtDto());         }    }}There are also DTOs: Sms2Dto and {Carrier}MtDto for every Carrier.Before that design, everything here was done in one class. There was a class for each carrier so a lot of code was repeated.
Composed Architecture
php;design patterns