Hacker News new | past | comments | ask | show | jobs | submit login

My contention is that there often are times when the complexity of the business requires a fairly extensive set of operations to occur in concert, including the creation of several models, email-sending etc.

In this case, the Right Place (tm) to put these is in POROs / Interactors that can be tested in isolation and re-used across the code-base if necessary. This code should not live in controllers and certainly not in ActiveRecord models.

It sounds like you agree with that, since you're using them in your own codebase?

In that case, is there not an advantage to standardising the API for these POROs in Rails? Simple methods like fail!, success?, failure? and message

Another way of asking the question - why do so many Rails developers fail to realise that they can use these concepts? Why are so many Rails codebases packed full of enormous ActiveRecord models that are crippled with numerous before_save callbacks?

Sure, shitty coders write shitty code. But can't you lend them a hand?




I don't get why POROs would need some special API. I also don't get why you're pulling code out into things like ConfirmGrouper that still depend on the DB. Why not a true PORO and something like ConfirmGrouper.for(grouper)? Why not just write methods that return bools?

Though I don't know if I agree that the actual sending of emails belongs in a PORO either and not a controller. It seems like determining whether or not emails need to be sent is the kind of logic I would put in a PORO and do the actual email sending from a controller method as in DHH's example.

Edit: Just saw DHH's second example, that's essentially how I would write it.


> In this case, the Right Place (tm) to put these is in POROs / Interactors that can be tested in isolation and re-used across the code-base if necessary.

Key phrase: "if necessary".

It sounds like you're advocating for building abstractions before you actually have a reason to use them. Your reason seems to be "we may need to reuse them in the future" or, "one can see where we might move in a direction where we'd want want to re-use this code", or worse yet, "we're definitely going to build some functionality after this release when we'll want to re-use this stuff."

I've been there, really, I have. Build the abstraction when you actually need it, not when you think you're going to need it, or pretty close to needing it, etc. Because 98% of the time, YAGNI.

> In that case, is there not an advantage to standardising the API for these POROs in Rails?

Not a big enough that I've come across to warrant building domain-specific abstractions and special rules that, as @dhh mentioned, will serve only to raise the barrier to entry to your codebase.


> It sounds like you're advocating for building abstractions before you actually have a reason to use them.

If it sounds that way, I've over-simplified the examples in the blog post in the interests of clarity. I'll take more care in future! The specific interactor in question is used in 4 separate places.

From the post:

> You obviously need to choose the patterns that fit the problem you’re trying to solve – it’s rarely one-size-fits-all, and some of these principles may be overkill in a very simple 15-minute blog application.


"Sure, shitty coders write shitty code. But can't you lend them a hand?"

It's not clear to me that adding more APIs and conventions that said shitty devs won't read about, understand, or even be aware of is actually useful.

If shitty devs are your problem, don't fix the dev tools - FIRE the tools pretending to be devs...


There are a lot of brilliant developers giving talks at every RubyConf advocating these very techniques...


The standard API for POROs is Object (and Class, etc.). Standardizing a new API necessarily makes them no longer "plain".


The current app I work on has a lot of warts, but only five `before_save` callbacks (there's maybe five times that many total callbacks, although there are lots of validations).

If you really want to standardize the interface, use the tools that already exist: ActiveModel and validations. Your “Interactors” are models; they just happen to be coordinating models that affect multiple ActiveRecord models simultaneously. (I did this for an account plan change system that affected billing and device assignment to a plan. It could easily affect a dozen or more records, all in a single transaction, but was itself easily testable.)




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: