{"id":1403,"date":"2024-09-03T00:00:00","date_gmt":"2024-09-02T22:00:00","guid":{"rendered":"https:\/\/demo.sidekick.be\/itenium\/kiss-decorators\/"},"modified":"2025-11-28T13:31:42","modified_gmt":"2025-11-28T12:31:42","slug":"kiss-decorators","status":"publish","type":"post","link":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/","title":{"rendered":"KISS and Decorators"},"content":{"rendered":"<h1 id=\"the-implementation\">The Implementation<\/h1>\n<p>A simplified version of the code would be:<\/p>\n<pre><code class=\"language-c#\">public interface IDoer\n{\n  void DoIt();\n}\n\n\npublic class Doer : IDoer\n{\n  public void DoIt()\n  {\n    \/\/ Actual Business Logic here\n    \/\/ But... Only happening for\n    \/\/ one case?\n  }\n}\n<\/code><\/pre>\n<p>And then another implementation, a decorator:<\/p>\n<pre><code class=\"language-c#\">public class LoopingDoer : IDoer\n{\n  private readonly IDoer _inner;\n\n  public LoopingDoer(IDoer inner)\n  {\n    _inner = inner;\n  }\n\n  public void DoIt()\n  {\n    \/\/ We were looping over something\n    \/\/ that made sense here, not just\n    \/\/ this for loop:\n    for (int i = 0; i &lt; 10; i++)\n    {\n      _inner.DoIt();\n    }\n  }\n}\n<\/code><\/pre>\n<h2 id=\"the-magic\">The Magic<\/h2>\n<p>To make it all work, the \u201cmagic\u201d \u2728\ud83e\udd84 <a href=\"https:\/\/autofac.org\/\">Autofac<\/a> wiring:<\/p>\n<pre><code class=\"language-c#\">var containerBuilder = new ContainerBuilder();\ncontainerBuilder.RegisterType&lt;Doer&gt;().As&lt;IDoer&gt;();\ncontainerBuilder.RegisterDecorator&lt;LoopingDoer, IDoer&gt;();\n<\/code><\/pre>\n<p>Probably there is no one in your team who knows what this does exactly and they\u2019d have to look at a completely different location (app startup) before it makes any sense.<\/p>\n<h1 id=\"keep-it-simple\">Keep it Simple<\/h1>\n<p>After removing the decorator and the Autofac registration, we ended up with:<\/p>\n<pre><code class=\"language-c#\">public class Doer : IDoer\n{\n  public void DoIt()\n  {\n    for (int i = 0; i &lt; 10; i++)\n    {\n      \/\/ Business Logic here\n\n      \/\/ New UseCase example\n      if (i == 0)\n      {\n        \/\/ UserStory implementation here\n      }\n    }\n  }\n}\n<\/code><\/pre>\n<p>Which is less code and much easier to understand, and it also made it easy, trivial even, to add the required change.<\/p>\n<h1 id=\"decorator-pattern\">Decorator Pattern<\/h1>\n<p>An excellent design pattern to adhere to the Open\/Closed Principle: Add functionality without modification.<\/p>\n<h2 id=\"intent\">Intent<\/h2>\n<p>It\u2019s one of the Structural Patterns from the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Design_Patterns\">GoF<\/a>.<\/p>\n<p class=\"notice--info\">Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.<\/p>\n<h2 id=\"applicability\">Applicability<\/h2>\n<p>When extension by subclassing is impractical because a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination.<\/p>\n<h2 id=\"consequences\">Consequences<\/h2>\n<p><em>More flexible than static inheritance<\/em>:<br \/> Responsibilities can be added and removed at run-time whereas inheritance requires creating a new class for each new combination.<\/p>\n<p><em>Avoids feature-laden classes<\/em>:<br \/> Instead of trying to support all features in a complex, customizable class, you define a simple class and add functionality incrementally with Decorator objects.<\/p>\n<p><em>Lots of little objects<\/em>:<br \/> The objects differ only in the way they are interconnected. Although easy to customize, <strong>you can no longer follow the execution flow from the source code alone and they can be hard to debug<\/strong>.<\/p>\n<h2 id=\"known-uses\">Known Uses<\/h2>\n<p>I\/O Streams are typically implemented using Decorators and they are a really good fit for the pattern too!<\/p>\n<pre><code class=\"language-c#\">byte[] buffer = \"test\"u8.ToArray();\n\nusing (FileStream fileStream = new(path, FileMode.Create, FileAccess.Write))\nusing (BufferedStream bufferedStream = new(fileStream))\nusing (GZipStream gzipStream = new(bufferedStream, CompressionMode.Compress))\n{\n  gzipStream.Write(buffer, 0, buffer.Length);\n}\n<\/code><\/pre>\n<p>We cleanly avoid having to create a <code>GZipBufferedFileStream<\/code> for this particular case. Having to write all these implementations would result in said explosion of subclasses and also make it difficult to keep things DRY!<\/p>\n<h1 id=\"conclusion\">Conclusion<\/h1>\n<p>Using the decorator pattern instead of writing a simple <code>foreach<\/code> loop; it\u2019s just adding <a href=\"https:\/\/en.wikipedia.org\/wiki\/No_Silver_Bullet\">accidental complexity<\/a>.<\/p>\n<p>You end up with the consequences of the design pattern (hard to learn and debug) without any of the benefits.<\/p>\n<p>Keep It Simple.<\/p>\n<h1>Extras<\/h1>\n<p><b>Stuff that came into being during the making of this post<\/b><\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/itenium-be\/KISS-Decorators\">The code from this blog post as xUnit tests<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I picked up a UserStory to make a small adjustment.<\/p>\n<p>The story was simple enough as was the required change but\u2026 Looking at the code, how was it supposed to work? It looked like it just.. Shouldn\u2019t\u2026<\/p>\n<p>Took some time but I found out, the behavior of the software was defined in the IOC registration, at startup, with Autofac.<\/p>\n","protected":false},"author":1,"featured_media":1987,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[27],"tags":[10],"class_list":["post-1403","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-design","tag-war-story"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>KISS and Decorators - Itenium<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"KISS and Decorators - Itenium\" \/>\n<meta property=\"og:description\" content=\"I picked up a UserStory to make a small adjustment.The story was simple enough as was the required change but\u2026 Looking at the code, how was it supposed to work? It looked like it just.. Shouldn\u2019t\u2026Took some time but I found out, the behavior of the software was defined in the IOC registration, at startup, with Autofac.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/\" \/>\n<meta property=\"og:site_name\" content=\"Itenium\" \/>\n<meta property=\"article:published_time\" content=\"2024-09-02T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-28T12:31:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png\" \/>\n\t<meta property=\"og:image:width\" content=\"360\" \/>\n\t<meta property=\"og:image:height\" content=\"300\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Usdevelop\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Usdevelop\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/\",\"name\":\"KISS and Decorators - Itenium\",\"isPartOf\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png\",\"datePublished\":\"2024-09-02T22:00:00+00:00\",\"dateModified\":\"2025-11-28T12:31:42+00:00\",\"author\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022\"},\"breadcrumb\":{\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png\",\"contentUrl\":\"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png\",\"width\":360,\"height\":300,\"caption\":\"kiss\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/demo.sidekick.be\/itenium\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"KISS and Decorators\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#website\",\"url\":\"https:\/\/demo.sidekick.be\/itenium\/\",\"name\":\"Itenium\",\"description\":\"We build software. We build careers.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/demo.sidekick.be\/itenium\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022\",\"name\":\"Usdevelop\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g\",\"caption\":\"Usdevelop\"},\"sameAs\":[\"https:\/\/demo.sidekick.be\/itenium\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"KISS and Decorators - Itenium","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"en_US","og_type":"article","og_title":"KISS and Decorators - Itenium","og_description":"I picked up a UserStory to make a small adjustment.The story was simple enough as was the required change but\u2026 Looking at the code, how was it supposed to work? It looked like it just.. Shouldn\u2019t\u2026Took some time but I found out, the behavior of the software was defined in the IOC registration, at startup, with Autofac.","og_url":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/","og_site_name":"Itenium","article_published_time":"2024-09-02T22:00:00+00:00","article_modified_time":"2025-11-28T12:31:42+00:00","og_image":[{"width":360,"height":300,"url":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png","type":"image\/png"}],"author":"Usdevelop","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Usdevelop","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/","url":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/","name":"KISS and Decorators - Itenium","isPartOf":{"@id":"https:\/\/demo.sidekick.be\/itenium\/#website"},"primaryImageOfPage":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage"},"image":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage"},"thumbnailUrl":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png","datePublished":"2024-09-02T22:00:00+00:00","dateModified":"2025-11-28T12:31:42+00:00","author":{"@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022"},"breadcrumb":{"@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#primaryimage","url":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png","contentUrl":"https:\/\/demo.sidekick.be\/itenium\/wp-content\/uploads\/2025\/11\/kiss-decorators.png","width":360,"height":300,"caption":"kiss"},{"@type":"BreadcrumbList","@id":"https:\/\/demo.sidekick.be\/itenium\/blog\/design\/kiss-decorators\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/demo.sidekick.be\/itenium\/"},{"@type":"ListItem","position":2,"name":"KISS and Decorators"}]},{"@type":"WebSite","@id":"https:\/\/demo.sidekick.be\/itenium\/#website","url":"https:\/\/demo.sidekick.be\/itenium\/","name":"Itenium","description":"We build software. We build careers.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/demo.sidekick.be\/itenium\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/6ab401ce01e858184ee4a8667fe0f022","name":"Usdevelop","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/demo.sidekick.be\/itenium\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cc8cf9b9e9d5bbe7e8d247907cc9ac8457bbfa2854b52eaddf6529adfe88ceab?s=96&d=mm&r=g","caption":"Usdevelop"},"sameAs":["https:\/\/demo.sidekick.be\/itenium"]}]}},"_links":{"self":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1403","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/comments?post=1403"}],"version-history":[{"count":3,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1403\/revisions"}],"predecessor-version":[{"id":2260,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/posts\/1403\/revisions\/2260"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/media\/1987"}],"wp:attachment":[{"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/media?parent=1403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/categories?post=1403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.sidekick.be\/itenium\/wp-json\/wp\/v2\/tags?post=1403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}