7 ms·
Rails Concerns: To Concern or Not to Concern
- stevebmark 6y agoConcerns are the best example of the flaws in Rails and Ruby. The fact that DHH came up with a mixin applied at runtime as the solution to organizing Rails apps is frustrating. Other programming ecosystems have rightly moved away from mixins and do-everything-dynamically, along with moving away from mixing data and methods that self-mutate that data. Having worked on large real world Rails apps, concerns are indeed a poor pattern in practice. They introduce hidden, untraceable dependencies, can clobber each other silently, make it difficult or impossible to understand where methods come from, and bloat classes into super coordinators, when "models" should only be data. Combine that with Ruby's horrible preference for metaprogramming and you get unmanageable code. PS: If you work at a company as big as Github that can afford to literally employ Ruby core maintainers, then you are welcome to reply with "but it works for Github!"
- cageface 6y agoI've been working on Ruby apps again lately after spending a few years in the iOS world. I don't miss iOS at all but moving back to a slow, dynamically typed language like Ruby after getting used to Swift is like trading in a Tesla for a Model T. Ruby was great it its day but I think we can do better now. Maintaining large Ruby codebases is no fun.
- ultrarunner 6y agoNo fun for you, maybe. And I can see where you’re coming from. I often find it very fun, though, which has prevented me from porting an API to another language like Go or (gasp) Swift. Ruby gives a lot of flexibility, and in my line of work (especially with covid mitigations) there are lots of immediate change requirements; flexibility is very important. That flexibility provides the ability to shoot yourself in the foot (and I’ve surely done it), but it also allows us to pull off events that have suddenly changed with little warning. I like that.
- theonething 6y ago> pull off events that have suddenly changed with little warning. Excuse my ignorance. What are the events you reference here?
- ultrarunner 6y agoI work for an event company, and in many cases much of it is orchestrated by Ruby code, including a few rails apps.
- theonething 6y agoaha. I wasn't sure if you were taking about events on the software side.
- ultrarunner 6y agoImagine the naming conventions on the software side :)
- joelbluminator 6y agoNot really sure what's Ruby's "slowness" has to do with anything? Were you having performance problems with Ruby or did you just throw in it being "slow" to prove a point? I worked on quite a few Rails apps for 6+ years and Ruby's speed was never an issue.
- joelbluminator 6y ago"Combine that with Ruby's horrible preference for metaprogramming and you get unmanageable code": Is it impossible to write maintainable code in Ruby or is it just teams of people with varying skill levels working under pressure and hard deadlines? Do you think the average Rails app is less maintainable than the average Node / PHP or even Java app? I'm not so sure.
- dhagz 6y agoIt's teams of people with varying skill levels under time pressure. Ruby is a language where projects can suddenly bloom with hyper-complexity if you're not careful. You really have to strictly adhere to a style guide and have seniors who can catch the violations automated checkers like Rubocop can't.
- joelbluminator 6y agoIt might be a bit more pronounced in Ruby, but I doubt this doesn't happen a lot in javascript / python / whatever language actually. You always better have at least a couple of seniors in each team that go over every PR and maintain the project's health. No getting around that no matter the language. Now languages like php / ruby / js are notorious for their low code quality but that's less about the language and more about how and where they're used: tons of startups, young people in the beginning of their careers, pressure to find market fit etc. I'd be surprised if .net / java / python projects don't turn into crap under these conditions. The worst code I've produced was written like that and I really doubt the tech stack would have made any big difference in the quality of code I produced.
- thedanbob 6y agoI tend to only use concerns in extremely cut-and-dry cases. And even then, I sometimes get annoyed with them when hunting for that one method which is tucked away in a concern somewhere. But sometimes they are the best solution for making sure a bit of shared behavior doesn't get out of sync between models.
- pugio 6y agoForgive the slight tangent but I'd like to talk about Rails in general: Just last night I was migrating an app from Rails 4 to 6.1 - I have been using rails since 0.9, but I think my long relationship is coming to an end. What I loved about Rails was that it built a web framework with the same basic idea as Ruby: optimize for developer happiness. Trying to use the webpack integration (released with Rails 5.1 I think) is a nightmare. Suddenly my clean Ruby world is polluted by JavaScript package hell, there are now two parallel asset pipelines with subtly different behavior, I can no longer reference JavaScript directly in my views, and the convention over configuration Rails approach seems to have been superseded by a tool with the most nightmarish proliferation of necessary configs that I've ever seen. To top this all off, none of this is documented well in any of the official Rails resources. The Rails JavaScript guide mostly focuses on their rails-UJS tool (which is fine, though also lacking in actual API documentation) and makes no mention of any of the webpacker stuff. The only docs I could find were in half finished pull requests in forked repositories, and some brief notes in markdown files. Before starting with Rails 6, I was excited to try out the new Stimulus.js, and hopefully the improvements derived from Hey.com. Now I want to tear out every bit of JavaScript integration from the framework and manage those assets entirely on my own.
- taf2 6y agoI spent a ton of time writing custom asset management in rails 2.x days. It was kind of fun. I think you can still use rails 3/4 style assists in rails 6?
- rajangdavis 6y agoYou can opt out of webpacker with --skip-webpack-install on the rails new command. If you're updating, you should be able to still use sprockets.
- temporallobe 6y agoI had a similar nightmarish experience migrating a few Rails apps from 4.x to 5.x. Because of the complexity and size of our apps, it took a few months to successfully complete and test. Luckily we had copious rspec tests with decent code coverage. I too dislike the troubling trend of not being able to directly access JavaScrips directly from the view; I am not sure why this is done, but it makes debugging much more difficult. More abstraction is not more better. In any case, we will eventually have to migrate to 6.x, so that will be fun.
- rubyist5eva 6y agoI've been doing Rails development for a decade. Concerns are probably the biggest code smell/anti-pattern I've ever seen in any application. It's used as a bandaid to "break up" classes which do too much (but you really don't, you're just hiding the complexity), or it's way over done and everything is magic and almost incomprehensible and unmaintainable. Overall, just a total nightmare to deal with. Would not recommend, and I always try to steer people away from using concers during code reviews.
- tomc1985 6y agoAgreed. Concerns break large classes up to an innumerable amount of small files. It becomes so hard to keep track of simple interactions because they are spread across half a dozen files and/or contexts.
- Axsuul 6y agoWhat's the alternative to sharing logic across ActiveRecord models?
- seancoleman 6y agoI think a different way of looking at the problem is that ActiveRecord models really shouldn’t have much, if any logic. Instead, logic should get delegated to other types of object, such as services, decorators, query objects, etc. While “fat models” is certainly better than “fat controllers”, I’m afraid it lead the Rails community astray with large-scale apps that required more nuanced architecture.
- Fire-Dragon-DoL 6y agoDon't put the logic in activerecord models at all. Not even the data. Use activerecord uniquely as a querying mechanism (read or write), don't use relationships and don't put validations in there. Create objects (aka behavioral objects, aka servoce objects) for the logic and create entities (plain ruby objects) when you need to pass around the data. Yes, you are essentially eliminating the entirety of activerecord. After 10 years of rails, you realize that is the only safe way to use that library. By the way User User::SignUp Are related. The behavior doesn't need to be in the same object, the namespace takes care of that already.
- irjustin 6y agoI'm an old dog. If I'm honest, Rails is the only thing I know (... I barely know a lot of things). Counter do DHH's and core Rails' pattern, I'm thin models and Service Objects (GASP the horror!) to handle business logic. Models become DAO-y. I had a lot of mental trouble handling different use cases for the same object. Like if an Admin vs User updates a post. The notification chains are completely different. So now my service objects look like: Post::UpdateByAdmin < Post::Base vs Post::UpdateByUser < Post::Base. So, in general, my concerns are pretty thin. Like the post only handle data grabs. Even then, I'm guilty of doing what the post says from time to time especially when I couldn't see far enough into the future.
- FpUser 6y agoI've never really had to program using Ruby but just reading this Concerns concept makes me shudder. Am glad that I do not have to deal with the code structured in such way.
- tobyhinloopen 6y agoI worked on Ruby fulltime in a large team and it’s as horrible as you imagine. One big ball of connected modules that depend on everything else. It’s not Ruby’s or Rails’ fault I guess, but it’s easy to screw up and do it badly. You can make some pretty neat stuff with it but it takes great care and a lot of discussions and disciplined code reviews
- deleted 6y ago[deleted]
- lipanski 6y agoAt the end of the day concerns are just Ruby modules and they are a core feature of the language. They are an acceptable style of programming. It all depends on the task, your team's size/maturity and the hard boundaries you'd like to enforce. The problem with concerns is that they can easily start leaking logic into other concerns or models and you've only got your team's conventions and common sense (which are all very soft boundaries) to steer you away from this. As a matter of fact, same goes for Rails engines - they make it very easy to call the parent app from within an engine and it's very tempting to do so at the cost of leaking logic and breaking these boundaries. If your team can agree and stick to a set of conventions in regards to concerns, there's nothing wrong with using concerns the way Basecamp uses them. If you prefer stricter boundaries, there are other patterns that you can follow (like service objects or ActiveJob or events). I personally use concerns when the behaviour tends to be very generic ("Paginates", "Cacheable", "SoftDeletes") and service objects for anything that touches the business logic.
- deleted 6y ago[deleted]