{"id":1234,"date":"2012-07-08T11:43:07","date_gmt":"2012-07-08T09:43:07","guid":{"rendered":"http:\/\/doanduyhai.wordpress.com\/?p=1234"},"modified":"2012-07-08T11:43:07","modified_gmt":"2012-07-08T09:43:07","slug":"design-pattern-the-pipeline","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=1234","title":{"rendered":"Design Pattern: the Pipeline"},"content":{"rendered":"<p>Today we&#8217;ll have a look into the <strong>Pipeline<\/strong> pattern, a design pattern inspired from the original <strong>Chain of Responsibility<\/strong> pattern by the GoF<\/p>\n<p><!--more--><\/p>\n<h1>I The Chain Of Responsibility<\/h1>\n<p>Basically the <strong>Chain of Responsibility<\/strong> defines the following actors:<\/p>\n<ul>\n<li><strong>Command<\/strong>: the object to be processed<\/li>\n<li><strong>Handler<\/strong>: an object handling interface. There can be many handlers in the chain. This interface defines 2 methods\n<ul>\n<li><em>setSuccessor(Handler successor)<\/em>: defines the next successor in the chain to pass the command to<\/li>\n<li><em>handle(Command command)<\/em>: handle the command<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p> The goal of this pattern is to decouple the <strong>Command<\/strong> object from its processing chain. A new Handler can be easily added to the chain without breaking any existing code.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/chainofresponsibility2.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/chainofresponsibility2.png\" alt=\"ChainOfResponsibility\" title=\"ChainOfResponsibility\" width=\"537\" height=\"377\" class=\"aligncenter size-full wp-image-1310\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/chainofresponsibility2.png 537w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/chainofresponsibility2-300x211.png 300w\" sizes=\"(max-width: 537px) 100vw, 537px\" \/><\/a><\/p>\n<p>The disadvantage of this design is the number of operations needed when a new handler is added into the pipeline. You need to break an existing successor\/predecessor link, insert the new handler then relink it to the chain. It is very similar to a linked list. If a successor link is badly set accidentally, the whole chain is broken.<\/p>\n<p> In the context of dependency injection within a container (JEE or Spring) it is not easier either. 3 operations are required: <\/p>\n<ul>\n<li>unlinking an existing handler<\/li>\n<li>relinking the new handler with its successor<\/li>\n<li>relinking the existing predecessor to the new handler<\/li>\n<\/ul>\n<p>All this is quite error-prone indeed.<\/p>\n<p>&nbsp;<\/p>\n<h1>II The Pipeline<\/h1>\n<p>The original need for the <strong>Pipeline<\/strong> pattern comes from my <a href=\"https:\/\/github.com\/doanduyhai\/tatami\" title=\"https:\/\/github.com\/doanduyhai\/tatami\" target=\"_blank\">Tatami<\/a> project.<\/p>\n<p> When an user posts a new Tweet, it needs to be processed by several services:<\/p>\n<ul>\n<li><strong>contentValidationService<\/strong>: to limit the tweet size to N characters, including the URL shortening<\/li>\n<li><strong>xssEncodingService<\/strong>: encode the tweet content to prevent XSS (cross-site scripting) attacks<\/li>\n<li><strong>tweetService<\/strong>: simply persist the tweet in the repository<\/li>\n<li><strong>userlineService<\/strong>: put the tweet in the current user line<\/li>\n<li><strong>timelineService<\/strong>: put the tweet in the current user timeline<\/li>\n<li><strong>taglineService<\/strong>: put the tweet in the appropriate taglines if it contains tags<\/li>\n<li><strong>mentionlineService<\/strong>: put the tweet in the timeline of any mentioned users<\/li>\n<li><strong>contactsService<\/strong>: spread the tweet to the timeline of all followers of current user<\/li>\n<\/ul>\n<p> As you can see, the tweet processing services resemble quite a lot to a pipeline of processors. And more importantly the processing order does really matter. <strong>xssEncodingService<\/strong> should be placed before the <strong>tweetService<\/strong> (responsible of the persistence in repository). Similarly, the <strong>tweetService<\/strong> needs to be placed before any line related service because in a multi-threaded environment, the tweet needs to be persisted before any user could read it.<\/p>\n<p> The <strong>Pipeline<\/strong> pattern meet those requirements but is more flexible than the <strong>Chain Of Responsibility<\/strong> pattern. It defines the following actors:<\/p>\n<ul>\n<li><strong>Command<\/strong>: command object to be process. A tweet in our example<\/li>\n<li><strong>PipelineManager<\/strong>: central class of the pattern. Define the following attribute and method\n<ul>\n<li><em>handlers<\/em>: list (ordered) of <strong>Handlers<\/strong><\/li>\n<li><em>doPipeline(<strong>Command<\/strong> object)<\/em>: execute the processing pipeline<\/li>\n<\/ul>\n<\/li>\n<li><strong>Handler<\/strong>: an interface defining the <em>process(<strong>Command<\/strong> object)<\/em> method\n<\/li>\n<\/ul>\n<p>Below is the formal UML class diagram:<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/pipeline.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/pipeline.png\" alt=\"Pipeline\" title=\"Pipeline\" width=\"530\" height=\"361\" class=\"aligncenter size-full wp-image-1316\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/pipeline.png 530w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/pipeline-300x204.png 300w\" sizes=\"(max-width: 530px) 100vw, 530px\" \/><\/a><\/p>\n<p>The major difference with the <strong>Chain Of Responsibility<\/strong> pattern is the introduction of the <strong>PipelineManager<\/strong> actor. The flexibility of the <strong>Pipeline<\/strong> pattern comes from the fact that at any time, a new <strong>Handler<\/strong> can be injected into the pipeline through the <strong>PipelineManager<\/strong> <\/p>\n<p>Below is a sample Spring XML configuration illustrating dependency injection<\/p>\n<pre class=\"brush: xml; highlight: [1]; title: ; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;bean id=&amp;quot;tweetPipelineManager&amp;quot; class=&amp;quot;fr.ippon.tatami.service.pipeline.tweet.TweetPipelineManager&amp;quot;&amp;gt;\n\t&amp;lt;property name=&amp;quot;tweetHandlers&amp;quot;&amp;gt;\n\t\t&amp;lt;list&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;tweetContentValidationService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;xssEncodingService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;tweetService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;userlineService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;timelineService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;taglineService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;mentionlineService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;contactsService&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;retweetService&amp;quot;\/&amp;gt;\n\t\t&amp;lt;\/list&amp;gt;\n\t&amp;lt;\/property&amp;gt;\n&amp;lt;\/bean&amp;gt;\n<\/pre>\n<p>Adding a new <em>tweetHandler<\/em> is as easy as adding a new entry in the list of handlers. Furthermore, since the <em>handlers<\/em> collection is a <strong>List<\/strong>, <strong>the order is preserved<\/strong>.<\/p>\n<p>&nbsp;<br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;ll have a look into the Pipeline pattern, a design pattern inspired from the original Chain of Responsibility pattern by the GoF<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,6],"tags":[],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1234"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1234"}],"version-history":[{"count":0,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1234\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}