8 ms·
I disagree with the comments here. This is mostly not good advice. Ifs exist because most real world problems require them. “If the box is checked, do this, ot
by d--b 8y ago
I disagree with the comments here. This is mostly not good advice.
Ifs exist because most real world problems require them. “If the box is checked, do this, otherwise do that”.
Masking if statements by syntactic sugar doesn’t serve any purpose in my opinion and if anything it makes the code more opaque, or worse, may force you to duplicate code...
- emsy 8y agoIf you really think it doesn’t serve any purpose this means you should always use if and never the proposed constructs. This is clearly wrong and I’d recommend you rethink your position.
- sverhagen 8y agoI don't think the argument is that the constructs are useless. The argument is that it's useless (not good advice) to use them if it is only for the purpose of avoiding if statements.
- quietbritishjim 8y agoAll rules for how to code better should be considered but potentially ignored while you're coding in practice. This includes the rule in the article ("never use if", although it doesn't really say that) and the rule in your comment ("never replace if with polymorphism", although this too is an exaggeration of what you said). If your code contains quite a lot of branching - especially the same pattern of branching in several places - then you should certainly consider replacing that with polymorphism, in the form of virtual methods or perhaps templates/generics (compile-time polymorphism). But you should also consider leaving the branching in place if that is simpler overall. That doesn't make the article bad advice IMO, you just need to not take it too seriously.
- d--b 8y agoFair enough. It’s annoying though (and kind of strange, really) that these articles (which discuss very basic concepts) make it to the front page, and may influence a bunch of rookie developers the wrong way.
- wool_gather 8y agoEh, there's no shortcut to experience. Beginners are going to get ideas from _somewhere_, without being able to thoroughly judge them. And they'll try some, and eventually they'll figure out what works and what doesn't. I thought this article was reasonably clear that it did not offer a silver bullet, just some structures to watch out for, consider, and maybe improve.
- tigershark 8y agoI would rather have new developers think in a more object oriented or functional way instead of procedural. If statements imho promote procedural thinking, while pattern matching, polymorphism, or to a somehow lesser extent, if expressions promote a more OO or functional way of thinking.
- Bartweiss 8y agoI agree that this stuff is mostly counterproductive. As design theory? Fine. As HN frontpage stuff? I mostly see it get discussed in the form of new devs or students asking things like "wait, how should I remove all the 'ifs' in my Java code?" (Yes, that's a real example.) Spreading the good news about case statements, function passing, and so on is great. But this stuff is so often written up as absolutes, when simple conditionals really are a part of most practical cases.
- hellofunk 8y ago> especially the same pattern of branching in several places - then you should certainly consider replacing that with polymorphism As a first step, I'd say better to just isolate the branching in one place, as a separate function, rather than immediately jump to polymorphism which could have high refactoring costs in some cases (even if it might eventually be worth it). Because premature abstraction is just as bad as premature optimization.
- sverhagen 8y agoYeah, as if a line with condensed conditional logic using Boolean operators really got rid of the branching and the running it through your head. My attempted better advice would be to keep methods short and the nesting/indentation limited. Use good method names. Make it easy to understand each method in isolation.
- moomin 8y agoI guess if you’re not familiar with Boolean operators that would be a thing? Seriously are you saying that if (x) { return y; } else { return false; } is as easy to read as return x && y;
- jstimpfle 8y agoHuh, is this python-style logical evaluation, i.e. "x && y" need not be a boolean but could be whatever "y" is? Regarding which way is better, there's not much benefit arguing one way or the other. This is a leaf decision. It doesn't affect the structure of other parts of the code.
- hellofunk 8y agoI'm curious, what about "x && y" is "python-style" ? It's been in nearly all languages, and for decades before python existed.
- jstimpfle 8y agoIt was not about "x && y" but about the construct from the parent post as a whole. It never uses y in a boolean context, but only as a value. So I was thinking y could be anything. In python this is how it works: >>> 0 and 'asdf' False >>> 3 and 'asdf' 'asdf' >>> 3 and '' '' 'and' and 'or' in python are short-circuited as in e.g. C, but it's even more short-circuited! The "last" component is not evaluated in a boolean context. For a complete evaluation you have to use the expression in an if or while statement or apply the bool() function. I would say it's like a monad, if that helps.
- meheleventyone 8y agoI was wondering which of the examples you think particular fall into this category of making the code more opaque? I actually went into this with similar misgivings. A lot of "get rid of ifs" advice, particularly from OOP people ends up making things more complex IMO. However most of the advice other than the "Switch to Polymorphism" seem very down to earth and a simplification. Less about getting rid of ifs as if their mere presence was a stain on humanity and more how to rewrite what they are doing more clearly.
- d--b 8y agoSorry I answered as a top level comment. Im on my phone
- meheleventyone 8y agoNo problem! It seems that the issue is less that the code is made more opaque but that you can quickly think of some counter-examples or nitpicks that make the advice less valid to you? I think the problem of not being universal is true of most programming advice. So I don't necessarily see it as a reason to discount it. I also think in contrast to a lot of articles the author has done a great job to couch their advice as being contextual. For example for your criticism of Pattern 4 the author does actually point out the obvious solution to these complex expressions. To split them out into several parts. Which is what you get with if statements to an extent but spread out much more with a lot of clutter. Some of your criticism also seems to be based on a misreading of the authors intent. For example Pattern 5 where the goal isn't to remove the if statement but prevent having to repeat the same error checking pattern everywhere.
- d--b 8y agoWell despite a few sentences like “remember, if statements are not all bad”, the author still makes a case that if statements are generally to be avoided. My point is that this in itself is bad advice. Overuse of oop concepts is just as harmful (if not more) as overuse of if statements.
- pmontra 8y agoIt depends on the language. Languages with pattern matching usually solve the problem with code like this (pseudocode) fn box(status=checked) do domething fn box(status=*) do something else My Elixir projects have 0 to 10 ifs and they do solve real problems. I use plenty of ifs in other languages but I follow some of the advices of the post.
- hellofunk 8y agoI don't consider this style of pattern matching to be semantically different than ifs or switch cases. There's literally no "if" but they are fundamentally similar to having a single function with a switch/if inside for the "doing something". Most pattern matching in languages is basically souped-up switch statements much of the time. Note that pattern matching is not one of the solutions mentioned by the author.
- dep_b 8y ago`switch boolValue` insists you do something with the false part, `if boolValue` does not. This is just looking at it from the most atomic level possible. If you have a group of booleans you get pretty complex lines of code. Switching on a tuple of three boolean where you can have cases like "if the first two are true ignore the third one" is super powerful. It becomes even better if you return an enum that indicates what it really means. Like CONNECTED, CONNECTING, DISCONNECTING, DISCONNECTED. Now every possible meaningful value of those three booleans has a word attached to it. A Swift-enum allows you to have methods inside enums: enum ConnectionStatus { case connected case connecting case disconnecting case disconnected func `for`(isConnected: Bool, isConnecting: Bool, isDisconnecting: Bool) -> ConnectionStatus { switch (isConnected, isConnecting, isDisconnecting) { case (true, _, false): return .connected case (false, true, _): return .connecting case (true, _, false): return .disconnecting case (false, false, _): return .disconnected } } Then somewhere inside your code: public func connect() { switch ConnectionStatus.for(isConnected: self.isConnected, isConnecting: self.isConnecting, isDisconnecting: self.isDisconnecting { case .connected, .connecting: return // We're already good case .disconnecting: reconnectWhenDisconnected() case .disconnected: startConnection() } The amount of if's that have to be juggled to do the same and the resulting code that is hard to parse when you're maintaining it definitely is more problematic.
- scandox 8y agoAs per another commenter I used Elixir for 6 months a couple of years ago and very quickly started using pattern matching and guards to provide most of the If-type control flow. It didn't cover every case but it came very naturally in most cases where it was useful. The overall logic remains the same, it's really just giving one a clearer view of a specific path.
- tigershark 8y agoI completely agree with you for the case when you say that avoiding an if brings you to code duplication. In that case from my point of view it’s a big NO. But in all the other cases, if you are using an OO language, there are always better tools than ‘if statements’. If you are using functional programming with if expressions instead of if statements then the ‘best balance’ moves a bit in favour of the ifs or a lot towards exhaustive pattern matching. On the whole I would say that I agree with the article discussed here, but with some caveats.
- majormajor 8y ago> Ifs exist because most real world problems require them. “If the box is checked, do this, otherwise do that”. There's a notable difference between "if the box is checked, do [thing 1], otherwise do [completely different thing 2]" and "if the box is checked, do [thing 1], otherwise do [basically thing 1, but with this additional metadata from service y]." And that difference, I think, is what tells you where to put the `if` statements. If things are distinct enough, you have some easy-to-read top-level ifs and switch based on that. Otherwise it's more complicated to trade readability vs code reuse/deduplication. But where you get into big trouble is when you don't think about the dangers of if's at all, and end up with call stacks 5+ methods deep with no rhyme or reason to why certain things are done in if statements in level 5 and other things are done with if statements in level 1. Creating a mental map of what's done where in what conditions for that kind of code is really hard - as is thoroughly testing it, since this often means you're passing a lot of context really deep and don't have easily separable units. (And yeah, "Switch To Polymorphism," I think, is a risky one here - that can turn into "still have the deeply nested if statements, but make them invisible.") I don't think the article really hits that well, though.
- collyw 8y agoMy previous team leader was a pretty poor programmer and would always describe the output of SQL queries he wanted me to generate with lots of "if, then". It was then my job to translate that into SQL which doesn't really have "if" in the same sense as an imperative language does. Sure I could have pulled out all the data and done the branching in Python, but that would have been a performance hit, but mainly because it would be ugly, require a lot more code and likely be a lot buggier. These days I try to keep as much work done in the database because the declarative nature of SQL generally works out with a lot less bugs as well as the performance benefit. Sure it's not going to be possible for every case, but I have noticed that the more experienced I get, the less I like "if"s.
- jacobsenscott 8y agoOf course there are legitimate cases to use if/else. This blog post suffers from the classic problem of blog post code examples - to fit the example in a blog post it needs to be trivial, and because it is trivial it doesn't demonstrate the real value of these techniques. I see if/else overused all the time - every single day in fact - when the techniques in the blog post should have been applied.
- csomar 8y agoLike anything else in life it is about balance. If you abuse ifs, then your code is unreadable, hard to debug and hard to maintain. If you abuse the alternative patterns then your code, again, becomes hard to grasp and hard to maintain. You need to look for a balance between ifs and alternative patterns.