There is a demo app? Cool, I never noticed such a thing existed, when I started out, I always loved to see examples of how things were done.
I think something that often gets missed regarding concerns is that they’re basically just syntactic sugar on top of standard Ruby mixins, and the problem there is that some other popular programming languages have little to no proper support for mixins. (I’m looking at you, JS! But some do, like Protocols in Swift/Objective-C.)
I personally am a massive fan of mixins/concerns, and I think they would be better regarded if the education piece started at a more fundamental level like “Why Ruby Has Mixins and Why That’s Awesome” and compared what they provide developers vs. non-Ruby-esque programming techniques.
Also: in my experience a lot of non-ruby coders are required to work on rails code bases. They will never dig deep into ruby and just make code, that is java-esque and have all the popular patterns. But it will be bad Ruby code. And it will have zero mixins as their primary languages don’t support mixins.
I just wanna echo the idea of writing a guide or set of guides to convey the ideas that DHH’s expressed here and in his screencasts. Not just about how to use concerns/mixins on a technical level, but about how to use them philosophically.
The omakase can extend to “tried and true” patterns and pathways that newbies can look to for advice on setting up their new (read: maybe not even first) app. The starting point for a guide could literally be what DHH just posted in terms of content and that would be a 10x improvement over what we have.
There is getting started app example here. So what I’m proposing is to expend this “getting started” section and showcase how other parts(including concerns) can be used in the context of real application.
For example on thing could be how controller concerns could be used on the scoped controllers:
class Posts::CommentsController < ApplicationController include PostScoped ... end class Posts::ParticipantsController < ApplicationController include PostScoped ... end module PostScoped extend ActiveSupport::Concern included do before_action :set_post end def set_post @post = Post.find(params[:post_id]) end end
I understand that Concerning might seem to fall in the valley between useless and incorrectly placed.
Let me go off on a tangent and make my case for it: it’s a good temporary, low-overhead tool for chunking of concerns. It’s “good enough for now” instead of “perfect or nothing”.
It allows me to group methods together while I’m in context and express “this all goes with the same chunk” without needing to break out into another file, typing three boilerplate lines of code. It’s communicative.
In the same spirit as the H1-H2- model, I can just markup my H2 here and there and keep writing instead of needing to declare-extend-include. If I reorganize later and learn new things about the future, it’s easily undone without worrying I’ll break something. The code works exactly the same, but what it communicates to humans changes.
I don’t think long term you’d want a component with a bunch of
concernings laying around. But taking that first step of chunking while you have the context in mind and the future complexity is unknown is super useful. I can come back another day, when my concern has grown large, and take the time to place it into its own file. Or I could have learned that this didn’t complexify as expected, and remove the concerning boundary. It’s a lean, iterative tool to me.
If I may make a gardening metaphor (I’m propagating pothos’ these days):
Concerning is the water jar I put my cuttings in to grow roots. Maybe it will, then I’ll transfer it to its own pot – or maybe it won’t and a pot wasn’t necessary – in which case I saved the effort.
On the one hand I am also unsure if a Concern / mixin tutorial is needed in the Rails guides. On the other hand, I’ve seen many projects were Concerns have just been used to extract parts of a god object into other files to make rubocop happy. And this is a code smell, which can lead to hard to understand and maintain code. So yes, maybe there is some more education on this needed.
sighh, if only these were in text format instead!
well, clearly then that’s the problem. sounds something like coding “for” the linter instead of coding “with” the linter. i feel like this is a common problem accross programmers and not just something about Concerns, so even with extended education i don’t think that sort of issue would go away.
@msapka i’ve seen this loads of times first hand. maybe exposing mixins very very visibly in rails code at the guides or something would help? i’m not sure
For then Ruby is often Rails, so having it in guide would be very useful
Totally agree with the concern generator. So much that we wrote one for ourselves, which later ‘evolved’ to a sublime text snippet, since we use it a lot.
But a guide with patterns for using concerns would be great. DHH also pointed out that there are two kind of ‘concerns’ they use, one is just for organizing code (that will not be shared with another classes, so it’s just tidying up) and the regular concerns that you use to share code.
My personal experience with Concerns is that they are headache. I find them to be extremely dangerous and easy to make a disaster with them. I’m aware of Provide sharp knives and I’m cool with that. But I find it really important that we as a community tell people how to use those sharp knives, and how to not use them. For example:
- Should a concern know about the details of the model/class including it (e.g. a column name)?
- Should a concern know about other concerns?
- Should a model/class know about a concern’s methods?
- Should they be used only to break up large models? Or when else could they be used?
Is it something we can do in code to prevent disasters within Rails or is the only thing we can do to add better and more documentation?
I’m not trying to convince anyone but here I share some links about the disadvantages of mixins/concerns so that we are all in the same page:
BTW I’m open to give another chance to Concerns if there is a doc where I can point people when I see them being used incorrectly.
My two cents: concerns aspire to be independent modules. Meaning, they could be included or not in a certain class, and nothing would break. They are plug in. I always think “okay, what if this module wasn’t there. Okay, what if it was.” To try to make a clean interface.
Of course, as any piece of code, it can have dependencies. Depend on another module, another class, something being present in the included class, name it. To me this is a bit a question of software engineering in the abstract. Single responsibility principle, what’s public interface what’s private, dependency graph, and so on.
Second, to me Concern is an invaluable tool to get there “eventually”. I wouldn’t be a happy camper if I had a linter go “your concern is not perfect (perfectly independent). Please do more work because this gradual progress is unacceptable.” This sounds very dramatic, but I’ve seen tooling from JS land that has just horrified me, so I’m never too careful.
Hopefully this helps a bit.
I agree with this. From my experience when I see newly created concerns they seem pretty good, the problem is with their maintenance/extensibility. Soon there will be a requirement that will introduce bi-direction between model and concern or someone coupling N concerns together if not being really careful/having experience.
I think the main problem is that Rails “suggests” to use Concerns by creating the
app/controllers/concerns folders by default but then it doesn’t give any advice on its intended usage. And as I already mentioned I find them to be extremely dangerous. I’m trying to put myself in the shoes of a junior dev, let’s help them have a good experience in Rails and not end up with a mess because of concerns.
If we can help by not allowing anti-patterns then that’d be amazing (or maybe we can do this in Rubocop), but yes, the least that we can do is provide a document talking about them and providing best and bad practices…
It sounds like you have perspective on this that might be helpful to express in a blog post.
Apart from that, Betsy, what is the output on this whole topic? Is it something going to be done?
I think that your opinion of Concerns is a lot like mine, but Rails is a big tent and a lot of folks have very different opinions – just read this thread. So I think what’s to be “done” is for you to make as strong an argument as you can for your perspective in blog posts and the like.
I feel a lot of people are looking for help with handling complexity and growth at the domain model layer. Some of the techniques that come to mind are:
- Extract model logic into specialised POROs
- Extract model logic into a service layer
- Separate large models into compositions of smaller modules (by functionality / identity)
- Extract reusable aspects of models into separate mixins
- Identify and extract domain concepts into new models
- Separate the model layer into different bounded contexts
These are software design techniques, not Rails or even Ruby specific. Prescribing which techniques to use is a divisive topic. How to implement a given technique is also subject to individual preference and style.
Perhaps it’d be helpful to have documentation illustrating:
- Selected techniques and a sample implementation using modules / concerns
- Directory structure convention in a Rails codebase for said implementation
I completely agree. My point is that Rails is creating for us the
concerns folder but it’s not the
services or other folders suggesting structure/design patterns/whatever.
I don’t like to be insistent but I’ll try to make clear my point one last time (I promise ). I think the output of this topic should be either:
- Rails stays accountable for the
concernsfolders created by default when running
rails newand adds documentation on why are they creating them, thus avoiding confusion
- Rails removes the creation of
concernsfolders by default when running
rails new, thus avoiding confusion
@santib Thanks for those concrete suggestions!
Would you feel comfortable adding the documentaiton you proposed?