Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>When you have a bunch of <code>if</code> statements, usually they can be refactored using polymorphism combined with the <a href="http://www.dofactory.com/Patterns/PatternState.aspx" rel="nofollow">state</a> pattern:</p> <p>As an introduction, please watch the following video from Misko Hevery (you will love it)</p> <p><a href="http://www.youtube.com/watch?v=4F72VULWFvc&amp;feature=player_embedded#" rel="nofollow">http://www.youtube.com/watch?v=4F72VULWFvc&amp;feature=player_embedded#</a>!</p> <p>This is a summary from the presentation:</p> <p>Most if's can be replaced by polymorphism (subclassing)</p> <p>This is desirable because:</p> <ul> <li>Functions without ifs are easier to read than with ifs</li> <li>Functions without ifs are easier to test</li> <li>Related branches of ifs end up in the same subclass</li> </ul> <p>Use Polymorphism (Subclasses)</p> <ul> <li>If you are checking an object should behave differently based on its state</li> <li>If you have to check the same if condition in multiple places</li> </ul> <p>Use if</p> <ul> <li>Bounds checking primitive objects (>,&lt;, ==, !=) </li> <li>... other uses but today we focus on avoiding if</li> </ul> <p>Polymorphic solution is often better because</p> <ul> <li>New behavior can be added without having the original source code</li> <li>Each operation / concern is separated in a separate file</li> <li>Makes it easy to test / understand</li> </ul> <p><strong>EDIT</strong></p> <p>At first sight using the state pattern with polymorphism, the solution would look more complex because it implies you will need more classes than before, but the trade-off is much much better, as long as you start writing tests for this kind of code you will find that's easier to test, easier to read and understand, and therefore, easier to maintain and extend (right now you just posted about movement to the right or left, but imagine if later you need to move up and down, if you do not refactor your code now, adding new functionality will be a real PITA)</p> <p>You would have something like:</p> <pre><code>// represents the current position class MyClass { public int X; public int Y; } abstract class NodeMoving { abstract void Move(); abstract bool IsValid(MyClass myclass); } abstract class NodeMovingLeft : NodeMoving { override void Move() { // add code to move left if(this.IsValid(MyClass myclass)) { // move } } } abstract class NodeMovingRight : NodeMoving { override void Move() { // add code to move right if(this.IsValid(MyClass myclass)) { // move } } } // and then start modeling the different states class RightFree : NodeMovingRight { override bool IsValid(MyClass myclass) { // add condition to validate if the right is free } } // combining conditions class PushedLeft : NodeMovingLeft { override bool IsValid(MyClass myclass) { // code to determine if it has been pushed to the left } } class LeftFree : PushedLeft { override bool IsValid(MyClass myclass) { // get condition to indicate if the left is free var currentCondition = GetCondition(); // combining the conditions return currentCondition &amp;&amp; base.IsValid(myClass); } } </code></pre> <p>You will need to add the properties needed in order to calculate the conditions and perform the movement</p> <p>It's worth to note how small the methods are, (yes you will have more than before) but they can be tested in isolation really easy</p> <p><strong>Edit 2 -- adding priority</strong></p> <p>Well now that we have a simple state machine, we need to evaluate the priorities, one way to do it (and I would like to hear ways to improve it) is by using a priority queue:</p> <p><a href="http://www.codeproject.com/Articles/13295/A-Priority-Queue-in-C" rel="nofollow">http://www.codeproject.com/Articles/13295/A-Priority-Queue-in-C</a></p> <p>It would look something like:</p> <pre><code> // you could place the priorities in a service to reuse it var priorities = new HashSet&lt;NodeMoving&gt;(); priorities.Add(new RightExists()); priorities.Add(new PushedLeft()); var currentPosition = new MyClass { X = 1, Y = 2 }; foreach (var priority in priorities) { if (priority.IsValid(currentPosition)) { priority.Move(); break; } } // output is: RightExists // now changing the priority order foreach (var priority in priorities.Reverse()) { if (priority.IsValid(currentPosition)) { priority.Move(); break; } } // output is: PushedLeft </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload