{"id":25929,"date":"2017-08-16T15:24:04","date_gmt":"2017-08-16T15:24:04","guid":{"rendered":"https:\/\/blog.jetbrains.com\/idea\/?p=15707"},"modified":"2017-09-20T10:56:28","modified_gmt":"2017-09-20T10:56:28","slug":"code-smells-deeply-nested-code","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/ja\/idea\/2017\/08\/code-smells-deeply-nested-code","title":{"rendered":"Code Smells: Deeply Nested Code"},"content":{"rendered":"<p>Or: I wants all your data, give it to me\u2026 my precious\u2026.<\/p>\n<p><em>This is part of a series\u00a0investigating\u00a0code that\u00a0looks suspicious\u00a0(&#8220;code smells&#8221;),\u00a0and exploring possible alternatives.<\/em><\/p>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/08\/code-smells-null\/\" rel=\"bookmark\">Code Smells: Null<\/a><\/li>\n<li><strong>Code Smells: Deeply Nested Code<\/strong><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/08\/code-smells-iteration\/\">Code Smells: Iteration<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/08\/code-smells-mutation\/\">Code Smells: Mutation<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/09\/code-smells-multi-responsibility-methods\/\">Code Smells:\u00a0Multi-Responsibility Methods<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/09\/code-smells-if-statements\/\">Code Smells: If Statements<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/idea\/2017\/09\/code-smells-too-many-problems\/\">Code Smells: Too Many Problems<\/a><\/li>\n<\/ul>\n<p>Continuing the series of <a href=\"https:\/\/blog.jetbrains.com\/idea\/tag\/code-smells\/\">code smells<\/a> and what do about them, in this post I examine some fairly innocent looking code that defies the obvious refactoring.\u00a0 Although the code example itself is fairly trivial, it&#8217;s actually a symptom of a problem found again and again in this particular project: deep nesting of code. This can be for loops, if statements, even lambda expressions or inner classes, or combinations of all of the above.<\/p>\n<p><!--more--><\/p>\n<p><strong>The Smell: Deeply Nested Code<\/strong><\/p>\n<p>The code I stumbled over was a double for loop with an inner if statement.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0 public MappedField getMappedField(final String storedName) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (final MappedField mf : persistenceFields) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (final String n : mf.getLoadNames()) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (storedName.equals(n)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return mf;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return null;\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>What&#8217;s wrong with this code?\u00a0 It&#8217;s OK to read, if we forgive the single-character variable names, and are used to working in a procedural way &#8211; we&#8217;re looking at all the fields, and then for each field we look at all the names, and if a name matches the name we&#8217;re looking for, we return that field.\u00a0 Simple.<\/p>\n<p><strong>Solution 1: Java 8 to the rescue<\/strong><\/p>\n<p>The lovely <a href=\"http:\/\/wiki.c2.com\/?ArrowAntiPattern\" target=\"_blank\" rel=\"noopener\">arrow\u00a0shape of the code<\/a> here is the bit that looks suspicious. \u00a0I&#8217;ve shown in previous <a href=\"https:\/\/blog.jetbrains.com\/idea\/2016\/12\/intellij-idea-inspection-settings-for-refactoring-to-java-8\/\">blogs<\/a> and <a href=\"https:\/\/youtu.be\/2xOtyGUTpQU\" target=\"_blank\" rel=\"noopener\">talks<\/a> that nested for\/if statements can often be replaced with\u00a0Java 8 Streams, and this frequently gives better readability.\u00a0 I was wondering why IntelliJ IDEA doesn&#8217;t suggest this particular code can be collapsed into a Stream operation, seems like maybe\u00a0<a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/util\/stream\/Stream.html#flatMap-java.util.function.Function-\" target=\"_blank\" rel=\"noopener\">flatMap<\/a>\/<a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/util\/stream\/Stream.html#findFirst--\" target=\"_blank\" rel=\"noopener\">findFirst<\/a>\u00a0could be the answer. But it&#8217;s not that simple. I tried crafting the correct expression without automagic help from the IDE, and came up with:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">Optional&lt;String&gt; found = persistenceFields.stream()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.flatMap(mappedField -&gt; mappedField.getLoadNames().stream())\r\n                                  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .filter(storedName::equals)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.findFirst();<\/pre>\n<p>Well, that&#8217;s no good. I want to return the <code>mappedField<\/code> that contains the name, not an <code>Optional<\/code> containing the name that I found. And I can&#8217;t get to <code>mappedField<\/code> later in the Stream. The best I can do is:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">persistenceFields.stream()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.filter(mappedField -&gt; {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0        for (String name : mappedField.getLoadNames()) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (storedName.equals(name)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0    return false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0})\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.findFirst()<\/pre>\n<p>Urgh. Nasty.<\/p>\n<p><strong>Solution 2: Better Encapsulation<\/strong><\/p>\n<p>What\u2019s the real problem here?\u00a0 It seems like the original code is reaching deep inside another object, stealing all its data, riffling through it and then only caring about the top level object.\u00a0 Removing the loop syntax, what you have is effectively:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">if (getPersistenceFields().get(0).getLoadNames().get(0).equals(storedName))\r\n\u00a0\u00a0\u00a0 return true;<\/pre>\n<p>This what the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Law_of_Demeter\" target=\"_blank\" rel=\"noopener\">Law of Demeter<\/a> warns us against, therefore suggests to me we consider a <a href=\"https:\/\/martinfowler.com\/bliki\/TellDontAsk.html\" target=\"_blank\" rel=\"noopener\">tell-don&#8217;t-ask approach<\/a>.\u00a0 Wouldn&#8217;t it be prettier to ask <code>mappedField<\/code> if one of its names matched the name we wanted?<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (final MappedField mf : persistenceFields) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (mf.hasName(storedName)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return mf;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/pre>\n<p>The other for loop that loops over the names is moved inside the <code>MappedField<\/code> class, so only this class needs to understand the internals of how these names are stored.\u00a0 Let\u2019s step through one way of performing this refactoring.\u00a0 There&#8217;s more than one approach of course, this is just one example.<\/p>\n<p>Firstly, extract the inner loop to a separate method.\u00a0 In this case, let&#8217;s call it <code>hasName<\/code>:<\/p>\n<div id=\"attachment_15718\" style=\"width: 1664px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-01ExtractMethod-2.png\" rel=\"attachment wp-att-15718\"><img aria-describedby=\"caption-attachment-15718\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15718\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-01ExtractMethod-2.png\" alt=\"Extract Method hasName\" width=\"1654\" height=\"654\" \/><\/a><\/p>\n<p id=\"caption-attachment-15718\" class=\"wp-caption-text\">Extract Method hasName<\/p>\n<\/div>\n<p>The extracted method doesn&#8217;t compile, but that&#8217;s OK because I wanted to change the method signature anyway &#8211; I want the method to return true if the name matches one of the <code>MappedField<\/code>&#8216;s names, false otherwise.<\/p>\n<div id=\"attachment_15714\" style=\"width: 1290px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-2ChangeMethodSignature-2.gif\" rel=\"attachment wp-att-15714\"><img aria-describedby=\"caption-attachment-15714\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15714\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-2ChangeMethodSignature-2.gif\" alt=\"Change method signature to return a boolean\" width=\"1280\" height=\"720\" \/><\/a><\/p>\n<p id=\"caption-attachment-15714\" class=\"wp-caption-text\">Change method signature to return a boolean<\/p>\n<\/div>\n<p>Now I want to actually use this return value in the original method<\/p>\n<div id=\"attachment_15715\" style=\"width: 1290px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-3UseBooleanValue-2.gif\" rel=\"attachment wp-att-15715\"><img aria-describedby=\"caption-attachment-15715\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15715\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-3UseBooleanValue-2.gif\" alt=\"Use the boolean value returned\" width=\"1280\" height=\"720\" \/><\/a><\/p>\n<p id=\"caption-attachment-15715\" class=\"wp-caption-text\">Use the boolean value returned<\/p>\n<\/div>\n<p>The code compiles now and behaves the same way as the original.\u00a0 Now I just need to move the <code>hasName<\/code> method into the <code>MappedField<\/code> class.<\/p>\n<div id=\"attachment_15716\" style=\"width: 1290px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-4MoveMethod-2.gif\" rel=\"attachment wp-att-15716\"><img aria-describedby=\"caption-attachment-15716\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15716\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-4MoveMethod-2.gif\" alt=\"Move method into MappedClass\" width=\"1280\" height=\"720\" \/><\/a><\/p>\n<p id=\"caption-attachment-15716\" class=\"wp-caption-text\">Move method into MappedClass<\/p>\n<\/div>\n<p>So now the <code>MappedField<\/code> has the <code>hasName<\/code> method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0 public boolean hasName(String storedName) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (final String name : getLoadNames()) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (storedName.equals(name)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return true;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return false;\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>\u2026and the class containing the <code>getMappedField<\/code> method (<code>MappedClass<\/code>) no longer needs to know the internals of how the <code>MappedField<\/code> stores its names, or even that it can have more than one name.<\/p>\n<p><strong>Optional extra step: Java 8<\/strong><\/p>\n<p>If you so wish, both of these methods can now use Java 8 syntax. In the case of <code>hasName<\/code>, this is more descriptive too, it states we only care if any of the names matches the given one.<\/p>\n<div id=\"attachment_15717\" style=\"width: 1034px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-5Java8NameMatches.png\" rel=\"attachment wp-att-15717\"><img aria-describedby=\"caption-attachment-15717\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15717\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-5Java8NameMatches.png\" alt=\"Java 8 Streams version of hasName\" width=\"1024\" height=\"234\" \/><\/a><\/p>\n<p id=\"caption-attachment-15717\" class=\"wp-caption-text\">The\u00a0<code>hasName<\/code> method can be converted to use Java 8 Streams<\/p>\n<\/div>\n<p>We end up with:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0 public boolean hasName(String storedName) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return getLoadNames().stream()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .anyMatch(storedName::equals);\r\n\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>Meanwhile, <code>getMappedField<\/code> can also benefit from Java 8:<\/p>\n<div id=\"attachment_15712\" style=\"width: 1034px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-6Java8GetMappedField.png\" rel=\"attachment wp-att-15712\"><img aria-describedby=\"caption-attachment-15712\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-15712\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2017\/08\/idea-6Java8GetMappedField.png\" alt=\"Java 8 version of getMappedField\" width=\"1024\" height=\"271\" \/><\/a><\/p>\n<p id=\"caption-attachment-15712\" class=\"wp-caption-text\">The\u00a0getMappedField method can be converted to use Java 8 Streams too<\/p>\n<\/div>\n<p>The final code for <code>getMappedField<\/code> looks more like I wanted the first time I saw it:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0 public MappedField getMappedField(final String storedName) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return persistenceFields.stream()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .filter(mf -&gt; mf.hasName(storedName))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .findFirst()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .orElse(null);\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p><strong>Final Step, Unrelated To This Code Smell<\/strong><\/p>\n<p>I stumbled over the original code when I was looking for methods that suit an <code>Optional<\/code> return type. This seems like a good candidate, it returns null in the case that the storedName doesn&#8217;t match any <code>MappedField<\/code>. Now we&#8217;re using the Java 8 syntax, not only is it clearer that we can use an <code>Optional<\/code>, but easier:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-title=\"\">\u00a0\u00a0\u00a0 public Optional&lt;MappedField&gt; getMappedField(final String storedName) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return persistenceFields.stream()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .filter(mf -&gt; mf.hasName(storedName))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .findFirst();\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>All we have to do is now deal with the returned <code>Optional<\/code> in the places that call this method, but that&#8217;s the subject for another blog post\u2026<\/p>\n<p><strong>In Summary<\/strong><\/p>\n<p>In languages like Java it&#8217;s very normal to see multiple nested for loops and if statements dotted around the place, particularly in pre-Java-8 code. This sort of code is perfectly acceptable for manipulating low level data structures (arrays, collections etc), but should really be treated as a smell if you see it in your domain code, particularly if the nesting gets very deep.\u00a0 In our example, although <code>MappedClass<\/code> needs to know about its <code>MappedField<\/code>s, it shouldn&#8217;t need to poke around the internals of <code>MappedField<\/code> to answer questions, it should be asking <code>MappedField<\/code> questions of its own.<\/p>\n<p>Symptoms<\/p>\n<ul>\n<li>Deeply nested code, usually loops and\/or conditionals<\/li>\n<li>Chained method calls that are all getters (or other non-builder, non-DSL method chains).<\/li>\n<\/ul>\n<p>Possible solutions<\/p>\n<ul>\n<li>Consider tell don&#8217;t ask. Where the code previously grabbed internal data and did checks against it, move those checks into the object containing the data and create a method with a useful name to help other objects answer their questions.<\/li>\n<li>Examine your encapsulation. Does the data really need to leak out into other classes? Should data and\/or responsibilities be relocated so that operations on the data are moved closer to the data itself?<\/li>\n<li><a href=\"https:\/\/martinfowler.com\/bliki\/EncapsulatedCollection.html\" target=\"_blank\" rel=\"noopener\">Collection Encapsulation<\/a>. Sometimes this pattern is a sign that you&#8217;re using a data structure as a domain object. \u00a0Consider\u00a0encapsulating this data structure (Collection, array, etc) inside a domain object of its own and adding helper methods to let other objects ask it questions rather than poke around its internals.<\/li>\n<\/ul>\n","protected":false},"author":360,"featured_media":0,"comment_status":"open","ping_status":"open","template":"","categories":[601],"tags":[3278,2993],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/25929"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/comments?post=25929"}],"version-history":[{"count":0,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/idea\/25929\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media?parent=25929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/categories?post=25929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/tags?post=25929"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/cross-post-tag?post=25929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}