5 ms·
If statements considered harmful
- ouid 10y agotl;dr: OOP is sometimes good.
- joncampbelldev 10y agopolymorphism is very good, but not handcuffed to OOP. Clojure protocols, Haskell typeclasses (and many other examples I'm sure) provide the same functionality "a la carte" without the rest of OOP's features coming along for the ride (to paraphrase Rich Hickey and Stuart Halloway). More eloquently explained details in this talk at around the 21 min mark [0]. [0] https://www.youtube.com/watch?v=cidchWg74Y4 https://www.youtube.com/watch?v=cidchWg74Y4
- millstone 10y agoOne big missing feature in typeclasses is overriding. You can't "call into super." A concrete example: you make a new type in Haskell, and you derive Show so it can be printed. But the default output isn't quite right - you want to add something to it. In an OO language you might "call into super" and append to the string. But in Haskell this isn't possible: you either get the default implementation, or you do it all from scratch. More generally, typeclass default implementations are a lame replacement for overriding, and existentials are anemic compared to dynamic binding. This pushes Haskell interfaces towards rigid, static designs. That's fine if that's what you want, but let's not pretend it's equivalent in power to OO polymorphism.
- joncampbelldev 10y agothat sounds a lot like sharing code by inheritance as opposed to composition. which is unrelated to dispatching by the type of the first (or implicit) argument. i personally would prefer to code to interfaces and keep hierarchy separate from behaviour
- joncampbelldev 10y agoperhaps I haven't felt your pain of rigid static designs because i mostly work in clojure, ymmv
- moomin 10y agoThis is a case of employing OO to circumvent a problem in OO languages. There's two potential problems with if statements: 1) non-locality 2) fragility. 1) can often be dealt with by changing the code, or parameterising. But in general, you want to be able to specify your own interface and specify how specific classes handle it. The article misses out one important detail, because the average OO language doesn't handle it: you might want to do this to someone else's class 2) You can make fragile code in any language, but the absence of pattern matching with totality checking makes it much worse. Of course, there's a third problem that's implicit throughout the article: the inability to verify something's not null through the type checker. The ideas in the article are good, but they're patterns for circumventing problems in your programming language. There's languages with no OO whatsoever that avoid the problems.
- b0bdog 10y agoCare to go into some details/examples of your last sentence?
- moomin 10y agoI think this article is a pretty good introduction to when exhaustive pattern matching is desirable: http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipatt...
- millstone 10y agoThe problem identified has nothing to do with OO. Look at this code: logFile.write(message); We might as well replace `logFile.write` with `fprintf(logFile...)`, and get the same result in C. So we don't need OO to experience this pain. Conversely, this is only a "problem" if `logFile.write()` results in SIGSEGV or NullPointerException or whatever. But some OO languages (Smalltalk, Objective-C, others?) dodge this by making null a message black hole. Confusing, but terribly convenient. One last point: notions of "pattern matching with totality checking" or "verify something's not null through the type system" presupposes exhaustive knowledge of the environment in which your code will run. Maybe that's correct: google.exe on Google owned hardware in Google-owned data centers will behave very precisely. But sometimes it's not correct. Your JavaScript code is running in a yet-to-be-written browser on an ancient version of some OS on random hardware. Your code's typechecking environment is unrelated to its runtime environment. Totality checking requires predicting the future. In this highly dynamic universe, languages like Haskell have no good solutions.
- kowdermeister 10y agoI'm really waiting for the ultimate "Programming is considered harmful" article.
- somehnreader 10y agoPardon my ignorance, but I don't even understand his point. I wouldn't even have bothered with a class at that level of abstraction. If I find repeating if statements throughout my code I put them in a method, end of story. Pseudopython: def logging(logger, message): if null == logger: return if null == message: return logger.write(message) I don't understand why the author would even bother with more than this, given his example. Also note that I used two return (disguised goto's) as guard statements to check the conditions before I do anything.
- egwynn 10y agoIn this case, I prefer FP-style destructured pattern matching (e.g. https://doc.rust-lang.org/book/patterns.html#destructuring https://doc.rust-lang.org/book/patterns.html#destructuring) to OOP-style method overloading (FTA). In the FP style, the compiler can make sure you handle all possibilities.
- rdnetto 10y agoIt's worth noting you can implement something similar in OOP languages using Church encoding: http://blog.higher-order.com/blog/2009/08/21/structural-pattern-matching-in-java/ http://blog.higher-order.com/blog/2009/08/21/structural-patt...