Live data from Hacker News

Tell, don't ask

robots.thoughtbot.com

41–50 of 88 posts

Re: Tell, don't ask

#41
post #11

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 ar…

It'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 st…

That 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.

Re: Tell, don't ask

#42
post #11

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 ar…

It'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 st…

if 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.

Re: Tell, don't ask

#43
post #14

Earlier quoted context omitted.

To 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.

There's a saying about good OO code, everything happens somewhere else.

Is that supposed to be a good thing? I always found that style extremely hard to follow.

Re: Tell, don't ask

#44
post #14

Earlier quoted context omitted.

To 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.

There's a saying about good OO code, everything happens somewhere else.

Everything in code is somewhere else, and you get there with a method call

http://www.youtube.com/watch?v=75oun5gvDAU&feature=playe...

Re: Tell, don't ask

#45
post #8

Excellent. As a self-taught hacker, I always felt like I was missing something about OO, because it's introduced with an analogy to real world objects, while glossing over the more subtle contracts that programming objects have with each other. Seems like we need a more developed vocabulary to express these things.

I think the vocabulary has been there, it's just very poorly taught/communicated. The c2 wiki was where I first encountered it. Old OOPSLA program proceedings, if you can find them, have some jewels among the cruft. And there is always Smalltalk Best Practice Patterns...

Re: Tell, don't ask

#46
post #28

Earlier quoted context omitted.

carrying on, why make all user models define a no-op? class User def post_created(post); end end class TwitterUser

Inheritance is not always the right solution.

Especially when the examples are written in a language which has mixins as core functionality.

Re: Tell, don't ask

#47

Earlier quoted context omitted.

It'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 st…

if 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 s…

(Edited original post to clarify that I was not talking about performance.)

If the inheritance already exists and make sense, adding another overridden method may be a win. The thing I'm arguing against is introducing a new class hierarchy to remove an if statement. Inheritance is a big gun and you shouldn't use it unless it significantly cleans up the code.

In this particular case, extending User to get TwitterUser is a particularly bad example because it's adding an is-a relationship when has-a is better. After all, users may have both twitter accounts and email addresses, and these can change dynamically (they can edit their notification settings). Unthinking use of inheritance is far worse than extra if statements.

Re: Tell, don't ask

#48
all of those examples look horrible, make debugging harder and implies strong code coupling.

example 1, we're mixing data with UI labels. How do you handle localization ? by coupling your localization code with your user data/behavior ?

example 2 : you're simply coupling the system_monitor with the alarm, while in the worst case, the alarm should be linked to the system_monitor. Now if you want to add a "report_to_government_agency" method, you'd add that inside the code of every single one of your monitors (knowing that you don't want to report a broken light, but it might be a good idea for a melting nuclear core) ? Note that I'm not saying that the first code is good, it's just as bad... Also, the method becomes very poorly named (I want to know if the sensor went back to normal, but every time I query "check_for_overheating", it just rings the alarm and doesn't give me any info back ???)

example 3 is just a poor usage of pseudo inheritance (and an abuse of duck typing). you create a new type of user for every messaging service again ? and if a user uses more than one messaging service, you just create a type for every combination ? Not very scalable nor readable, IMO.

The last example is just as bad. useless inheritance, senseless object. the definition of street_name is wrong. the doc will be around "Street name returns a street name or an error message if there's no street name defined" How do you know if there's no street name, now ?

All those examples basically make all extension harder. They're everything that's wrong with OO. an object is not about one structure that contains data and does everything that can be done with it. An object is about giving organized access to pertinent data and/or pertinent behavior and (potentially) allowing to change them.

Re: Tell, don't ask

#49
post #14

Earlier quoted context omitted.

To 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.

There's a saying about good OO code, everything happens somewhere else.

It'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...

Re: Tell, don't ask

#50
post #43

Earlier quoted context omitted.

There's a saying about good OO code, everything happens somewhere else.

Is that supposed to be a good thing? I always found that style extremely hard to follow.

You 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.

Post reply on HN