Live data from Hacker News

Rails – The Missing Parts

eng.joingrouper.com

121–130 of 173 posts

Re: Rails – The Missing Parts

#121
post #118

Earlier quoted context omitted.

Please take a second to think about who you're saying "No, they're not." to. You'd think perhaps that he knows what he has AR callbacks in AR for, regardless of what you might think they're in there for. The whole idea of ActiveRecord is that you to make your models with a clean interface to persistence. Among the features of that interface are the callbacks. They are there for your domain model to make use of, that'…

Please. I'm well aware of who the parent was. I'm well aware of what his intent was. And I'm well aware not only of the strengths of the active record pattern (which I implemented in at least two different languages five years before he put Rails out there—as did many, many others) but also its inherent weaknesses. You keep using the term "domain model" to refer to active record objects, which makes it clear that you…

Oh I insist.

"If they were, the persistence would be handled elsewhere."

Persistance is handled elsewhere, it's handled in the superclass. If you think that's not a good idea, you shouldn't be using ActiveRecord, because that's the way it works.

You could argue there's not enough abstraction from the DB in AR, but that's a different discussion. Here we discussed if the persistance callbacks were an appropriate tool for in the domain model, and I reckon they are.

Also, any fool knows that putting lots of code in a single file is not a good way of scaling complexity, so yeah at some point you're going to need to break your code out in concerns and what not. ActiveRecord most certainly does not stand in the way of that.

Re: Rails – The Missing Parts

#122
post #39

The proof is always in the pudding. While there are good and reasonable times to introduce "interactors", this particular example is poor. The tests presented are anemic, and the code is absolutely not any clearer by being extracted and wrapped. I would indeed have kept all this in the controller. The key point for an "interactor" extraction is imo when you have multiple models being created in symphony, like a Signu…

I've only been involved in a couple of Rails projects (at least since the wedding list management app I wrote for my own wedding back in the v1 days), I'm in complete agreement with David.

And honestly, Rails already has something that works beautifully for an “interactor” extraction. It's called ActiveModel. Add a bit of other code (include ActiveModel::ForbiddenAttributesProtection, ActiveModel::Validations::Callbacks, and ActiveModel::SerializerSupport; extend ActiveModel::Naming) and you've got an object that acts like an ActiveRecord object but orchestrates changes across multiple models in a clean, constructive way—without introducing an entirely different way of working with your code.

I've done this at both places I've been doing Rails and it works at both cleaning up the models it orchestrates and keeping the business logic in the places where it belongs. I'm working actively to get rid of some of the Rails Fads that have come through and wreaked havoc on the current codebase (we've got Presenters and Commands and all sorts of other stuff that is just making the code harder to understand with little value).

There's a million ways to skin this particular cat, and claiming that “adult” Rails needs this particular gem or that particular way of writing code says a lot more about the person claiming it than the people who aren't following that particular fad.

Re: Rails – The Missing Parts

#124
post #54

Earlier quoted context omitted.

Yes, rewriting a system after it's already settled and designed can indeed bring a cleaner code base about. But don't confuse that with "better architecture". Don't even get me started on the hand-wavy "loosely coupled". If this is a poor example, pick a good example. I'll be happy to code ping pong you whatever example you choose. One way to spend hundreds of thousands of LOC on an application is to stuff it with ne…

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…

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

Re: Rails – The Missing Parts

#125
post #121

Earlier quoted context omitted.

Please. I'm well aware of who the parent was. I'm well aware of what his intent was. And I'm well aware not only of the strengths of the active record pattern (which I implemented in at least two different languages five years before he put Rails out there—as did many, many others) but also its inherent weaknesses. You keep using the term "domain model" to refer to active record objects, which makes it clear that you…

Oh I insist. "If they were, the persistence would be handled elsewhere." Persistance is handled elsewhere, it's handled in the superclass. If you think that's not a good idea, you shouldn't be using ActiveRecord, because that's the way it works. You could argue there's not enough abstraction from the DB in AR, but that's a different discussion. Here we discussed if the persistance callbacks were an appropriate tool f…

Concerns are just a complicated way of putting lots of code in a single class. The interface is the same if you put everything in the same file or if you break it out into a dozen mixins/concerns.

Re: Rails – The Missing Parts

#126
post #54

Earlier quoted context omitted.

Yes, rewriting a system after it's already settled and designed can indeed bring a cleaner code base about. But don't confuse that with "better architecture". Don't even get me started on the hand-wavy "loosely coupled". If this is a poor example, pick a good example. I'll be happy to code ping pong you whatever example you choose. One way to spend hundreds of thousands of LOC on an application is to stuff it with ne…

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…

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

Re: Rails – The Missing Parts

