loading...

re: Is “Defensive Programming” actually healthy? VIEW POST

TOP OF THREAD FULL DISCUSSION
re: I have to agree that if there's ANY chance that a stray value is going to get into your function you should throw an exception (if your type system...
 

You mention that if statements are a code smell... but what does it smell of?

Like the code in the article does it’s job and it communicates it’s intention clearly.

 

They are an OO code smell.. In OO things should be solved by dynamic dispatch and not by successive ifs since all the rules about a type should be in a class, rather than dispersed all over the program.

A second best option is to use tables (as others suggested) but that's just a fancy if/elseif/...

From a purist OO perspective the solution is to make methods in each type that would solve your problem.

So instead of:

if (type == 'red') {
doSomething1();
else if (type == 'blue') {
doSomething2();
} else if ...

You can just write:

type.doSomething()

Where doSomething() is overloaded for each type.
Now you may use a single if/else if/.. statement or table in one place to convert your string into an object (a factory method) but thats in only one single place in the program.

If you can’t tell me why it smells (as in you can’t tell me what type of bug will occur based off of what you’re seeing) then you might be blindly following doctrine.

And as far as “the OO era” that you mentioned, many of us are moving to more functional concepts like splitting data from logic. I do that not because I want to follow the functional programming doctrine but because I found code to be more testable that way. I’ve also found that I was able to utilize composition much easier when I started to throw away the idea of encapsulation.

Consider checking out this incredible article: medium.com/@cscalfani/goodbye-obje...

The specific bug is that by spreading your type logic all over the program, if you need to update it, you need to find all those if statements to update them. So your code is more error prone and less maintainable. Its also a violation of the DRY principle. Specifically if you want to add a new type, and forget to update one of your many if statements you'll have a bug. Or if you want to change the behavior of a type, and forget to update it in one of the many if statements.

I did mention "OO era" in case because I new the functional style would be mentioned. Note however that with a functional style, you shouldn't throw away encapsulation necessarily. Encapsulation is modeled in your code module. You could do the exact same thing in a functional style without proliferating your code with if statements.

The functional equivalent for this is multimethods. (though I'm not sure the language you are using supports that construct)

See clojure.org/reference/multimethods for example

You might be missing the point when you say this. Based off what you said, I feel that I might not have explained myself well:

The specific bug is that by spreading your type logic all over the program, if you need to update it, you need to find all those if statements to update them.

I’d like to clarify that the assertNever function tells me if a new type was added and it tells me if one was removed.

So I don’t need to “find those if statements” because the compiler will inform me.

That is a work around.

But no, the compiler won't tell you. An exception will tell you at runtime. Assuming you tested correctly you may find this before it hits production. But its hard to argue that this is better than just using better coding practices.

if/elseif/... is a code smell. A bad practice if it can be avoided. In this case it can be avoided.

Try compiling this code. The compiler will in fact tell you if you’re missing a case that’s described in the discriminated union.

Of course, that only works if you recompile all your libraries and dependencies. The OO solution would work even if you only recompiled the class.

code of conduct - report abuse