Construction: the OOP solution to the branch problem

Ok, as promised, here is my first post regarding software development; this doesn't pretend to be original, it's more a way to organize thoughts for myself. If you find it useful, great!

The topic will be how Object Oriented Programming solves the branch problem, and I think that OOP solves it by construction, i.e. moving all the branch decisions at the construction time of the software.
What is the branch problem? Essentially, in your code now you will have branches, where you will have to decide what path to follow according to the value of some part of the state; something like (pseudo Python here):
 
if a == 1:
   # code 1
else:
   # code 2
 
where the value of variable "a" comes from? it comes from some input provided by the user of the system, which can be an human being or an automated system; it can also be another part of this program:
 
def somefunction(a):
    if a == 1:
        # code 1
    else:
        # code 2
 
somefunction doesn't know where a comes from, it justs executes the code. Note that the object "somefunction" (I know, it is a function here, but this changes only if you are in Java and all that you can manipulate is a class), has to decide each time which branch to execute. This check can be replicated over and over again in multiple places; is this a bad thing? Well, it wouldn't if code is immutable and never changes, but code changes, and external condition changes, and so, sooner or later, someone will come to us and ask to add another condition, to deal with the special case of a == 2. So now somefunction becomes:
 
def somefunction(a):
    if a == 1:
        # code 1
     elif a == 2:
        # new code 1
     else:
        # code 2
 
What's the matter? it was just one place, not a big deal, right? Wrong. We said that it was in multiple places, and we have to go in all the other places and fix it everywhere.
 
"But Marco", you will say, "it's just that you are writing bad code... after all, the caller of somefunction knows the value of a, so he could simply call the appropriate function!"
 
def callerfunction():
     if a == 1:
          somefunction1()
     elif a == 2:
          somefunction2()
     else:
          somefunction3()
 
def somefunction1():
     # code 1
 
def somefunction2()
     # new code 1
 
def somefunction3():
     # code 2
 
The point here is: where "a" comes from? If it's all the some value, 2 out of 3 branches are useless. Otherwise, it has to come from some other input; maybe a is a function of two other inputs, like "b" and "c"; something like:
 
def callerfunction(b, c):
     a = # some function of b and c
 
we can play the same game again with the caller of callerfunction, who know knows (or could know) what to call; in the end, we will arrive at the inputs which the function can't know, because they come from a person, who decides to click on "Red" rather than on "Green", or another system, which calls our API with 3 and 5 as values.
So the branch problem is to decide what is going to be the control flow of our program, based on the user inputs.
Now, in my understanding, OOP solves this problem at construction time; what does it mean? In OOP we create objects (for example, class instances) and we put the code in the methods of those classes; which classes or which subclasses are we going to create? It depends on the user input. Let's get on with the example:
 
class SomeCode1:
     def run(self):
          # code1
 
class SomeCode2:
     def run(self):
          # code2
class SomeCode3:
     def run(self):
          # code 3
 
def factory(a):
     if a == 1:
          return SomeCode1()
     elif a == 2:
          return SomeCode2()
     else:
          return SomeCode3()
 
somefunction = factory(a)
...
somefunction.run()
 
"This is all very nice, Marco, but you still have your if here, just as you had before!"
 
Yup, the if is still here, and you can't get rid of it with our current computers, because, we assume that the value of a is not know until we actually run the program and someone provides the actual value for it. What we did, we moved the decisions based on what to do with the input as close as possible to the user (ideally, right after we get the input from the user) and then we can forget about it, because we build the software which will react in the proper way. Now, all the decisions regarding what to do with the input are in one central place (the factory) and if we need to add more behavior based on this input, for example we need to add the case of a == 3, we can simply go to the factory and fix it.

Comments

Popular posts from this blog

Trenitalia e gli Eurostar

Magicworks and patrons