{"componentChunkName":"component---node-modules-gatsby-theme-medium-to-own-blog-src-templates-blog-post-js","path":"/on-the-anti-if-campaign-the-double-dispatch-service-locator-example/","result":{"data":{"site":{"siteMetadata":{"siteUrl":"https://javame.netlify.app","githubUrl":"https://github.com/aterreno/blog"}},"mdx":{"fields":{"slug":"/on-the-anti-if-campaign-the-double-dispatch-service-locator-example/"},"excerpt":"I had a good number of jokes and questions since the announcement of the  anti-if campaign . Do you want to remove all these if? What’s…","timeToRead":2,"frontmatter":{"title":"On the anti-if campaign, the double dispatch service locator example","description":"","categories":[],"date":"February 04, 2008","canonical_link":"https://javame.netlify.app//on-the-anti-if-campaign-the-double-dispatch-service-locator-example-75720bb637ef"},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"On the anti-if campaign, the double dispatch service locator example\",\n  \"description\": \"\",\n  \"date\": \"2008-02-04T00:00:00.000Z\",\n  \"categories\": [],\n  \"published\": true,\n  \"canonical_link\": \"https://javame.netlify.app//on-the-anti-if-campaign-the-double-dispatch-service-locator-example-75720bb637ef\",\n  \"redirect_from\": [\"/on-the-anti-if-campaign-the-double-dispatch-service-locator-example-75720bb637ef\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"I had a good number of jokes and questions since the announcement of the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://brainscrum.wordpress.com/2007/11/26/the-anti-if-campaign/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"anti-if campaign\"), \".\"), mdx(\"p\", null, \"Do you want to remove all these if? What\\u2019s wrong with the ifs?\"), mdx(\"p\", null, \"So, it\\u2019s better to clarify something.\"), mdx(\"p\", null, \"First of all it\\u2019s not about removing every single if, it\\u2019s about having a more flexible, maintainable and readable code.\"), mdx(\"p\", null, \"A long case (or if then else) statement can be difficult to read and follow, maintenance can be painful.\"), mdx(\"p\", null, \"The first category of if to get of rid of, the most immediate it\\u2019s the type based if.\"), mdx(\"p\", null, \"There is clear: something is wrong, the responsibility is not where the if is but in the class itself.\"), mdx(\"p\", null, \"So, an example.\"), mdx(\"p\", null, \"On a project (in a Domain Driven Architecture) we had a fairly long \\u201Cif type then, else if type then, etc\\u2026\\u201D\"), mdx(\"p\", null, \"The if chain was on different Tasks Types in a workflow engine.\"), mdx(\"p\", null, \"Let\\u2019s imagine that the workflow is an engine for a touch-less car wash system.\"), mdx(\"p\", null, \"So you have, for example:\"), mdx(\"p\", null, \"InsertCoinTask\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"2-StepHeatedPreSoakTask\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"HighPressureTouchFreeWashTask\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"Tire&WheelCleanerTask\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"HighPressureRinseTask and so on.\"), mdx(\"p\", null, \"Every task depends on the completion of a previous one and might need a run time configuration.\"), mdx(\"p\", null, \"So, the code was something like this:\"), mdx(\"p\", null, \"if (task is InsertCoinTask)\"), mdx(\"p\", null, \"{ Configure(task as InsertCoinTask) }\"), mdx(\"p\", null, \"else if (task is StepHeatedPreSoakTask) {\"), mdx(\"p\", null, \"Configure(task as StepHeatedPreSoakTask) }\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"\\u2026\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"Inside of a class called TaskServiceConfigurator, were for example a Configure method was implemented like:\"), mdx(\"p\", null, \"private Configure(Tire&WheelCleanerTask task)\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"{\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"task.TirePosition = touchFreeWashTask.LastCarPosition;\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"}\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"The different configure methods inside that class (then private!) were setting previous tasks settings, values and so on.\"), mdx(\"p\", null, \"So, pain points:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"The long if: you can easily forget to configure when adding your task to the workflow to add it there\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Private configuration methods: difficult to test, not only the configuration but also when testing the task itself\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Public setters on the tasks: since each task is configured inside the TaskServiceConfigurator all the setting came from there\")), mdx(\"p\", null, \"Solution to this has been a double dispatch.\"), mdx(\"p\", null, \"We added on the Task Interface a method Configure with the ITaskServiceConfigurator as a parameter, like this:\"), mdx(\"p\", null, \"ITask\\xA0\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"{\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"Configure(ITaskServiceConfigurator configurator)\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"}\"), mdx(\"p\", null, \"Tire&WheelCleanerTask is an ITask and the Configure implementation might look like:\"), mdx(\"p\", null, \"Configure(ITaskServiceConfigurator configurator)\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"{\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"tirePosition = configurator.LastCarPosition;\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"\\u2026\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"}\"), mdx(\"p\", null, \"The above example probably is too stupid, but the key point is that the LastCarPosition depends on other task (performed or not) it\\u2019s really a run-time configuration, a real time dependency between tasks.\"), mdx(\"p\", null, \"I found easier to test the tasks, passing a stubbed configuration and the configuration itself had a definitely better code coverage.\"), mdx(\"p\", null, \"Any better solution to this code redesign is more than welcome.\"), mdx(\"p\", null, \"(Task names are taken from this page: \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://www.autec-carwash.com/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"http://www.autec-carwash.com/\"), \"\\xA0:-))\"));\n}\n;\nMDXContent.isMDXComponent = true;"},"allWebMentionEntry":{"nodes":[]}},"pageContext":{"id":"81efbe0b-1741-5701-9db2-d2732c419792","previous":{"id":"f65bab9a-99e0-506b-87b1-9f35d9a6f684","fields":{"slug":"/pomodoro-technique-goes-international/","published":true},"frontmatter":{"redirect_from":["/pomodoro-technique-goes-international-d92a442d7113"],"redirect_to":null,"title":"pomodoro technique goes international"}},"next":{"id":"f2d1e297-b8d5-51f7-9f43-17d062e1b4af","fields":{"slug":"/how-do-you-build-your-projects/","published":true},"frontmatter":{"redirect_from":["/how-do-you-build-your-projects-b5a2dd32336"],"redirect_to":null,"title":"How do you build your projects?"}},"permalink":"https://javame.netlify.app/on-the-anti-if-campaign-the-double-dispatch-service-locator-example/","themeOptions":{"plugins":[],"config":{"title":"Antonio Terreno","description":"Antonio Terreno's blog archive","shortBio":"","bio":"Principal Consultant at Equal Experts","author":"Antonio Terreno","githubUrl":"https://github.com/aterreno/blog","siteUrl":"https://javame.netlify.app/","social":{"twitter":"javame","medium":"","facebook":"","github":"aterreno","linkedin":"antonioterreno","instagram":"tritonitri"},"goatCounterCode":null}}}},"staticQueryHashes":["4131332129","645483741"]}