70

I've had a colleague that told me he once worked for a company that had as a policy to never have conditionals ("if" and "switch" statements) in the code and that they let all the decisions in the code be done using polymorphism and (I'm guessing) some other OO principles.

I sort of understand the reasoning behind this, of having code that is more DRY and easier to update, but I'm looking for a more in-depth explanation of this concept. Or maybe it's part of a more general design approach.

If anyone has any resources for this or would be willing to explain or even have some more terms related to this I can use to find more answers I'd be much obliged.

I found one question on SO that was kind of related but I'm unfamiliar with C++ so I don't understand too much of the answers there.

(I'm no OO guru btw but I can manage)

I'm most proficient in PHP, and after that Python so I'd prefer info that uses those languages.

Update: I'll ask my colleague for more info on what he meant exactly.

Update 2015: after some more years of experience in programming I see now that the aim of this policy was probably to prevent programmers from adding functionality in a haphazard way by just adding conditionals (if statements) in certain places. A better way to extend software is to use the "Open/Closed principle" where software is extended by using inheritance and polymorphism. I strongly doubt whether the policy was super strict on all conditionals as it's kinda hard to go completely without them.

Community
  • 1
  • 1
Niels Bom
  • 8,728
  • 11
  • 46
  • 62
  • 16
    What is this company that your colleague speak of? I ask so I can avoid them. Flow control statements are fundamental to programming. If I can't even use the most basic tools *when they are appropriate* to get the job done, what else can't I use? Yes, it is true that you can abuse `if` statements, but that's true for everything else. – In silico Aug 31 '11 at 22:22
  • 16
    @In silico - Flow control statements are fundamental to **procedural** programming. Polymorphism is fundamental to object-oriented programming. That said, most of us use both paradigms. – TrueWill Aug 31 '11 at 22:28
  • 6
    @TrueWill: Flow control is fundamental to imperative programming, and OOP is as much based on imperative programming as procedural programming. Even when you go "pure" OOP, you still have the same thing wrapped up in a slighty more OOP-y dress (`condition ifTrue`, as Smalltalk does it, has essentially the same effect and meaning as `if condition`). And you *have* to use some flow control over polymorphism, unless you want to wrap *everything* (such as evenness of an integer) into dedicated objects. –  Aug 31 '11 at 23:04
  • 2
    possible duplicate of [Can you write any algorithm without an if statement?](http://stackoverflow.com/questions/1937362/can-you-write-any-algorithm-without-an-if-statement) – nawfal Jan 04 '14 at 11:52
  • Polymorphism depends heavily on overloading, so for languages like js and php you are doomed with this approach. – SparK Jan 23 '19 at 17:12

6 Answers6

66

There are some resources on the Anti-IF Campaign site, such as this article.

I believe it's a matter of degree. Conditionals aren't always bad, but they can be (and frequently are) abused.

Additional thoughts (one day later)

Refactoring: Improving the Design of Existing Code is a good reference on this subject (and many others). It covers Replace Conditional with Polymorphism. There's also a new one, Replace Conditional with Visitor, on the web site.

I value simplicity and single responsibility over removing all if statements. These three goals often coincide. Static analysis tools that support the cyclomatic complexity metric can quickly point out code with nested or serial conditionals. The if statements may remain post-refactoring, but could be broken out into smaller methods and/or multiple classes.

Update: Michael Feathers wrote an article on Unconditional Programming.

This is a popular topic: Phil Haack on Death to the IF statement!

TrueWill
  • 25,132
  • 10
  • 101
  • 150
  • 4
    I think it is also important to include this video from Google Tech Talks that talks about this principle: https://www.youtube.com/watch?v=4F72VULWFvc – War Gravy Sep 25 '15 at 23:28
16

After some years of programming I return to my own question, the context of which I now understand a little better.

There's a good talk by Sandi Metz where she refactors a really hairy ball of if-statements to something waaay less hairy: https://www.youtube.com/watch?v=8bZh5LMaSmE

Niels Bom
  • 8,728
  • 11
  • 46
  • 62
7

I've had a colleague that told me he once worked for a company that had as a policy to never have conditionals ("if" and "switch" statements) in the code and that they let all the decisions in the code be done using polymorphism and (I'm guessing) some other OO principles.

I think your colleague misunderstood something or used the wrong words to explain it. And you can't completely avoid conditional statements.

There is a thing to say: proliferating of if statements inside OOP may be a symptom of bad programming. Some example:

Don't use if to check return value of the function like a old C-style programming:

int ret = some_func();
if (ret != null)
   //do something

This was typical in C code but with OOP you should use exception:

try{
    do_something();
}catch(Exception e){
    e.printStackTrace(); //why I was not able to do something
    handle(e); //there is something else I could do to handle the occurred error
}

Sometimes if statements proliferation is related to a bad design. Consider the follow example in Java:

BaseClass base;
if (base instanceof DerivedClassOneFromBase){
    DerivedClassOneFromBase d = (DerivedClassOneFromBase)base;
    d.methodOne();
}else if (base instanceof DerivedClassOneFromBase){
    DerivedClassTwoFromBase d = (DerivedClassTwoFromBase)base;
    d.methodTwo();
}

This is another example of bad if statements, probably related to a bad design. If the two derived object would have a common method defined in their base class BaseClass, the you could have called that method instead of checking their concrete type and casting them:

base.commonMethod();
Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • 1
    I agree that too ifs inside an app is a bad symoton! But using try catch as a flow decision structure is even worse, 1. youre using if/else the same way 2. its TOO SLOW (self experience!!!). ps; Im not saying that your code above is good or bad as its isolated from any context. – Renato Gama Aug 31 '11 at 22:46
  • @Renato - as you say, it's about the context. Microsoft recommends using exceptions for reporting errors/failures, as opposed to return values. There's a chapter on this in [Framework Design Guidelines](http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613). – TrueWill Sep 01 '11 at 02:14
  • 5
    @Renato Gama: yes Exceptions are slightly slower, but the point is that they are exceptions. Their not supposed to control flow decision structure, but handle occasional errors. – Heisenbug Sep 01 '11 at 09:38
  • As a minor aside, exceptions are orthogonal to OOP, although I can't think of any OOP languages that lack it (other than Go, which is only kind-of OO.) – Kevin Jul 22 '16 at 18:11
7

I read the post you linked and it seems that they were mostly talking about removing the need for conditionals within a class, not to be confused with all code in general. The idea being that if you need to check an object's state (using a conditional) to determine if it has certain functionality, then in actuality you have two objects (one that supports the functionality and one that does not) and should define them as two related classes instead.

6

Sometimes conditionals inside methods are bad as they are a sign that you are just performing multiple functions or multiple types methods in the one method.

If you have a class called Automobile and subclasses such as Car and Bike, and a method such as:

drive(Automobile a)
   if (a.isCar)
      // do stuff
   else if (a.isBike)
      // do stuff

you are most likey doing something wrong. Even if it is not a switch based on type, it can often be wrong. If the method is performing multiple functions depending on some variable, it is often trying to do more than one thing and probably should be separated into multiple methods.

For example:

save(Car c)
   if (c is new)
      // do some stuff
   else if (c is old)
      // do some stuff

could potentially be broken up into save and update, as they are two different functions. Though it does depend.

Completely banning if statements would be silly though as they have many valid use cases.

BobTurbo
  • 242
  • 2
  • 5
0

Avoiding conditionals does not necessarily mean you need to get it done by polymorphism or inheritance, take for example :

You have 3 different folders to store uploaded images, uploaded videos and uploaded pdf

You can write code as :

uploadMedia(mediaType){
   if(mediaType == images){
     uploadTo("myProject/images");
   }else if(mediaType == videos){
     upoloadTo("myProject/videos);  
   }else if(mediaType == pdf){
     uploadTo("myProject/pdf");
  }
}

Another alternative that people might use is switch-case :

uploadMedia(mediaType){
         switch(mediaType){
         case : images
         uploadTo("myProject/images");
         break;

         case : videos
         uploadTo("myProject/videos");
         break;

         case : pdf
         uploadTo("myProject/pdf");
         break;
    }
}

But then you can totally avoid conditional statement by using something like dictionary/hashmap/json (Depending upon whatever you work with) :

For example :

HashMap<String,String> mediaMap = new HashMap<>();

mediaMap.put("images","myProject/images");
mediaMap.put("videos","myProject/videos");
mediaMap.put("pdf","myProject/pdf");

//mediaType can be images/videos/pdf same as keys of mediaMap
uploadMedia(mediaType){
  uploadTo(mediaMap.get(mediaType));
}

This is sort of pseudo code so there might be syntax mistakes, but overall this concept is also helpful in avoiding conditionals. Also line of code can be reduced.

TGW
  • 805
  • 10
  • 27
  • Switch statements are just if statements written with other words, also known as "syntactic sugar", so that's not really answering my question. The hashmap is basically another way to write a switch statement. If-less programming (as I understand it) is more about avoiding the problems you (very likely) will have when you use if statements (a lot). They tend to multiply and make code hard to read. If you use the open/closed principle or inheritance you can avoid that (and gain other problems of course). – Niels Bom Sep 11 '17 at 11:54
  • 1
    I didn't get this part of your comment **The hashmap is basically another way to write a switch statement**. I thought of it as an alternative to switch-case and if-else, making code easier to read. Also, it would really help me understand if you or maybe anyone reading this could tell me performance effect of using hashmap over if/else or switch/case. This could help me understand bottlenecks of performance too. Thanks :) – TGW Sep 11 '17 at 12:18
  • You're correct, using a hashmap is an alternative to switch-case and if-else statements. It's an alternative that can sometimes make code easier to read. It is not an alternative if you're looking for something that is not a conditional. It's just written differently. If you want to discover the performance effects of one programming solution over another you can simply measure it with timers. But let's not go offtopic in this thread :-) – Niels Bom Sep 18 '17 at 13:44
  • Thanks, you're right should not go off topic on this thread – TGW Sep 18 '17 at 13:47