Live data from Hacker News

Where the logic hides in rails apps

gammons.github.com

1–10 of 56 posts

Re: Where the logic hides in rails apps

#2
These kinds of callbacks, which remind me about the "aspect oriented programming" that was hyped for a short while a few years ago, look super dangerous.

I could easily imagine someone unaware of this hook running a test to create a bunch of user entries, sending emails all over the place without even realizing.

It's like someone read http://en.wikipedia.org/wiki/COMEFROM and took it seriously.

Re: Where the logic hides in rails apps

#3
post #2

These kinds of callbacks, which remind me about the "aspect oriented programming" that was hyped for a short while a few years ago, look super dangerous. I could easily imagine someone unaware of this hook running a test to create a bunch of user entries, sending emails all over the place without even realizing. It's like someone read http://en.wikipedia.org/wiki/COMEFROM and took it seriously.

Anybody who doesn't have something like mail_safe [1] installed is asking for trouble, no matter where he stores his business logic.

[1] https://github.com/myronmarston/mail_safe

Re: Where the logic hides in rails apps

#4
post #3
post #2

These kinds of callbacks, which remind me about the "aspect oriented programming" that was hyped for a short while a few years ago, look super dangerous. I could easily imagine someone unaware of this hook running a test to create a bunch of user entries, sending emails all over the place without even realizing. It's like someone read http://en.wikipedia.org/wiki/COMEFROM and took it seriously.

Anybody who doesn't have something like mail_safe [1] installed is asking for trouble, no matter where he stores his business logic. [1] https://github.com/myronmarston/mail_safe

That's a nice solution to the "emails gone wild" problem, but - no offense - it's a bit besides the point.

We could just as well be talking about S3 data, facebook posts, tweets, anything with (side) effects beyond the active database record in question.

Re: Where the logic hides in rails apps

#6
Maybe this is naive, but what's wrong with just putting `UserMailer.welcome_email(user).deliver` in the controller, right after the user is created? In my mind, delegating an email to be sent should be a job for the controller.

IIRC, the Rails ideology says that "Models should not know about any part of the application except for their own datastore." Even though the :after_create hook is the "Rails way", doesn't this violate their own practices?

Re: Where the logic hides in rails apps

#7
I'll give a proposal now: every chair of every developer shall from now on give them electric shock whenever they use the term "business logic". Ouch.

Seriously, "CreatesContact" is not really a class. It's a procedure, function with side effects, whatever you call it. Just with a class wrapper that boosts the developer ego almost as much as an AbstractFactoryManagerFactory.

No, modules are actually great. If you have billions of tiny modules all over the place, you probably (note the "probably") optimized way too early by splitting things out into them without a clear reason.

And guess what, if a new developer comes into a project and investigate stuff, they will see the model class start with all sorts of metadata, including callbacks, including those fancy ones called "before_save". If they can't guess what "before_save" means, you might want to either pay for an English class, or switch the framework to something that speaks in German.

And as for using rails as a web delivery mechanism, can you please, please, please investigate things like Sinatra and plain old rack, because those are delivery mechanisms. Rails is a framework, and it's entire point is being opinionated. If you disagree with the opinions, you probably should investigate other frameworks, or just use the libraries that you like (including those that are parts of Rails). Or maybe whack Rails into whatever shape you would like you to be in.

(Also, monolithic applications happen to the best of us, but the problems in them actually often come from the fact that they're monolithic. Stop looking for other developers to blame).

Re: Where the logic hides in rails apps

#8
post #3
post #2

These kinds of callbacks, which remind me about the "aspect oriented programming" that was hyped for a short while a few years ago, look super dangerous. I could easily imagine someone unaware of this hook running a test to create a bunch of user entries, sending emails all over the place without even realizing. It's like someone read http://en.wikipedia.org/wiki/COMEFROM and took it seriously.

Anybody who doesn't have something like mail_safe [1] installed is asking for trouble, no matter where he stores his business logic. [1] https://github.com/myronmarston/mail_safe

I tried to pick a very contrived example. The architecture rails forces you to have is great if all of your business logic is simply CRUD. Once your app starts doing other things though, that's where careful consideration is needed as to where that logic should live.

You could imagine callbacks or observers that do all sorts of things:

  ping an external service
  touch another model or models
  send an internal email
  or does a combination of a bunch of stuff.
Things get even tougher when you start having flags that turn logic on or off. It has the potential to really become a mess, very fast.

Re: Where the logic hides in rails apps

#9
post #6

Maybe this is naive, but what's wrong with just putting `UserMailer.welcome_email(user).deliver` in the controller, right after the user is created? In my mind, delegating an email to be sent should be a job for the controller. IIRC, the Rails ideology says that "Models should not know about any part of the application except for their own datastore." Even though the :after_create hook is the "Rails way", doesn't thi…

It's okay if that's the only case where the email should be sent, and other means of user creations should never, ever do that. It might be an issue if, for example, the email should be sent always, no matter how the user was created.

Edit: basically, the question is "which process involves sending the email". It might be "creating a user," or it might be "using the 'create user' form". At some point you might need a more abstract solution, of course — see things like Listeners, DHH's Concerns, AOP or whatever you like. But the thing is, if you don't delay too long, you can retrofit your codebase with it, so don't worry too much.

Unless you're coding up a nuclear plant or storm barrier or the moon-carving laser. Please don't use webappy principles to code drivers for the moon-carving laser.

Re: Where the logic hides in rails apps

#10
I like the idea of one-class-one-responsibility but have a number of questions:

1) Isn't the whole idea of ActiveRecord that persistence is hidden from the model programmer? Surely the model doesn't actually have 'triple duty' because it doesn't contain any persistence code?

"Imagine you are a brand new developer on the team that supports this app. You see the @contact.save call but now, the fact that it performs business logic is even harder to see, since the logic is placed in another module, somewhere in some other directory." - I will imagine I am a new developer on the project:

2) My expectations have been subverted. My understanding of Rails conventions is that business logic does live inside the model which will be inside app/models. Therefore, the first question I'd ask myself would be: "What business logic happens when this an instance of this model is created?" Surely Rails supports this paradigm by virtue of the existence of after_create? Wouldn't I have to visit a third class in non-obvious location to understand the updated example(app/use_cases)?

3) Doesn't CreatesContact now have two responsibilities as well? Namely Creation and validation? And the name doesn't communicate that it performs validation as well, does it?

4) Doesn't creating this new class exacerbate the problem of code/logic being 'scattered all over the place'?

5.1) Doesn't the issue of: "[In the controller], To an outside observer, it is not entirely clear that an email will be sent." remain just as problematic as the model containing the code for sending the email? Because you'd have to mentally context switch (the single biggest obstacle to understanding code IMHO) from the controller to the CreatesContact class to see what is happening. when CreatesContact.new(@contact).create_contact! is called.

5.2) Continuing the thread of the last question, CreatesContact.new(@contact).create_contact! certainly doesn't say to the programmer: "I send an email if a certain flag was checked". Isn't this unintentionally self-defeating? The aim is a reduction of 'obfuscation', but isn't hiding what a 'single-responsibility' class actually does obfuscation itself?

I don't mean to be dismissive, but, broadly, I disagree with the way you have tried to compartmentalise this application. The purpose of my questions is to help me understand your opinion.

Post reply on HN