
{"id":315,"date":"2015-11-26T01:40:23","date_gmt":"2015-11-26T00:40:23","guid":{"rendered":"http:\/\/serverdude.dk\/?p=315"},"modified":"2015-11-26T01:40:23","modified_gmt":"2015-11-26T00:40:23","slug":"how-to-refactor-a-refactored-switchcase-statement","status":"publish","type":"post","link":"https:\/\/serverdude.dk\/?p=315","title":{"rendered":"How to refactor a refactored switch\/case statement"},"content":{"rendered":"<p>When good intentions go slightly wrong<\/p>\n<p>For some odd reason I picked up a link to DZONE on &#8220;How to refactor a switch\/case statement&#8221; &#8211; the link <a href=\"https:\/\/dzone.com\/articles\/how-to-refactor-a-switchcase-statement\">https:\/\/dzone.com\/articles\/how-to-refactor-a-switchcase-statement<\/a> is now defunct, I&#8217;m not sure why. Anyway, Gianluca Tomasino, the original author still has the article on his <a href=\"http:\/\/gianlucatomasino.tumblr.com\/post\/116422860987\/how-to-refactor-a-switchcase-statement\">blog<\/a>.<\/p>\n<p>So I read through this &#8211; I know I dislike switch\/case jump tables, though not as much as I hate if-else-if &#8211; or as I like to reminisce Sid Meier&#8217;s Pirates! and call it the &#8220;evil El Sif&#8221;<\/p>\n<p>Gianluca is quite right, that one option would be to use the <a href=\"http:\/\/www.oodesign.com\/strategy-pattern.html\">Strategy   pattern<\/a>, but then goes on to show how not to implement this pattern by adding a method for each of the enums, then tie a specific implementation inside the enum ending up with a less readable and less maintainable code.<\/p>\n<p>The enum part is right &#8211; eliminate the magic strings, define the different types.<\/p>\n<p>The strategy interface definition is wrong &#8211; the name &#8220;HasStrategies&#8221; does not convey any useful information. The 2 methods bind concrete enums to an interface, 1 abstract method, e.g. &#8216;execute&#8217; should be sufficient. Then the specific strategy is pushed inside the enums themselves. Enums should not care for whichever strategies you have for them, thus that sort of coupling is not wanted.<\/p>\n<p>In the Decider class, we now define the specific strategy to use, which sort of defies the purpose of extracting the code from a switch &#8211; the specific class will now have 2 reasons for change:<\/p>\n<ol>\n<li>Change to the strategy<\/li>\n<li>Change to the enum definitions<\/li>\n<\/ol>\n<p>&#8220;A class should have one, and only one reason to change.&#8221; That is the intent of the <a href=\"http:\/\/www.oodesign.com\/single-responsibility-principle.html\">Single   Responsibility Principle<\/a><\/p>\n<p>If we add another value to the enums, then we need to change the Decider implementation as well, that is contrary to the <a href=\"http:\/\/www.oodesign.com\/open-close-principle.html\">Open   Close Principle<\/a>. From the looks of it, we have to change the enums (well, that&#8217;s a given), the strategy, and the decider implementation.<\/p>\n<p>What I&#8217;d recommend:<\/p>\n<p>Define the strategy interface using only one method<\/p>\n<pre style=\"background-color:#ffffff;color:#000000;font-family:'Courier New';font-size:9,0pt;\"><span style=\"color:#000080;font-weight:bold;\">interface <\/span>Strategy {\r\n    String execute();\r\n}<\/pre>\n<p>Simply define the values<\/p>\n<pre style=\"background-color:#ffffff;color:#000000;font-family:'Courier New';font-size:9,0pt;\"><span style=\"color:#000080;font-weight:bold;\">enum <\/span>Values {\r\n    <span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">PIPPO<\/span>, <span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">PLUTO<\/span>;\r\n}<\/pre>\n<p>Implement the strategies for each of the values, and add them to an EnumMap<\/p>\n<pre style=\"background-color:#ffffff;color:#000000;font-family:'Courier New';font-size:9,0pt;\"><span style=\"color:#000080;font-weight:bold;\">class <\/span>ValueStrategies {\r\n    <span style=\"color:#000080;font-weight:bold;\">final static <\/span>EnumMap&lt;Values, Strategy&gt; <span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">MAP <\/span>=\u00c2\u00a0\r\n<span style=\"color:#000080;font-weight:bold;\">             new <\/span>EnumMap&lt;Values, Strategy&gt;(Values.<span style=\"color:#000080;font-weight:bold;\">class<\/span>);<\/pre>\n<pre style=\"background-color:#ffffff;color:#000000;font-family:'Courier New';font-size:9,0pt;\">    <span style=\"color:#000080;font-weight:bold;\">static <\/span>{\r\n        <span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">MAP<\/span>.put(Values.<span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">PIPPO<\/span>, <span style=\"color:#000080;font-weight:bold;\">new <\/span>Strategy() {\r\n            <span style=\"color:#808000;\">@Override\r\n<\/span><span style=\"color:#808000;\">            <\/span><span style=\"color:#000080;font-weight:bold;\">public <\/span>String execute() {\r\n                <span style=\"color:#000080;font-weight:bold;\">return <\/span><span style=\"color:#008000;font-weight:bold;\">\"methodA\"<\/span>;\r\n            }\r\n        });\r\n        <span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">MAP<\/span>.put(Values.<span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">PLUTO<\/span>, <span style=\"color:#000080;font-weight:bold;\">new <\/span>Strategy() {\r\n            <span style=\"color:#808000;\">@Override\r\n<\/span><span style=\"color:#808000;\">            <\/span><span style=\"color:#000080;font-weight:bold;\">public <\/span>String execute() {\r\n                <span style=\"color:#000080;font-weight:bold;\">return <\/span><span style=\"color:#008000;font-weight:bold;\">\"methodB\"<\/span>;\r\n            }\r\n        });\r\n    }\r\n    <span style=\"color:#000080;font-weight:bold;\">static <\/span>Strategy get(Values value) {\r\n        <span style=\"color:#000080;font-weight:bold;\">return <\/span><span style=\"color:#660e7a;font-weight:bold;font-style:italic;\">MAP<\/span>.get(value);\r\n    }\r\n}<\/pre>\n<p>Implement the decider using these elements:<\/p>\n<pre style=\"background-color:#ffffff;color:#000000;font-family:'Courier New';font-size:9,0pt;\"><span style=\"color:#000080;font-weight:bold;\">public class <\/span>AltDecider <span style=\"color:#000080;font-weight:bold;\">implements <\/span>Decider {\r\n\r\n    <span style=\"color:#808000;\">@Override\r\n<\/span><span style=\"color:#808000;\">    <\/span><span style=\"color:#000080;font-weight:bold;\">public <\/span>String call(String which) {\r\n        Values value = Values.<span style=\"font-style:italic;\">valueOf<\/span>(which.toUpperCase());\r\n        <span style=\"color:#000080;font-weight:bold;\">return <\/span>ValueStrategies.<span style=\"font-style:italic;\">get<\/span>(value).execute();\r\n    }\r\n\r\n}<\/pre>\n<p>Well, the mapping from a primitive to the enum should not take place inside the method, the Decider interface should be modified to fix such hacks, if the String, which, is null or does not represent a Value, then a NullPointerException and IllegalArgumentException respectively will be thrown from the Value conversion.<\/p>\n<p>The names are still not meaningful.<\/p>\n<p>With this solution a new enum value will require a change to Values and the implementation for its strategy inside the ValueStrategies.<\/p>\n<p>If re-use of the strategy implementations were of concern, then naturally they should be implemented in their own classes and not as anonymous values inside the map.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When good intentions go slightly wrong For some odd reason I picked up a link to DZONE on &#8220;How to refactor a switch\/case statement&#8221; &#8211; the link https:\/\/dzone.com\/articles\/how-to-refactor-a-switchcase-statement is now defunct, I&#8217;m not sure why. Anyway, Gianluca Tomasino, the original author still has the article on his blog. So I read through this &#8211; I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,10],"tags":[],"class_list":["post-315","post","type-post","status-publish","format-standard","hentry","category-programming","category-software-development"],"_links":{"self":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=315"}],"version-history":[{"count":4,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/315\/revisions"}],"predecessor-version":[{"id":319,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/315\/revisions\/319"}],"wp:attachment":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}