#127

Earlier quoted context omitted.

Sure - I don't think anyone in the Rails world is claiming to have invented these principles. The problem is that Rails ships with a very limited set of core architectural concepts, and many inexperienced Rails developers feel like they've got to cram all of their code into a Model, View or Controller. Once your codebase reaches a certain complexity, principles from other programming paradigms are extremely useful.

To be fair, Rails does have concerns which let you easily compose your models out of modules, rather than having big god-object models, and it is easy to load other arbitrary collections of code too. So it is not really limited to MVC. For beginners, I'm not sure it would be helpful to introduce a whole load of named patterns, as it just leads to cargo-culting and overuse of patterns without understanding whether the…

The problem with concerns is that they don't actually break down the god classes, they just separate the pieces of the god class into different files and combine them at runtime.

The important metric here isn't "wc -l app/models/god.rb", it's "God.public_instance_methods.length".

Re: Rails – The Missing Parts

#128
post #121

Earlier quoted context omitted.

Please. I'm well aware of who the parent was. I'm well aware of what his intent was. And I'm well aware not only of the strengths of the active record pattern (which I implemented in at least two different languages five years before he put Rails out there—as did many, many others) but also its inherent weaknesses. You keep using the term "domain model" to refer to active record objects, which makes it clear that you…

Oh I insist. "If they were, the persistence would be handled elsewhere." Persistance is handled elsewhere, it's handled in the superclass. If you think that's not a good idea, you shouldn't be using ActiveRecord, because that's the way it works. You could argue there's not enough abstraction from the DB in AR, but that's a different discussion. Here we discussed if the persistance callbacks were an appropriate tool f…

Jesus christ. You aren't seriously arguing that handling it in a parent class removes it from the AR object's responsibilities, are you? In point of fact, that inheritance pattern is a bad idea, and I don't use it when I'm implementing an actual domain model, but that's seriously irrelevant.

1) I did argue exactly that; 2) it follows from (1) that an evented mechanism based on the database lifecycle of such objects is about the persistence of said objects, not about the domain.

lastly, if you think code complexity is about how fat your models are, I urge you to get out of "the rails way" for awhile and do some heavy reading. Moving code into concerns is just geography, and having lots of code in a single class is merely the most visible symptom of complexity.

Re: Rails – The Missing Parts

#129
post #71

Earlier quoted context omitted.

If reassigning a case is part of the domain, it belongs in the model. I don't know how to put this gently, but this concoction looks like a hot mess with no separation between modeling and controlling. These commands have a ton of domain logic all tangled up with activity reporting, formatting, and parameter parsing. It looks like a big ball of mud to me :(

Perhaps that's why the OP used a simple example. Complex examples are pretty hard to get your head around at first glance; even sane systems can be perceived as a 'hot mess' upon a quick read without any context. I disagree that re-assigning a case belongs in the case model. It is a complex interaction between several models. Extracting it to a command object allows all of the rules to be easily understood.

It's a model, all right—but it may not be part of the “Case” model. It might be part of a CaseAssignment model that is (for lack of a better word) a virtual model. Or it's part of the controller that does the changes. It mostly depends on how your code gets used and where it gets used from.

When I did something similar[1], I implemented it as a “virtual” model and applied validations to make sure that the PlanChange was properly constructed, and then performed the change in a transaction. I was able to test the hell out of it both with and without actual database interaction. But I was able to use it in three different locations and removed lots of special case code that had built up over two years of development.

You probably don't need Commands. You probably need something to orchestrate manipulating multiple ActiveRecord objects simultaneously in a transaction. It's still a model, but it may not be the model that you thought it was.

[1] Account from Plan [a] to Plan [b] that has a different quota, affecting Device assignments, possibly including moving some devices to Plan [b], some devices to Plan [z] (a default plan), and disabling some devices entirely because there's no quota available anymore.

Re: Rails – The Missing Parts

#130
post #54

Earlier quoted context omitted.

Yes, rewriting a system after it's already settled and designed can indeed bring a cleaner code base about. But don't confuse that with "better architecture". Don't even get me started on the hand-wavy "loosely coupled". If this is a poor example, pick a good example. I'll be happy to code ping pong you whatever example you choose. One way to spend hundreds of thousands of LOC on an application is to stuff it with ne…

You can't possibly think that there's never a use case for the Interactor pattern. Please watch Uncle Bob's talk: http://www.confreaks.com/videos/759-rubymidwest2011-keynote-...

I can possibly think that there's never a reason to reach for a pattern when it's better to let a pattern emerge from your code and then refine it. As far as the video is concerned I personally won't bother to watch it—Bob Martin sells snake oil as “clean code”.
Post reply on HN