{"id":490,"date":"2013-10-13T23:31:18","date_gmt":"2013-10-13T23:31:18","guid":{"rendered":"https:\/\/intelligentbee.com\/blog\/?p=490"},"modified":"2024-08-05T12:43:32","modified_gmt":"2024-08-05T12:43:32","slug":"the-chain-desing-pattern","status":"publish","type":"post","link":"https:\/\/intelligentbee.com\/blog\/the-chain-desing-pattern\/","title":{"rendered":"The Chain Design Pattern"},"content":{"rendered":"<p>Today&#8217;s article is meant to show you how to go from plain-text tasks to a collection of classes that are meant to work together.<!--more--><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_68_1 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title \" >Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/intelligentbee.com\/blog\/the-chain-desing-pattern\/#What_is_the_project_about\" title=\"What is the project about?\">What is the project about?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/intelligentbee.com\/blog\/the-chain-desing-pattern\/#Now_the_fun_part\" title=\"Now, the fun part!\">Now, the fun part!<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"What_is_the_project_about\"><\/span>What is the project about?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The project describes a cron, that was built taking in consideration the folowing steps:<\/p>\n<ol>\n<li>Read Excel files (the files are imported from another software product).<\/li>\n<li>Insert data from each row, contained by the Excel file, \u00a0into a MySQL database.<\/li>\n<li>Insert statistics into database, regarding the parsing process of the file &#8211; these will be refered to as\u00a0<code>statistic objects<\/code>.<\/li>\n<li>Most important task:\u00a0make it OOP.<\/li>\n<\/ol>\n<p>As you can see this description is a bit short, so allow me to go in more detail.<\/p>\n<p>The cron needs to be able to read excel files exported from another IT software. Basically, the client already has a backend application, used for saving data about his products, but needed something to export that data from excel files to a mysql database server.<\/p>\n<p>The reason being that in the future his clients can log into a website and modify their data themselves, without contacting his office.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Now_the_fun_part\"><\/span>Now, the fun part!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>However, the description above looked a little too brief to me, so I asked myself the following questions:<\/p>\n<blockquote><p>How easy will it be to add new functionalities to the existing ones?<\/p>\n<p>How easy will it be to enrole the project, from its current state, into a framework? (By the time i wrote this, i&#8217;ve already enroled the project into Symfony)<\/p>\n<p>How easy will it be, for a new programmer, to take the project and create a new functionality, without knowing all the details of the project?<\/p><\/blockquote>\n<p>Starting from this questions, I digged around, searching for solutions. This is what it helped me: <a title=\"Chain of Responsibility\" href=\"http:\/\/sourcemaking.com\/design_patterns\/chain_of_responsibility\" target=\"_blank\" rel=\"noopener\">Chain of Responsibility<\/a>\u00a0design pattern.<\/p>\n<p>To avoid any ambiguity, this article does not show you how to implement <code>Chain of Responsibility<\/code>\u00a0it describes how to implement the &#8220;chain&#8221; design pattern. The difference between these two is that the event is treated by all the objects and not only by one, like in the <code>Chain of Responsibility<\/code> pattern.<\/p>\n<p>As I previously said, I was inspired by <code>Chain of Responsibility<\/code> (I wanted three objects that do things separate ways):<\/p>\n<ul>\n<li>The first one should scan the Excel data folder (in this directory, I put all the Excel files that needed to be parsed) and create statistic objects for each file.<\/li>\n<li>The second object should parse those files, take the data and insert it into the MySQL database.<\/li>\n<li>The third object should insert the data from the statistic objects (objects that describe the files that were parsed) in the database and move the Excel files from the initial directory into the <code>ExcelParsedFiles<\/code> directory.<\/li>\n<\/ul>\n<p>All good and dandy, but if you translate this into a <code>php<\/code> script, you will probably be tempted to do something like this:<\/p>\n<pre class=\"theme:tomorrow-night toolbar:2 lang:php decode:true\">&lt;?php \r\n\r\n    \/\/ this will take care of the first task\r\n    $objFinder = new FilesFinder();\r\n\r\n    \/\/ this will return the statistic objects \r\n    $files = $objFinder-&gt;getFiles();\r\n\r\n    \/\/ object for parsing and inserting data from files\r\n    $objParser = new XLSXParser(); \r\n    $objParser-&gt;insertDataFrom($files);\r\n\r\n    \/\/ save the statistics and move the files to excel files runned folder\r\n    $objStatistics = new Statistics();\r\n    $objStatistics-&gt;insertStatistics($files);<\/pre>\n<p>I&#8217;m not a very big fan of this, so, a solution to avoid it, will be to wrap the three objects into a list that executes itself. Let&#8217;s take a look at the &#8220;final&#8221; file that takes care of the request:<\/p>\n<pre class=\"theme:tomorrow-night toolbar:2 lang:php decode:true\" title=\"index.php\">    \/\/ get sequence of classes that are needed for parsing job\r\n    $chain = ChainBuilder::getInstance()-&gt;getChain();\r\n    $chain-&gt;execute();<\/pre>\n<p>To explain the first line, <code>ChainBuilder<\/code> is the object responsible for wrapping all three objects (<code>FilesFinder<\/code>, <code>XLSXParser<\/code>, <code>Statistics<\/code>) in just one object (see the bellow print of the object).<\/p>\n<pre class=\"theme:tomorrow-night toolbar:2 lang:php decode:true\">FilesFinder Object\r\n(\r\n    [_successor:protected] =&gt; XLSXParser Object\r\n        (\r\n            [_successor:protected] =&gt; Statistics Object\r\n            (\r\n            )\r\n\r\n        )\r\n    )\r\n)<\/pre>\n<p>Every one of those three classes extend a fourth abstract class, called <code>ChainElement<\/code> (you will find the code for this class below) .<\/p>\n<blockquote><p>&nbsp;<\/p><\/blockquote>\n<pre class=\"theme:tomorrow-night lang:php decode:true\" title=\"ChainElement\">&lt;?php \r\n\/**\r\n * Base class for every object part of the sequence \r\n * of objects that need to be executed\r\n *\/\r\nabstract class ChainElement\r\n{\r\n    \/**\r\n     * the next object that needs to run \r\n     * @var ChainElement\r\n     *\/\r\n    protected $_successor = null;\r\n\r\n    \/**\r\n     * method for setting the next object that needs to be executed\r\n     * @param ChainElement $objSuccessor\r\n     *\/\r\n    public function setSuccessor(ChainElement $objSuccessor)\r\n    {\r\n        $this-&gt;_successor = $objSuccessor;\r\n    }\r\n\r\n    \/**\r\n     * getter for the next object that needs to be executed\r\n     * @return ChainElement\r\n     *\/\r\n    public function getSuccessor() \r\n    {\r\n        return $this-&gt;_successor;\r\n    }\r\n\r\n    \/**\r\n     * abstract function that every object part of the sequence\r\n     * needs to overwrite  \r\n     *\/\r\n    abstract function execute();\r\n\r\n    \/**\r\n     * method to determine if we have a successor and if we have \r\n     * call his execute method\r\n     *\/\r\n    public function executeSuccessor()\r\n    {\r\n        if(!is_null($this-&gt;_successor) &amp;&amp; is_object($this-&gt;_successor) === true)\r\n        {\r\n            $this-&gt;_successor-&gt;execute();\r\n        }\r\n    }\r\n}<\/pre>\n<p>As you can see, the <code>FilesFinder<\/code> class, the <code>XSLXParser<\/code> class and the <code>Statistics<\/code> class need to overwrite the abstract method <code>execute()<\/code> from <code>ChainElement<\/code>.<\/p>\n<p>Another requirement for this is that, at the end of each <code>execute()<\/code> method, the <code>executeSuccessor()<\/code> method should be called, in order to do the next part of the job.<\/p>\n<p>To explain even better, <code>objFinder<\/code> will make the call, at the end of <code>execute()<\/code> method, that will invoke the next object; the <code>objXLSXParser<\/code> will run its <code>execute()<\/code> method, that will invoke the objStatisctics&#8217;s <code>execute()<\/code> method.<\/p>\n<p>As a result of this approach, I can always add a new object in the sequence, without compromising the\u00a0existing code. For example, I can add an <code>objCleaner<\/code> (doesn&#8217;t matter what it does) at wherever in the sequence, the object will need to extend the <code>ChainElement<\/code> and overwrite the <code>execute()<\/code> method .<\/p>\n<p>As an addition to this classes, if you will ever use this, I suggest you make another class (mine is called <code>ChainParams<\/code>), that will implement the <code>Singleton<\/code> design pattern, which should hold the &#8220;communication&#8221; objects from one <code>ChainElement<\/code> to another.<\/p>\n<p>Hope you&#8217;ve \u00a0enjoyed the post!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today&#8217;s article is meant to show you how to go from plain-text tasks to a collection of classes that are [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[82],"tags":[175,184,194,196,199],"yst_prominent_words":[1388,1399,1398,1397,1396,1395,1394,1393,1392,1391,415,1387,1386,1351,1147,1025,1014,1013,426],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/490"}],"collection":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/comments?post=490"}],"version-history":[{"count":7,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/490\/revisions"}],"predecessor-version":[{"id":132725,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/490\/revisions\/132725"}],"wp:attachment":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/media?parent=490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/categories?post=490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/tags?post=490"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}