title: Resolving Cyclomatic and Perceived Complexity
body: <p>I have the following method in my test app:</p>
  
  <pre><code>def on(definition, visit = false, &amp;block)
    if @page.is_a?(definition)
      block.call @page if block
      return @page
    end
  
    if @context.is_a?(definition)
      block.call @context if block
      @page = @context unless @page.is_a?(definition)
      return @context
    end
  
    @page = definition.new(@browser)
    @page.view if visit
  
    @page.correct_url? if @page.respond_to?(:url_matches)
    @page.correct_title? if @page.respond_to?(:title_is)
  
    @model = @page
  
    block.call @page if block
  
    @page
  end
  </code></pre>
  
  <p>When I run the rubocop tool against the file containing this method, I get the following responses:</p>
  
  <pre><code>C: Cyclomatic complexity for on is too high. [10/6]
  C: Perceived complexity for on is too high. [10/7]
  </code></pre>
  
  <p>What I don't get is what it thinks is "too complex" thus I'm having trouble figuring out how to resolve the issue. Ideally I'd rather not just tell rubocop to avoid the warning since it's no doubt telling me <em>something</em> useful.</p>
  
  <p>As far as the method being complex, as you can see, I have a couple of <code>if</code> calls and then I have to work with the <code>@page</code> object in order to make sure it is set up correctly. (This example, in context, is a Watir-WebDriver object.)</p>
  
  <p>I do agree the method is complex in that it requires checking on if <code>@page</code> is already existing and set to something as well as checking if the <code>@page</code> should be the same as the <code>@context</code>. But -- again, I'm not sure what to do about it.</p>
  
  <p>The full code for the module that this method is inside is here:</p>
  
  <p><a href="https://github.com/jnyman/symbiont/blob/master/lib/symbiont/factory.rb" rel="nofollow">https://github.com/jnyman/symbiont/blob/master/lib/symbiont/factory.rb</a></p>
  
  <p>I was initially thinking I could just break this up into different method calls, which might reduce the complexity of each method. But then that means someone reading my code has to hop to a series of different methods to understand what <code>on</code> is doing. Just moving things around wouldn't seem, to me, to be removing complexity overall; rather, it would just be shuffling it around. Or am I wrong?</p>
  
  <p>Any advice here is appreciated.</p>
  
  <p><strong>UPDATED CODE</strong></p>
  
  <p>I have gotten this reduced somewhat. Here's what I now have:</p>
  
  <pre><code>def on(definition, visit = false, &amp;block)
    if @page.is_a?(definition)
      block.call @page if block
      return @page
    end
  
    if @context.is_a?(definition)
      block.call @context if block
      @page = @context
      return @context
    end
  
    @page = definition.new(@browser)
    @page.view if visit
  
    @model = @page
  
    block.call @page if block
  
    @page
  end
  </code></pre>
  
  <p>Based on feedback, I removed an <code>unless</code> qualifier that did seem to be useless. I also removed two lines that I found I could put to better use somewhere else (checking the title and the url).</p>
  
  <p>This has removed the "perceived complexity" entirely and has left me with just this:</p>
  
  <pre><code>C: Cyclomatic complexity for on is too high. [7/6]
  </code></pre>
  
  <p>I appear to be "one point" (or whatever the terminology is) too complex.</p>