6 ms·
For me, this technique is bigger than objects or encapsulation. It's about reusing existing "branch points" that a language gives you (whether it is polymorphis
by djacobs 14y ago
For me, this technique is bigger than objects or encapsulation. It's about reusing existing "branch points" that a language gives you (whether it is polymorphism, method dispatch, namespacing) instead of explicit conditionals at a level higher than the language. My general take is that explicit conditionals in a high-level language are a smell. Sometimes they're necessary, but if you tell yourself that they mostly aren't, you tend to end up with cleaner code.
I'm not saying it's possible to avoid conditionals completely, but this article gives several good examples of where it's possible. Someone should put together a similar set of examples in a functional language.
- 0x0 14y agoTo a certain level this is true. However if you hide all branching logic inside OO techniques, following the flow of logic and decisions becomes harder as they are hidden in deeply nested class hierarchies and overridden functions.
- gnaritas 14y agoThere's a saying about good OO code, everything happens somewhere else.
- moe 14y agoIt's a slippery slope, though. When you have a chunk of 50 consecutive lines with branches, then yes, that might be worth an abstraction. Sadly too often, in ruby, I see people turning 8 consecutive lines into 4 layers of indirection...
- gnaritas 14y agoThe slope flows the other way IMHO, most of the time most programs I've seen arent abstracting enough and the code is far to sequential and unnecessarily complicated because of it. Excessive if and switches seem far more common to me than excessive use of polymorphism.
- moe 14y agoTwo sides of the same coin. Your example is newbie programmers, mine is the same newbies on their second project. ;) As usual it's all about striking the balance. I wonder if one day we'll come up with a programming language that can enforce these things in a meaningful way.
- gnaritas 14y agoMy example is not newbie programmers, rather, much code written by experienced OO programmers who don't have a Smalltalk background. I can't say what it looks like now, but I recall Rails active record implementation being heavily procedural in nature when I first looked at it way back and DHH is hardly a newbie. Decompile most classes in the dot net framework, and you'll find a fuck ton of procedural code even though it presents an OO API. 500 line methods are not uncommon. When you learn OO in a procedural language like ruby or java, you tend to have a slightly odd idea of OO. Just because a language supports objects doesn't make it object oriented, it just allows object orientation. I thought I knew OO until I learned Smalltalk, and discovered just how deep the rabbit hole can go. If's, foreach, while, unless, switches, these are all procedural constructs. You don't truly grok OO if you can't write a program without using procedural constructs (as an exercise). And who knows, maybe someone will invent a language that nails the balance, I won't bet on it soon though.
- moe 14y agoWell, this is leading a bit astray. In principle I agree with you, but in general procedural constructs are not harmful and should be used where appropriate. 500 lines is indeed a bit much, but I've seen through 100 line methods without an urge to refactor. The best programs are those that have both; good use of patterns and the odd suspiciously long method if appropriate. The worst programs are not only the classic spaghettis but also those that dogmatically stick to a pattern even where it makes no sense. Java is notorious for the latter, but I also often see ruby programs where the author religiously clinges to the belief that no method can be allowed to exceed 5 lines of code. That, in combination with misunderstood unit-testing (foo.MUST_RECEIVE :bar), often leads to ridiculously tight coupling and effectively a monolithic brick that is resilient to change. I call these programs Gnocchi-code. A close relative of spaghetti, just higher density...
- ori_b 14y agoIs that supposed to be a good thing? I always found that style extremely hard to follow.
- gnaritas 14y agoYou have to change how you read code. Stop worrying about implementation details and see the objects API, and stop digging into every method, you don't need to see the implementation all the time. Step back, look at the classes and the messages between them and ignore the implementation whenever possible. When you understand how the parts work together, then you tend to know which part is broken for any given bug, and you know you can ignore most of the other parts entirely. Yes it's a good thing, because such programs are simple and pluggable allowing you to add features by adding new classes rather than modifying and potentially breaking existing ones.
- ori_b 14y agoBut they're not simple. The complexity is still there, it's just distributed and difficult to trace. I much prefer the functional way of doing things. The complexity is still minimized, but I can see where things are coming from, and how data is composed. While it's harder to add "cases" to types in the functional style, I find myself wanting to add functions over types far more often, and therefore, I find that it works far better for me.
- gnaritas 14y agoOf course do what works for you. But distributed is the wrong word in a sense, the complexity is broken down into simpler parts that aren't complex, that's the point. If you're unwilling to adapt your reading style, then you won't see the benefits because your thought process isn't congruent with the style. You clearly prioritize data over behavior, so naturally functional code fits your thought process better, but your though process is one among many. OO works well when your thoughts are behavior centric rather than data centric. Functional and OO actually go very well together.
- jaggederest 14y agoEverything in code is somewhere else, and you get there with a method call http://www.youtube.com/watch?v=75oun5gvDAU&feature=player_detailpage#t=130s http://www.youtube.com/watch?v=75oun5gvDAU&feature=playe...
- solutionyogi 14y agoPersonally, I think this is what 'encapsulation' is about. People have generally thought about 'encapsulation' as guarding the data but I feel that it is about both data + behavior. A quick tip: Any time you check an object's state to decide which method to call on it, you are breaking encapsulation. Call the method on the object and let it figure out what to do based on the state it is in.
- gnaritas 14y ago> A quick tip: Any time you check an object's state to decide which method to call on it, you are breaking encapsulation. Unless that object is self. But a good tip none the less.
- gnaritas 14y ago> I'm not saying it's possible to avoid conditionals completely But it is. Smalltalk has no conditional statement, conditionals are implemented via polymorphism on the subclasses True and False (ignoring compiler optimizations).
- cwp 14y agoYeah, but even in Smalltalk, lots of #ifTrue: messages are a code smell.
- gnaritas 14y agoOf course, you can write C in any language if you try hard enough.
- Roboprog 14y agoThat smells of a parlor trick -- passing one or two blocks / objects / functions to a boolean object to execute or not. Having said that, I like how many OOP languages implement loops as a special case of "visitor", though.
- gnaritas 14y agoIt's not a parlor trick, rather it's what it means to be object oriented. Traditional language constructs are built with object and methods as library rather than special magic keywords. Whatever the problem, Smalltalk builds the solution using objects, thus it is oriented towards objects. It doesn't just have objects, it's built out of them, Smalltalk "is" objects; library and language are the same thing. Your custom constructs are syntactically identical to core language constructs because it's all just library.
- skybrian 14y agoIt's a poor example of a reasonable technique. Reusing branch points is great. Adding an expensive branch point (inheritance to the User class) to replace a cheap one (if statement) is not a win, particularly when it screws up the model. Edit: to clarify, by "expensive" I mean expensive in terms of human hours to understand the code, not computer performance. Class hierarchies are much harder to understand than if statements.
- sukuriant 14y agoThe example was small, but this technique can be used to great effect and great ease of reading when you have larger objects and sets of differentiation that you're working with.
- gliese1337 14y agoThat depends on what you're optimizing for. If you care about making your code smaller (which reduces the occurrence of bugs), making it more readable, etc., and performance isn't much of an issue, then it probably is a win. If you care about getting maximum performance... well, then, you need to get a good knowledge of the target system's performance characteristics and how language features are implemented in order to decide if it's a win or not (or, y'know, just profile the two options, I guess); it's entirely possible that a string of pointer dereferences might turn out to actually be faster than a conditional branch anyway.
- adgar 14y ago> If you care about making your code smaller (which reduces the occurrence of bugs), making it more readable, etc., and performance isn't much of an issue, then it probably is a win. Maintainability over the life of the code is more important than optimizing its present state to the most elegant solution. The code is going to grow, requirements will change, cases will be added not present in the current system.
- roguecoder 14y agoif statements are nearly always bad, because they don't communicate anything and they make the execution flow opaque. Will this method do what it says it will? Who knows! Will this statement be executed? Well, unless some condition is met along the way! Sometimes they are necessary, as in guard clauses, but I find avoiding them as much as possible leads to far more maintainable code. If, and only if, my code is too slow is your concern relevant. That happens so rarely I find it not worth spending time on.