Live data from Hacker News

Tell, don't ask

robots.thoughtbot.com

81–88 of 88 posts

Re: Tell, don't ask

#81

Example 3 adds a nonsense method, EmailUser#send_to_feed. What does that mean? Email users don't have feeds. If we're going to evangelize OO purity, let's do it right. class Post def created user.post_created(self) end def send_to_feed(feed) feed.send(contents) end end class TwitterUser def post_created(post) post.send_to_feed(twitter) end end class EmailUser def post_created(post) # no-op. end end The post merely te…

This is all nonsense anyway. There's no such thing as a TwitterUser or an EmailUser. You just have users, some of whom use Twitter, some use email (and may have multiple addresses), and some use both, and they can edit their settings to add and remove accounts and change notification preferences. So it's really has-a rather than is-a. Adding unnecessary inheritance is far worse than the original problem.

I suspect the author is trying to use trivial examples to highlight the pattern. As with everything it's about judgement. If you're going to inherit another type be sure to observe Liskov Substitution Principle, otherwise in avoiding conditionals you're introducing another approach that will lead you towards entropy. That is after all what many of these principles are for isn't it? reduce entropy. Writing the code is easy, maintaining and adding crazy new features from the pesky business is where it gets expensive? Entropy kills apps.

In my experience observing (pragmatically, never dogmatically) OO principles like SOLID reduces entropy. Thus are worth applying.

Personally I prefer polymorphism and null object pattern over conditionals to deal with edge cases, though if you have a leaky abstraction in the first place no principle or pattern is going to save you!

Re: Tell, don't ask

#82
post #73

Earlier quoted context omitted.

A better solution would be to just use Observers. One for email, one for twitter. The user shouldn't care about how to talk with these services.

Observers are one of the worst possible solutions because they lie outside the purview of, well, everything in the system. You don't ever see them in the code. You don't know they are there. They are pieces of unicorn code that have side effects that you won't know about or see because they aren't "in the code". Horrible solution. Code should be simple and easy to understand. Observers add significant complexity and…

They add (at least in Ruby) a few lines of code to a program; and take things like Email out of the User model and put them in a more appropriate place.

Re: Tell, don't ask

#83
post #70

Earlier quoted context omitted.

But 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 w…

Of 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 y…

What I prioritize is the ability to quickly and easily answer the question "Where is the bogus value coming from?". When the inputs building up the value are spread all over the place, it's annoying to trace.

Re: Tell, don't ask

#84
post #73

Earlier quoted context omitted.

Observers are one of the worst possible solutions because they lie outside the purview of, well, everything in the system. You don't ever see them in the code. You don't know they are there. They are pieces of unicorn code that have side effects that you won't know about or see because they aren't "in the code". Horrible solution. Code should be simple and easy to understand. Observers add significant complexity and…

They add (at least in Ruby) a few lines of code to a program; and take things like Email out of the User model and put them in a more appropriate place.

And you'd never know that they existed if you look at the user model...

My stance is that things like sending email should be explicit calls so they are obvious. Sending email when registering a new user, for example, should be in the if user.save branch in your controllers or, if you have a more SOAish app, in the service that creates users.

def create user = User.create(params[:user])

  if user.save
    Emailer.new_user_email.deliver
    render 'welcome'
  else
    render 'oh shit'
  end
end

Or, refactor that out a bit (ONLY IF NECESSARY!)

def create user = UserService.create_user_from(params[:user])

  if user
    render 'welcome'
  else 
    render 'oh shit'
  end
end

Re: Tell, don't ask

#85
post #83

Earlier quoted context omitted.

Of 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 y…

What I prioritize is the ability to quickly and easily answer the question "Where is the bogus value coming from?". When the inputs building up the value are spread all over the place, it's annoying to trace.

When you know how the parts work, you don't have to trace it. 99% of the time, I see a bug, I know what's broke, because I understand the program at a high level and know X just can't happen anywhere but Y. Object oriented programs are not a sequence of data transforms, if you insist on thinking of them that way then of course you're going to dislike OO. I've never had any of the problems you're relating to me, because I embraced a change in how I think when I changed to OO.

If you insist on thinking functionally or procedurally, well, then OO won't agree with you because you won't let it. You want to see everything in one place so you can see the big picture all at once; if that works well for you great.

But there's another way that we like, rather than seeing everything crammed into one spot in a complex way, we break it down into many small parts that are each individually stupidly simple. Each part assigned a responsibility in completing the overall task, and each part pluggable with any part having the same interface. The big picture is in the message names between the parts and the part names themselves, and the actual code implementing those messages is basically irrelevant. We find this simpler precisely because we can ignore everything but the one part we're working on, which is stupidly simple. And we can easily extend the system buy subclassing any part to change the behaviour of the program without touching the existing parts, but simply by adding new ones.

Quite simply, we don't want everything in one place, it's inflexible, brittle, not pluggable, and not simple in the way we define simple.

Re: Tell, don't ask

#86
post #83

Earlier quoted context omitted.

What I prioritize is the ability to quickly and easily answer the question "Where is the bogus value coming from?". When the inputs building up the value are spread all over the place, it's annoying to trace.

When you know how the parts work, you don't have to trace it. 99% of the time, I see a bug, I know what's broke, because I understand the program at a high level and know X just can't happen anywhere but Y. Object oriented programs are not a sequence of data transforms, if you insist on thinking of them that way then of course you're going to dislike OO. I've never had any of the problems you're relating to me, becau…

You're talking about rows versus columns in the expression problem. You prefer making it easy to add columns, I prefer making it easy to add rows.

Re: Tell, don't ask

#87
post #86

Earlier quoted context omitted.

When you know how the parts work, you don't have to trace it. 99% of the time, I see a bug, I know what's broke, because I understand the program at a high level and know X just can't happen anywhere but Y. Object oriented programs are not a sequence of data transforms, if you insist on thinking of them that way then of course you're going to dislike OO. I've never had any of the problems you're relating to me, becau…

You're talking about rows versus columns in the expression problem. You prefer making it easy to add columns, I prefer making it easy to add rows.

If that's what you need to tell yourself. You seem like the typical OO hater, uninterested in grokking it, just interested in justifying your dislike with a bunch of hand waving about how you think it's complicated without presenting an alternative that has the same flexibility. As you've not added anything interesting to the conversation, I don't care to continue it; good day.

Re: Tell, don't ask

#88
post #86

Earlier quoted context omitted.

You're talking about rows versus columns in the expression problem. You prefer making it easy to add columns, I prefer making it easy to add rows.

If that's what you need to tell yourself. You seem like the typical OO hater, uninterested in grokking it, just interested in justifying your dislike with a bunch of hand waving about how you think it's complicated without presenting an alternative that has the same flexibility. As you've not added anything interesting to the conversation, I don't care to continue it; good day.

I think I've been trolled.
Post reply on HN