I noticed that too. But it renders and scrolls perfectly on Chrome. I wonder what's the difference?
Firefox is typically a lot slower than Chrome, but the performance difference this time is amazingly large.
Was bad in Firefox on Windows too (even to the point of me googling to find tab profiling tools for firefox out of curiosity, didn't find anything useful that's still active, so I've no clue what it is doing it)
We fixed in in Firefox 47, but the fix was deemed too risky to be uplifted to Firefox 46. That was probably a mistake. Anyway, Firefox 47 is going to be released in two weeks on June 7th. In the meantime you can remove the box-shadow from .widewrapper.main using the devtools, or you can use Firefox Beta (47) or Firefox Developer Edition (48), which you can get here: https://www.mozilla.org/en-US/firefox/channel/#developer
You see a simple line of code, and you can immediately say (assuming you know User is an AR model) what it’s doing. The problem here is that people confuse simplicity with convenience. It’s convenient (aka “easy”) to write this in your controller and get the job done, right?
Now, this line of code is not simple, it’s easy to write it, but the code is extremely complicated under the hood because:
- params must often go through db-specific coercions
- params must be validated
- params might be changed through callbacks, including external systems causing side-effects
- invalid state results in setting error messages, which depends on external system (i.e. I18n)
- valid params must be set as object’s state, potentially setting up associated objects too
- a single object or an entire object graph must be stored in the database
This lacks basic separation of concerns, which is always damaging for any complex project. It increases coupling and makes it harder to change and extend code.
This feels like the core of the argument of the whole post. It does not seem correct. In isolation, the call to User#create seems magical. But there's not enough context here to criticize it. We don't know enough to say whether there's inadequate separation of concerns.
No matter how we handle "users", we are going to need to do all 6 things in the list the author presented. No matter how we structure those 6 things, there is going to be a single entrypoint function that kicks them off --- end users won't be pushing 6 different buttons to drive them. So: what's the better design here?
I agree that this is not a good example of simplicity vs ease, but I think his core argument is still correct about what Rails is. (Whether you or I may like/dislike "What Rails Is" is, of course, another matter.)
The other way to look at Rails is that, as a framework, it has made a decision to have the model carry most of the weight for domain logic. In a "fat model skinny controller" framework, you're not surprised to see single lines of "magical" code like this in the controller, any more than you're surprised that each line of the route table masks thousands of lines of code that execute when a URL is matched.
This is very much not Merb's design. But that doesn't make it an invalid design; it just means that understanding a Rails app might best start with the models, not the controllers.
(There's a lot not to like about Rails! It's been years since I worked in it full time and I don't miss it.)
In 2016, with systems regularly decomposing into services for both perf and code management purposes, I'm trying really hard to find a reason to say this isn't an invalid approach except for what amount to toy problems (the kind where "if you don't know where you're trying to go, any road will get you there"). ActiveRecord being a mudball of "what X is" and "how to get X" is a really, really big problem, and my view of it as an observer--heavy in Ruby, heavy in avoiding Rails at all costs--is that it seems to be sourced from an unwillingness of the Rails community to consider that not everything is Rails. Services become intractable, as I note in my reply to your first post--and I don't even mean "microservice all the things", just the profoundly unsexy and unbloggable "SOA".
That DHH might even believe with a straight face enough of that essay to write its contents like an English major who just discovered the adjective doesn't really change that the universe is continuing to shrink the place in which his viewpoint can make sense. And, with it, goes Ruby's relevance, because of the heavy weight of Rails on the Ruby world as a whole.
The point I made is that this is all happening in your ORM layer, in ActiveRecord these concerns are not separated. Recent addition of Attributes API at least isolated coercion logic, but it's still part of the ORM, which for me is a mistake.
> This feels like the core of the argument of the whole post. It does not seem correct. In isolation, the call to User#create seems magical. But there's not enough context here to criticize it. We don't know enough to say whether there's inadequate separation of concerns.
There's enough context for me to start putting up the horns and cheering, because AR is one of the more persistent boils on my ass when I'm building things in Ruby (because I use Ruby for Ruby, rather than Rails, my frontends are all JavaScript and my services are all Grape). His last point is sufficient to me to demonstrate inadequate separation of concerns--the better design is the one that doesn't require an active database connection to know what fields the object has in it. Answering "how do I build an SOA without every service having a line to every database?" inevitably becomes "don't use ActiveRecord, ever".
What solnic has done with Virtus (which I use in all my projects, it's awesome, he's one of my favorite current Ruby people because of it and I'm sad that he may be leaving) is to return to the novel notion that an object knows what's in it. Dumb data objects are in almost every case a better long-term strategy, and solnic's frustration, if not expressed perfectly, is one that inevitably burns even Rails projects that grow to scale. And while this is a single example of Rails's monolithic nature choking out a lot of the Ruby ecosystem, it's not the only one (see his comments on ActiveSupport).
That's a totally valid point, but is 100% orthogonal to what's being discussed. Invoking a single command to validate, run callbacks, persist to the database, etc, etc. a model (and the larger argument of whether conflating DB access and persistence logic is a good thing) has nothing to do with whether the object is aware of it's own properties.
They are both critcisms of ActiveRecord, for sure, but quite a bit different in content. One (AR objects not knowing their own properties) feels, at least to me, like an unfortunate early design decision, while the other (encapsulating everything involved with saving a model in a single statement, "magic avoidance" be damned) is very much in line with the core philosophy of ActiveRecord and Rails.
> a single object or an entire object graph must be stored in the database
Hence "the last point" (though you might have caught me mid-edit). I view these as functionally the same problem: not only are you instantiating the object, but it must immediately go to live in the database or it's useless.
But you're right in that it is a philosophical problem. Rails is wrong. =)
There are always pros/cons to any approach one can as easily argue that without AR your code is less DRY as you need to keep your models in sync with your DB schema manually. (I am not a fan of AR either)
That's not really a unit test and not really a good idea to do it this way. You'll still have to keep model in sync with schema you'll just know when they diverge.
This might no be the the best example, but this is not a Medium blogspam, the guy has wrote several widely used gems and we should not stop at this technical example to invalidate the whole points he is trying to make (and I don't consider this code to be the core argument of the post.)
In Django, the validation & type coercion would typically happen in a Form object (or, if you're using Django REST Framework, a Serializer). That step at least is outside of the ORM and seems much more explicit to me.
Also, in Django models are explicitly defined. There's no ActiveRecord magic of reading the database to define the model. Which is not to say that AR's approach is bad or wrong, but it is pretty significantly different from Django.
I had a hard time understand how Rails works under the hood by reading the source. No such issue when reading Django source code. Rails magic is really powerful and I got overwhelmed. Maybe its just my Ruby-fu is not strong.
I get the feeling its not your Ruby-fu, but Rails is a lot like trying to jump into the show Supernatural in Season 10. I did some Rails sites early, and now have very little clue what's going on when I read new code. I'm sure I could get it, but its going to be a time investment. This seems to be the way of opinionated frameworks.
It's been awhile since I looked at either but I remember as a beginner I had trouble parsing both the Django source and the Rails source. The rails source was the hardest because I didn't understand ruby and the Django source was hard because I didn't understand python.
I feel like people really forget what it's like to be a beginner when they say "read the source".
I haven't worked with Rails, but have worked extensively with Django and this doesn't seem to be the case. Even though Django is very similar to Rails in some ways, to pretty big differences is that Django seems to be much more explicit in general and (I might be wrong about this) Django seems to be easier to use in a SOA since your controllers (views in Django) are not as tightly coupled to your models.
That's correct. Around the time that Rails became popular, Django was undergoing a major refactoring to remove "magic" and make its underlying logic more explicit.
Further smaller changes have been made since then for the same purpose: explicit over implicit, code or configuration over convention is part of Django's philosophy.
IMO that also makes it easier to graduate from a beginning to an intermediate level use of the framework because while there are sane defaults in many places, in others you're required to define your specific implementation explicitly from the start. It's a tiny bit more code up front, but all the details are exposed and it's obvious how to override default behavior. And at the same time the framework supports keeping your code reasonably DRY and takes care of much of the tedious, repetitive stuff.
There's still tight coupling in some places (ModelForms, for instance, are arguably part of the controller layer and are tightly coupled to the ORM). But they're reasonably optional (you can use plain Django Forms instead of ModelForms in your views or not use the Forms library at all.)
This argument often comes up and I'm genuinely curious why people think Django is less "magic" than Rails, in my experience it has been the opposite.
My experience with Django (for instance: class-based views and admin parts) is actually that you have dozens of magical classes or methods and if you don't know them all, you're screwed. Often when I try to do something, many aswers on StackOverflow boil down to "just override a_method_that_is_hidden_somewhere()" or "just use ListButWithSpecificBehaviorView(), easy you see?".
Are there any specific example you have in mind where Rails do something magical that requires more code in Django but where Django is more explicit?
PS: not trying to start a flamewar, both are OK-frameworks, bla bla bla ;-)
My problem is whenever something spooky doesn't work, I never know which part of the source to read through. You need to understand the architecture to even know where to look. Which means you have to go through a huge up front process (like reading a webseries on the subject) to even get started. This front loading is the kind of thing that keeps more people from getting into programming, and is one of the primary ways we keep our salaries high.
I agree with the author that abstractions should be optional, whenever possible.
However, just because something is heavily abstracted doesn't mean it's a bad approach, at least from a productivity standpoint. Without certain things being heavily abstracted, we'd go insane.
Just as
User.create(params[:user])
gets translated to thousands of lines of Ruby, so also
CoolClass.new('foo', 3)
gets translated to thousands of lines of C, and
printf("It's %d degrees today in %s.\n", temperature, city);
gets translated to thousands of lines of assembly.
Are they all heavy abstractions? Yes. Is it oftentimes very nice to be able to use heavy abstractions? Also yes.
There was a recent article about Julia that discussed how a printf in C translate to very few instructions in assembler.
Also I would like to point that "translates" is a little misleading word. There are two ways of implementing an abstraction from a higher level system to a lower level one.
You can generate code or you can write a runtime framework that does the work dynamically. Although from the higher place both may seem the same, there's a huge difference between them that has consequences.
And most important, a call is not the same as the implementation of the called function, my point to begin with, please see my comment in the context of yours.
Per cloc it's actually 1093 lines of C (plus some more in the printf.c file), and generally speaking hundreds of lines of C is the equivalent of thousands of lines of assembly.
In any case, the complexity of the called function is exactly what we're discussing — it's why the author objects to "User.create(params[:user])"
The link to that article is below. printf in C tranlates to a few lines of assembly in preparation for a call to sprintf. That in turn will have a lot more instructions in assembler.
To me the point isn't so much separation of concerns as it is separation of side-effects.
printf has a well design side effect (printing to stdout). Coolclass.new has an expectation of an instantiation of object in memory. If Coolclass.new also called an external service, then that would be a violation in my opinion. Thankfully, we generally don't do that.
User.create is not only capable of tons of side effects (just like Coolclass.new) but it is encouraged to do so (via callbacks and such).
Better design? In all seriousness Django - they get this right. It seems to hurt rails developers that it means typing a bit more, or is a little less 'magic', but then python did always attract software engineers, whereas Rails always seemed to attract code "ninjas" at best.
> No matter how we handle "users", we are going to need to do all 6 things in the list the author presented.
I think maybe your broader thesis is we almost always need all 6 things. And if that's true for you then Rails is a good tool for you.
If we only ever need one out of the 6 things at a time then ActiveRecord is only adding extra complexity for us.
I think OP is basically saying I usually only need one or two and that they'd rather not have the extra layer of indirection... "save(andValidate)" is fine for them. They don't need the orchestration abilities that the declarative "afterSave(validate)" step affords.
DHH's suppress really is a good example. If you are calling save(andValidate) everywhere, you can't really do something like suppress(), because your validation logic is disbursed.
My opinion, and I think maybe OP would agree, is that there's usually a nice, composeable way to get the same problem solved, without resorting to a giant engine that understands all the different parts. But that's just an empirical assertion on our part. Obviously your mileage will vary.
This should come at no surprise, although I don't see anyone criticizing Rails anywhere.
I've never written a line of Ruby, but trying to read Rails code evokes me all this: it seems like a framework created with the sole purpose of hiding everything possible from the programmer.
Conventions is something I try to avoid at all costs. Conventions are usually things that are hard to find in documentation. Conventions are things that every experienced user says that "oh, this is common knowledge" and conventions are the reason why things seem to work magically.
Obviously if you follow a framework from day 0 you don't even notice it. For newcomers, it's a source of frustration.
Frameworks should be designed for experts as well as newcomers. I was a Ruby-only developer and, after starting a full time Rails job, picked it up quickly enough.
That's not really what convention refers to here. Rails' motto "convention over configuration" simply means that boilerplate should be avoided, and that code should use sensible defaults whenever there isn't information.
For example, ActiveRecord class names map to table names through a simple pluralizer (UserProfile -> user_profiles). That's a convention, no configuration needed. Just write a class and off you go. You can override this behaviour, but you can also write huge apps that just follow the convention. Other frameworks would typically make this mapping explicit.
You do need to read the documentation to see what the conventional behaviour is, but it's not very deep knowledge. It's not much worse than other frameworks, where you need to find how things are configured.
My experience is that programmers migrating to Rails are thoroughly confused by these conventions like "UserProfile -> user_profiles". Although it's only the second-biggest source of confusion after ActiveSupport, e.g. "10.hours.ago" even though the integer class does not have an hours method according to the Ruby documentation.
Is there a problem? If they don't know, there's not much harm. But surely this is part of the learning process. Understanding leads to enlightenment. There's certainly evidence that tons of developers using JavaScript don't know how classes work.
I can call methods on objects in most frameworks/libraries. The fact that I don't know if .trim() is a core Javascript function or part of jQuery isn't a weakness of jQuery. If a "developer" can't be bothered to consult documentation when they work on a slightly different project than they're used to, then they're in the wrong industry.
It's definitely a issue, but I think it's far from the biggest issue. If you're going to use ruby, you're going to have to come grips with the culture, which for better or worse involves more "magic" and meta-programming than, say, Python where the same power exists but is avoided on principle.
It takes a little getting used to, but once you are, then the tooling is there to help you make sense of these things:
1.method(:year).source_location
The bigger issues with Rails I see are the monoculture issue raised in the article, plus the intractable issues with ruby around performance, memory bloat, concurrency, and last but not least, the multi-paradigm nature giving you functional features, but without any of the usual immutability guarantees (unless you follow a constrained and unconventional coding style which no one does in the ruby community).
Yes 1.+(5), 5.-(1), 1.*(2). Ruby is probably the most object oriented language out there, besides Scala(which borrows from Ruby. Which borrowed form Smalltalk). Keeps syntax rules to a minimum. Where is something like Java 1 + 1 is a special syntax case on primitive types(primitive types in hindsight were a terrible decision). In Ruby methods can be called with spaces and without parenthesis. So 1.+(5) is the same as 1 + 5.
But is that any different from any other system, where you have to learn how things are put together? For example, Java projects frequently use Maven. You need to download and learn Maven to understand how it's put together.
You can explain those two things you mention in a few seconds ("Ruby allows adding new methods to anything; the 'hours' method is defined by ActiveSupport"), and then the confusion has been eliminated. That leads to an increased understanding of Ruby.
FWIW, I've had a whole bunch of junior colleages learn Ruby, and those things were never a point of confusion. If anything, I have the opposite experience; Ruby and Rails are superb for newbies because of all the sane (convention over config) defaults.
Unfortunately, one segment of the Rails developer culture has perpetrated a lot of ugly overdesign (mini-frameworks such as Devise, ActiveMerchant, etc. that inject themselves into Rails in brittle ways) that certainly will confuse newbies. But that's not Rails' fault.
Explicit configuration may teach a new developer about a codebase, but it also means that there's more upfront work when developing. If the conventions are already there, in the form of good developer habits and good workflow, it's more pragmatic to encode them as explicit conventions, rather than introduce lots of un-DRY boilerplate.
And if conventions don't change :) If a team can follow conventions it's a good thing, but I personally favor explicit code that does nor les nor more than it says. I do use frameworks, but I always pick the minimalist ones where I can see the chance understanding what goes on under the hood.
Your complaint is more about implicit vs. explicit. Implicit behavior is bad when it's surprising. When it's what you would have done anyway, then making it explicit creates an unthinking, tedious ceremony that you repeat daily.
Some of my favorite Rails devs are former Python devs. They appreciate conventions and the freedom they give you.
Rails has plenty of critics. You just aren't looking hard enough.
The most common criticisms are: it's slow and it has too much "magic."
At the end of the day, it comes down to this: every framework has its pros and cons. When you use a framework, you gain certain benefits but sacrifice certain things and have to conform to the framework's opinions. In the case of Rails, the primary benefit is extremely fast prototyping. But that's only possible because the framework hides a lot of complexity from you, which can bite you in the ass if you try to go outside its conventions.
This. One fine example is Gitlab: It's full of features and does many nifty things. But it's painfully slow and the developers now have a hard time trying to fix this.
The slowness is not due to Rails. It is mainly due to us not scaling up the infrastructure team fast enough and now having problems with the file serving backend. We're working on it in https://gitlab.com/gitlab-com/operations/issues/42
Rails developers are spending more time fighting Rails these days than improving it. I have the feeling that good coders have left the ROR ship and that Rails is now the framework for code-schools and learn-to-code bootcamps. It's a bit sad, but as long as Rails is tied to Basecamp I don't see any solutions.
The author is right, competition is important, the Rails/Merb scenario is the open-source version of Microsoft E.E.E
Really, even if it weren't tied to Basecamp I think if DHH remains as Rails' BDFL, we won't see the type of changes a lot of developers want to see. Which just means we need to highlight other frameworks like Hanami, Trailblazer, et al. in Ruby user groups.
This isn't a Rails gripe. He only seems to know Ruby/Rails and lashes out at it. Frameworks = Lots of abstraction. At least the abstractions in Rails aren't leaky.
solnic wrote the majority of DataMapper, its successor rom-rb, and the Virtus object modeling library. He knows much more than Rails and understands its problems.
Not to take away from solnic's many valuable contributions to open source, but I think it would be more accurate to say he was a heavy contributor to DataMapper rather than that he wrote the majority of it
Yes, I was on the core team between 2010-20#{hard-to-tell}. DataMapper was created by Sam Smoot and quickly taken over by Dan Kubb who did a crazy amount of work, practically rewriting it and introducing all the crucial features, and then maintained it for a couple of years with the help from a small group of people.
This is correct. It's probably hard to measure a person's total contribution to DataMapper because the gems are spread out across 20 to 30 repositories, not just dm-core.
I did maintain DM for a few years, but burnt out as there wasn't enough time to keep up with the community demands and work a full time job. There were a couple of years I effectively worked 40-60 hours a week on DM and only 5-10 on work; this wasn't tenable long term and burned me out.
The small dev team, of which solnic was a core member, are an amazing group and there's no way I could've maintained DM for even a fraction of the time I did without their support.
I personally can't wait for Rails to be a distant past. So many start-ups got burnt badly by using Rails -- easy to start, hard to scale, maintain, and extend. Rails is too opinionated and if your use-cases don't fit into "Rails way" your screwed.
But at least it got them started and they could understand if there is a market for their product. My bet: if twitter started with Java Struts (it was 2006) they would have had to spend so much money and have needed so much time to launch that we would be using something else now. Not necessarily a system bootstrapped with Ruby, but you got the idea.
> if your use-cases don't fit into "Rails way" your screwed
Of course.
If a startup service doesn't fit Rails, they should have picked something else. I'm not using Rails for everything.
Startups usually try on a bunch of use-cases (features, ideas, workflows) before they gain traction or die. Your saying that startups should know all the use-cases they plan on building before they even start -- that simply impossible. Maybe your point is that startups shouldn't use Rails and its more suited for dev projects with a clear spec.
Not really. Rails is good for quickly hacking things together across a very wide range of the domains that startups usually play in, which makes it as good as anything out there when upfront productivity is the priority and you have rapidly evolving specs.
The only really common startup use case it's decidedly bad at is realtime/sockets/streaming data, where Node takes its place as the hack-it-together tool of choice--at a significant productivity penalty compared to Rails.
It's also, of course, pretty bad at all kinds of tasks unrelated to web development or REST apis. You wouldn't want to write machine learning algorithms or do statistical analysis in Rails, just like you wouldn't want to do 3d game development in Rails. And while you do occasionally see startups who have bolted some heavy data processing or pseudo-ML monstrosity onto their Rails apps, I've never seen anyone in the Rails community claim that was a good idea. The vanilla recommendation there is to keep your main server stack in Rails and then write services in something more appropriate for those needs.
Your also implying that easy to get started and ( scale, maintain, and extend) are mutually exclusive. I am saying they are not and don't have to be. Moreover, this kind of thinking just proves the point of why we need to move of from Rails.
Move from Rails into what? Nobody is disagreeing that Rails has problems, but until there's a battle-tested replacement out there with a similarly strong community and range of libraries it's all just theorizing.
I've always heard people blast Rails b/c of Twitter's experience but Twitter did survive it and scale. Maybe Twitter would have never gotten to the level of success they did without using Rails? Also, I'm not convinced that the original developers at Twitter did a great job implementing the first Twitter infrastructure. It is possible to write bad code using Rails that would be bad no matter what language or framework was used. It's a huge unknown in that story that entirely changes how to judge the outcome.
Back up what you're saying. Rails built a lot of extremely successful companies. It is not hard to scale or maintain if you are competent. If you scale beyond the capacity of Rails, you are Twitter and it's ok to move on.
I am seeing good amount of comments saying "Twitter did it", this is simply a logical error (survival bias). Moreover, I think Twitter would of been successfully even without using RoR.
I'm somewhat split on the author's opinion here. I also picked up Rails back in the day (I think the first version I installed was 0.8), and I have a bit of a love/hate relationship with it.
As a framework for building comventional HTML templated database backed websites I still think it's near unbeatable, especially with the addition of a few common gems. However it so often gets shoehorned into other places - API backends, rich client apps, and massive systems. Places where the Rails conventions rapidly go from everything falling into place to getting in the way and needing to be worked around, or heavily tuned.
I completely agree that ActiveRecord is the core of why big Rails applications are complex to work with and often exhibit disproportionally poor performance. It doesn't lend itself well to composition, and results in data persistence being intertwined with business logic. That's fine for early prototypes, and in all honesty will get you to market quickly, but it makes extracting the concepts you discover during development into a coherant API much more complex than I'd like.
These days I still use Rails for the aforementioned HTML generating web applications, but it's often acting as an API client to systems built on top of a Grape based backend, with an API built around service objects and a simple data access later.
Interesting you bring up the point about API backends. I'm the author of Nodal [1], with the goal of bringing the best design patterns and practices from Rails and Django to the world of Node, focused completely on building a decoupled API layer. There is no view / template logic at all.
The project is very lightweight right now (benefits of being a young project with a sole full-time contributor), but I'd be interested to hear your feedback as to what you think is or isn't necessary for continued development. :)
Interesting, I think I came across Nodal while evaluating options for a side project a while back. Having just taken another look the big thing that seemed to be missing was something to serialize objects to JSON, although that may be because serializing objects is so trivial on JavaScript anyway. There also didn't seem to be much documentation about the operational side of things, most glaring was nothing being said about how the scheduler actually schedules jobs and ensures they get run.
Scheduler is actually still a WIP. I've changed the core around significantly in the last few releases, which has changed how the scheduler operates. That's why there's not much around it. ;)
We serialize models to JSON automatically in the response layer, and all models have a `.toObject()` method that takes an optional interface (which keys to actually serialize).
There is full API documentation but I still have a lot of work to do creating more fleshed-out tutorials. :)
The issue I have with just having a toObject or to_json method is that context is everything when serialising. Different access levels, different client types, and just different parts of an API call for different ways of sending data to end users.
Which is why you very clearly specify the interface whenever .toObject is called (which fields are exposed). By default, everything is included, but you have complete granular control. It's what allows us to do things like have full GraphQL support. :)
Although I may not agree with your perspective entirely, but I respect it.
I think everyone has different needs, and you have your personal needs which Rails no longer satisfies, so you are moving on.
Rails still solves a lot of problems for a lot of people I believe. I work as a consultant for a few companies and in some cases I see people losing time and money on what would be resolved immediately if they had just made the right call by using Rails.
Good luck on your journey, and remember the rails community will always have its door open for you :). Your projects on github look exciting, I will take a look at them. Very cool stuff!
Reminds me of Zed Shaw's critique of Rails[0] which explains many of the short comings of Rails. Zed wrote the mongrel server for rails. Assume this article is massively politically incorrect & vulgar as hell, just as a heads up. Really good read though, and does explain some of the interior politics of rails and how it evolved.
This article is nothing like "Rails is a Ghetto". Zed's rant is 90% personal feuds, drama that is practically completely irrelevant today. The article being discussed is 90% technical critique.
> This article is nothing like "Rails is a Ghetto". Zed's rant is 90% personal feuds, drama that is practically completely irrelevant today. The article being discussed is 90% technical critique.
True. And yet, it reminded me of that article Zed wrote, which I summarized as a vulgar critique of the internal politics of the rails community.
I too have stopped using Rails. To other Rails refugees, I highly recommend the up-and-coming Phoenix Framework for the Elixir language: http://www.phoenixframework.org/.
Simple as in simple, fast, productive, beautiful Ruby-like syntax. Favors a functional and immutable workflow over object-oriented and mutable spaghetti code.
Spun up my first Phoenix toy project 6 months ago and fell in love. You can really tell that a number of the core contributors are/were rails contributors, it carries over a lot of its strengths and tries to learn from its failings. Could really see Phoenix replacing Rails some day.
The creator of Elixir is in the Rails core team and helped (wrote?) write Rack. The creator of Phoenix built Rails apps for quite a while before finding Elixir—their experience definitely helps because they take what is good about Rails but know which "pain points" to improve on.
How's the community and library ecosystem looking in Elixir/Phoenix?
It sounds great in principle. I'd love to move from Rails toward something more functionally-inspired, but I worry that lack of libraries and google results is going to be a net productivity killer over the Rails + evolving into micro-services approach.
I've been trying out Phoenix, and it seems like the top contender for a Rails successor. It's not quite as fluent as Rails, but it's close. But I'm curious: since it is so much like Rails, won't it suffer from all the same complaints as in the article? It is still a monolithic, "Phoenix is your app" kind of framework, isn't it? Isn't the Devise-but-for-Phoenix library going to require Ecto? I think of Phoenix as just "Rails but faster." How is it different from Rails in ways the article author would appreciate?
(Edit: Btw I happily accept Rails' monolithic nature for all its conveniences, and I don't really identify with this author, but I'm curious to hear your opinion whether Phoenix would be a good fit for him.)
> A new phoenix application is not a monolith. The `phoenix.new` generator generates a regular Elixir application for you that sets up a default Endpoint worker in your supervision tree, as well as a web directory to put phoenix related files (routers, controllers, etc). wrt to collective process, we add `worker(MyApp.Endpoint, [])` into your supervision tree, so we do exactly what you are wanting. Building a Phoenix application is building an Elixir application, not the other way around. Your phoenix dependency and related workers are just one component to your larger Elixir/OTP infrastructure. Note: Lance Halvorsen, who gave the "Phoenix is not your App" talk, is on the Phoenix core team. We have been pushing these ideas since the beginning and as Lance I and laid out in our ElixirConfEU talks, we're taking a stronger stance on isolation with upcoming changes to guides and phoenix resource generators.
I think it's really quite a testament to Phoenix that so many people think it too is monolithic. A client can request a Phoenix application and I can get productive immediately without worrying about creating an unmaintainable, unperformant mess. No wasting 2 days on configuration hell. I can even jump into an existing project and be productive.
Another point is that the libraries around Elixir aren't (in my experience) Phoenix-focused or obsessed with magical Phoenix integration. In most cases, things work well together. Just call functions.
Monkey-patching, thread-unsafe operations, and uncontrolled shared global state are all non-problems in Phoenix. Decent code architecture and testability aren't usually a problem either because proper separation is enforced. Functional/immutable programming makes a huge difference here too.
Ecto 2.0 is really what ActiveRecord should've been. It's incredibly well thought-out. I suspect the author would be really pleased with Ecto.
Finally, Phoenix favors simplicity over ease in most cases. Complexity is not hidden in 100 layers of abstraction and callbacks.
The author also mentioned DHH's... colorful personality. So I'll take this opportunity to mention how much more welcoming and humble Jose Valim and Chris McCord are.
Phoenix is very Rails like in the way it makes developers work and very un-Erlang. I mean: Phoenix apps are monoliths and not loose collectives of processes with an explicit http process.
It starts with the right claim but it ends with workers inside Phoenix. Instead the router and the http server should be at the same level of the other workers. Actually, they shoul be much less important, an implementation detail.
A new phoenix application is not a monolith. The `phoenix.new` generator generates a regular Elixir application for you that sets up a default Endpoint worker in your supervision tree, as well as a web directory to put phoenix related files (routers, controllers, etc). wrt to collective process, we add `worker(MyApp.Endpoint, [])` into your supervision tree, so we do exactly what you are wanting. Building a Phoenix application is building an Elixir application, not the other way around. Your phoenix dependency and related workers are just one component to your larger Elixir/OTP infrastructure. Note: Lance Halvorsen, who gave the "Phoenix is not your App" talk, is on the Phoenix core team. We have been pushing these ideas since the beginning and as Lance I and laid out in our ElixirConfEU talks, we're taking a stronger stance on isolation with upcoming changes to guides and phoenix resource generators.
I said this before: phoenix is the new Rails, and that is not a good thing. Phoenix will end up bogged down with the same great "ideas", hex will end up chock full of crap like gems.
Elixir ok, phoenix not so much.
askyourmother, while you're busy putting down other communities and folks' hardwork, we'll continue building the future. Comments like these aren't welcome and add zero value to the conversation.
If you want to rebuild Rails in elixir, go for it. Seems like a wasted opportunity though - to break away from all things Rails.
And yes, phoenix will end up bogged down like Rails, and hex will end up chock full of crap, it is the Rails developer mentality I'm afraid, they just can't help themselves.
Have you tried Phoenix?
I can see some similarities with Rails, but Phoenix's components are way more decoupled. In my current app Phoenix is handling the websocket messaging stuff. All the real logic is handled by Elixir modules and apps that have nothing to do with Phoenix.
I like to think of Phoenix as an interface to my app. It's less intrusive than Rails.
You don't have to use Ecto (the "ORM" thingy that is actually not an ORM) to get get the full power of Phoenix, it's also decoupled.
Regarding Hex, it's like every package managers out there. Sure you can publish anything. Rubygem is full of crap, npm is full of crap etc.. But I can also find some very small and focused libraries that wouldn't have been published, had a quality filter been setup to publish anything.
Understood but to make me clear: I'd like to see Phoenix as part of an umbrella application and not it starting other applications as its workers. It should be a peer among peers and not the boss. However, as Rails demonstrated, the current approach is very convenient so I can hardly criticize it too much at this stage of Phoenix adoption. I think it helps the onboarding to the platform.
Phoenix v1.3 is adding an `--umbrella` flag to the `phoenix.new` generator for first-class umbrella support out of the box. In the Phoenix book we also have the reader breakout their application in an umbrella for the domain bits and a web app for the phoenix bits. Umbrellas have been a little underserved in the community so far, but stay tuned for future improvements around this.
What I'm trying to understand is why all these coding academy students are learning ruby on rails:
To make them have to go back to coding academy school in two years?
So that they maintain legacy codebases and don't touch the new shiny features the experienced engineers are working on until they get their training wheels off?
Because there is actual demand for ruby on rails despite all the hate and sunsetting of rails I see on HN?
HN is a place where people who are on or fancy themselves on the bleeding edge of tech congregate. It shouldn't be surprising that the opinion of that group, with the selection pressure it experiences, is dismissive of anything that's closer to "stable, mature project" than "hot new thing".
You're making the mistake of assuming that what people talk about on HN/etc. is correlated with the state of the industry. Tech forums are always going to be focused on news and up-and-coming things, whether or not those up-and-coming things actually succeed at displacing the technologies they're aimed at displacing.
Also, and I'd love to see actual demographics on this but I know it's impossible, while lots of posters on HN/proggit/whatever are professionals, a lot of them are also high school or college students that are still coming at it from a hobbyist perspective (i.e., focused on what's new and exciting rather than engaged in the relatively boring world of getting paid to solve other people's problems). For that matter, a lot of the professionals approach their work from a hobbyist perspective (not necessarily a good thing for their customers).
I don't mean to sound like I'm down on hobbyists or students at all, just that different people care about different things, and just because most HN posters know a lot about the technologies they post about doesn't mean they know or care about the actual state of the industry (just their corner of it)(that applies to me too of course, we're all like the blind men and the elephant).
I can't speak for other cities because I haven't watched their job markets enough, but anecdotally in Chicago I've seen it break down mostly like this:
Big companies use enterprise Java unless they're stuck with a legacy VB/ASP/Coldfusion stack, with C# less commonly.
Fintech companies use a mix of C# and C++.
Small companies started before ~2010 use PHP, with Rails less commonly.
Small companies started after ~2010 use Rails, with hipster Java (Scala/Groovy/et al) less commonly.
I can only remember offhand seeing one job ad for a company using Sinatra instead of Rails for their Ruby stack.
Any decent coding school should teach the basics, so that learning a new framework or language is, if not trivial, then at least something you can pick up on your own.
Ruby on Rails is mature, widely adopted, and reasonably stable. Just like the then-dominant Java web stack was when Rails was getting going. There can be expected to be Rails demand for some time; that doesn't mean its not losing currency, just that that isn't an instantaneous process.
I can't speak for others, but I run a very small 'academy' alongside my business and I picked Rails for them to learn for the following reasons:
1. it's easy to get something up and working, which for a lot of students helps keep them motivated
2. Hartl's Ruby On Rails Tutorial. So far, it's the best book/course on how to get from knowing pretty much nothing to being able to work in a 'modern' dev setting (good editor, git, bitbucket, testing, backend, front-end, etc.).
3. if they want to actually get a job as a junior dev somewhere else, I've found that joining a startup or company that uses Rails is pretty easy. Much easier than jumping into a front-end React/Redux shop, for example.
I do not necessarily intend to use Rails actively with them in their first projects, and for those who can and want to I'll probably have to introduce them to the complexity and horrors of front-end javascript development, but at least with the Rails Tutorial they can get started by themselves and learn some degree of 'best practices'.
Having little experience with Rails, it's the tone of that "Crazy, Heretical" article [1] that really strikes me. That tone where you're laboring to describe something that really truly does make sense when you're in the company of a bunch of people that just don't want to hear it.
There's too much purism in those kinds of arguments, arguments that really are more about spectrums. It sounds like Rails is really great for learning the shallowest 40% of a wide variety of programming concerns, and a lot of web solutions for small clients aren't ever going to dip below that 40%. And as soon as you get beyond that 40%, asking questions like "but what if it doesn't make sense to do it that way?" and "what is that weird runtime bug that doesn't happen in my development environment?" and "why can't I refactor without being scared I'll introduce a weird regression bug?" then it's totally fine to be attracted to the idea of static typing, compilation, and libraries/frameworks that are more explicit.
The main difference is that Django does not rely on monkeypatching or magic methods, and for me the separation of concerns feels just natural in Django.
When I started with Rails it felt like magic, you didn't know why things worked.
I was quite happy to walk away from the Ruby on Rails world 4 or 5 years ago. I basically escaped before the onslaught of Rails 3.0 and what came next. I think somewhere around the adoption of coffee script I got pretty concerned.
While at Google I became aware of Go and what that looked like at scale. I would highly recommend trying out Go. I think the simplicity will be a refreshing change but there will also be some familiarity coming from the Ruby/C world, can't quite pinpoint why but just feels that way.
I used Rails mostly for small or medium sized projects, one or two developers teams, all of us freelancers. It's the perfect tool for this kind of work. We can deliver quickly, send invoices, move on to something else or come back later to add features.
Do projects get complicated? Yes, some of then. Mainly because most customers pay for features and not for refactoring or design, which they don't understand (remember, no in house technical staff). Try to sell them a new page with attached the price of a major refactoring... good luck with that. So sometimes features get kludged together because of budget constraints. I have projects with suboptimal UX (understatement) because they rationally decide to make tradeoffs between usability and costs. It's their privilege. I bet this would happen with any language or framework. Your customers could be more long sighted than mines, I hope they are.
So, would I move away from Ruby and from Rails? Yes, when customers won't like starting a project with Rails anymore. This means that other tools don't have to cost them more. Do I care about Rails architectural shortcomings? A little, but I appreciate its shortcuts more. They work well in my projects.
This is my takeaway from Rails. Good default for your 1.0. Frankly, I would probably use Rails even if I was starting a startup. It's easy to hire, easy to talk about. Heck you will often find graphic designers who have played with Rails.
Choosing Rails will definitely lead to problems in the long run, but at least they are well understood problems. You're going to do an in-flight replacement of your 1.0 eventually anyway. You just need one grayhair on the team to steer the younglings away from the worst abuses and you'll have a stable, if clunky, platform to build on. It's the definition of mitigating risk.
Java and C# are of course equally boring, but I think the fact that Rails is culturally open source provides a huge benefit over them.
JavaScript, Go, Haskell, etc are arguably better if you really understand them, but they're research projects. Lots of great pieces of code, but the story of how to use them together is still being written. I would use one of them if my intention was to hire slow and keep my dev team fewer than ~30 people in the long term.
Yes, I'm talking about the consensus web development framework around Node, to the extent that there is any. Same for Go and Haskell. Obviously all three are mature languages.
The Go community is just not that big into web development. There are web frameworks (eg. Revel) but they're not seeing that much traction. I truly love Go but I just don't think it's a good building material for more than a JSON API - for which it is awesome BTW.
Can't speak about the Haskell community though. To the extent I know the language I probably wouldn't want to use it to create HTML forms, either.
Haskell has a healthy and growing web ecosystem, from larger frameworks like Yesod to leaner ones like Snap, Scotty, and Spock. Servant is also looking promising as toolkit for building both API servers and clients. And GHCJS lets you write your frontend code in Haskell as well, if you so choose.
What you're missing (at least with Node.js/Javascript) is that Node does not aim to be Rails. Node doesn't aim to have one correct way of doing one thing as Rails often does. Yes, there are best practices, but Node aims to give the developer the freedom to do things as they need to.
The result of this is that, yes, development of your standard CRUD app is probably not as fast as it would be with Rails. Also, moving from project to project is not as easy as it would be with Rails. But the advantage is that, if you have good developers who are good at architecting (a big if), you architecture will better reflect the problem at hand.
No, I'm aware of that. I love Node and npm and UNIX and I use only small single purpose modules and its amazing. But I am effectively a research engineer. And honestly, if you want your company to run on Node, you need to be a research engineer too, because "which infrastructure should we use?" is an open question in the world you describe.
Compare to Rails, where you start of with OK infrastructure by default. That's not better, it just means you can hire a random person off the street and they're on the same page as you. If you want to keep a team of 50 JavaScript developers on the same page you need a really strong culture. Or just say "Use Ember and Express, end of story". But at that point you no longer have the "developer freedom" you correctly cite as the core selling point of Node.
And by "on the same page" I mean "we both have a similar understanding of a sensible default way to transport persist text fields from an HTML form". Put 10 JavaScript programmers in a room and you'll get 8 different approaches.
> The result of this is that, yes, development of your standard CRUD app is probably not as fast as it would be with Rails. Also, moving from project to project is not as easy as it would be with Rails. But the advantage is that, if you have good developers who are good at architecting (a big if), you architecture will better reflect the problem at hand.
And if you just want something to work quickly, Rails wins. JS encourages developers to spend days and weeks on picking each part of a framework for an MVP that may go nowhere. Rails is no longer the new shiny and it has moved into the 'get shit done' category of developer tools.
No. Rails just happened to be in the right time and place to attract relatively young, progressive people who tend to use social media more.
There's plenty of "drama" in many programming communities, but a lot of it is hidden, because your median Java developer is less likely to be on Twitter, Medium, or even HN.
One advantage of starting with Rails is that you can progress to JRuby on Rails when scaling is required. From there you can factor out services to Clojure or Scala without rewriting everything. So I'd say Rails has much more to offer than a quick starter app.
Uh, Go is not a research project. It was written to be used, not to explore previous unexplored language features. Basically nothing in the language is new (or at least wasn't new to the creators), something that it is often criticized for.
Dropbox has stated that pretty much their entire backend is written in Go. Go is also (obviously) used in production at Google. Neither Dropbox or Google is screwing around. Once a project is run at Google or Dropbox scale, it is no longer a research project.
Go is very simple (many people say too simple) and writing a web app in it doesn't really require a very good understanding of the language. This is because very few of its more advanced features are really required for writing a normal web app. Because it isn't really a framework, it does require a good understanding of web development.
I think Haskell can be fairly described as a research project and definitely requires a good understanding.
> Go is very simple (many people say too simple) and writing a web app in it doesn't really require a very good understanding of the language.
But you do have to know to how to use the standard libraries well to write anything beyond a Hello World web app in Go.
Just because the Go language itself is simple, it does not mean web development is easy in Go. Quite the opposite, you have to write a lot of boilerplate code in Go (even with Go frameworks) to do things that would seem trivial in other frameworks.
I think what erikpukinskis means may be more that Go is still a "non-mature"/"research" ecosystem - for example, what do you use for version control of dependencies? Rails has bundler, Go has a few different approaches, none of which are the go-to thing everybody uses.
Standard Chartered is a massive multi-national bank with a £17 billion market cap and a multi-million line Haskell code base. Is that still a research project?
> Java and C# are of course equally boring, but I think the fact that Rails is culturally open source provides a huge benefit over them.
Java is culturally open source at this point; nearly every widely-used Java library is open source and there is a huge open source ecosystem around Java (namely everything maintained by the ASF, but there are plenty of other open source projects like Gson, etc.). Bonus points for tying in to any of the bazillion proprietary software systems also built in Java.
The problem with Java is that it's so damn verbose -- it can take forever to build a moderately complex system because you just have to worry about so many things (maven, spring, jetty, etc.) just for a simple web service. This means you're spending time up front solving a lot of technical problems just to get a simple web service up and running.
Rails is great because it implements a set of sensible defaults and lets you worry about product design rather than implementing yet another database backend for a user store. Its event-routing model also makes a lot more sense for the web; in Java everything is kind of a hack to link the web stuff back to the JVM. But yeah, once your project gets complex, it might as well be Java -- complex software is just complex to write. Rails kind of sucks when the "sensible defaults" don't make sense anymore because you need heavy customization. It's a great prototyping platform, and that means a lot -- but it still won't let you escape the problems caused complexity.
> Try to sell them a new page with attached the price of a major refactoring... good luck with that
Could it work to include a "technical debt" figure in your quotes (where each feature without refactoring increase the debt and the "interests" on each future invoices)? Might be useful to explain them that quick-and-dirty is not always the best solution.
Do the customers know what Rails is enough to like or dislike it? Or do they like the promises of quick functionality which you translate in to lower costs?
If I may also ask, have you run in to an older rails app when someone wanted some fairly minimal additions? Have you been the "next guy?" or do you avoid those projects? Did you migrate it to a newer rails? rewrite it? Or write old rails code? I've run in to a couple of ancient apps that were running untouched for like 4 years, they want to freshen the application, maybe add some features, you have to sell them a major refactor, or you can't touch it, like they depended on some gems that were orphaned. It's not exclusive to Rails, I've seen this with node too, once the application needs to be living and breathing to stay healthy, once you put it on the shelf, it's dying. An express.js 2 to 4 migration is effectively a rewrite, it's not super terrible but it's a chunk of work that isn't adding their new features.
I've simply never heard a long term success story with rails or node when it comes to maintenance. It's maybe not a technical thing but it seems like it's the culture of both communities. Blue sky and green field code? It's a blast, fixing up or adding to someone else' existing code? I probably wouldn't touch it. Oddly, I don't feel the same way about a lot of Java stacks though.
Basecamp went through a massive rewrite, and GitHub went through a long period of (perceived) low pace innovation culminating in "Dear Github".
I don't know whether Rails maintenance issues played a part in either of those things. However I do know that YAGNI and tight coupling are traditionally things than come back to haunt you 5+ years later. Front ends may change in that time but the fundamental logic of applications, especially their data structures tends to evolve much slower. Isolating the two can only be a good thing if you're not building a throwaway project.
Everything long term is going to need serious refactoring or a rewrite at some point (or just hire exponentially more developers). I don't think it has anything to do with the language or framework.
Depends if it was written well in the first place. I am maintaining a Django app, and because they have gone for "thin models fat controllers philosophy" (the opposite of Djangos best practices) it is a pain in the arse to modify stuff that should be easy.
Ok, maybe the framework doesn't have much influence, but a language with sane types will make refactoring easier. I'm not saying it will make it easy, just easier than other languages.
No, those customers only know that Rails is mainstream and so it's a safe choice. If I propose Phoenix to them I bet they will look puzzled and ask me about PHP, Python, Node, Rails, maybe even Java. I'll make a test.
I've been the next guy many times. Rails makes that easy because I know where to look. The worst are custom PHP projects because I need to understand the original programmer's way of thinking. It can be a smart architecture (usually it's not) but it's time consuming and inefficient cost-wise.
I migrated every single version of Rails.
Never total rewrites, no need to do that.
I'm maintaining Rails 3, 4 and 5 beta apps right now. The customer with the 3.2 one has very little budget (we atarted and paused the upgrade to 4.2) and it's going to be EOL very soon. We'll see what happens. I was the next guy, that app started in 2011, I got it in 2012.
Orphan and incompatible gems happen. They make upgrades more difficult but I always handled them. With node it's an order of magnitude worse because of the much more rapid pace of change. It's the main reason for I would not recommend using Node.
Java just costs more to the customer. I use it only when I'm the next guy in a Java project. It's always a pain to work with it. It's like those ten lines would be one if this was Rails and I would have delivered two days ago (small new features). I just don't understand why developers want to inflict that environment to themselves.
Because Java is a huge chunk of the job market (at least in the Sacramento area), not because it's a "language of choice" . Actually, the JVM is a nice thing, even if the Java language is primitive and verbose.
Too bad the jFoo alternate language implementations haven't got more traction yet. (jRuby, Jython, Nashorn, et al)
Because it takes so long to start and you feel it whenever you run the tests. It gets a little better if you disable the JIT compiler and so... in dev mode, where developers spend all their life, it's not faster than RMI. Because it used to support only the syntax of older versions of Ruby. Basically devs get all the pain of the JVM and none of the gains. Guess what they want to use? A customer of mine asked me how to migrate from jRuby to MRI because devs where having problems. I explained and suggested they could try using MRI in dev and keep jRuby in production. They're a JVM shop. I'll ask them what they decided to do.
"Java" is a big world now. A java 8 app with spring boot and jooq is just as simple to work in as any other backend software. If someone is stuck on java 6, classic spring, and hibernate...I feel your pain.
I ended up with a small nightmare with streams and collectors. That boilerplate shouldn't belong to this world, probably it's there because of the Java way to static typing.
They use Spring, don't know which versions, but it's got @RequestParam annotations to extract parameters from the request body. I think this is Spring Boot. It looks like Sinatra because of the @RequestMapping. Having @RequestParam in the action arguments looks a little like Phoenix pattern matching but I didn't have time to dig into the web and understand if it can really route requests to different actions according to the RequestParam. Overall is more or less where Ruby frameworks where ten years ago unless it's got pattern matching.
The webapp I had to work on still use ctags, which are a major PIA which slows down work and raises costs.
Queries are written in SQL, which is perfectly OK, and executed on a connection returning a java.sql.ResultSet. Not shiny but everybody can understand that. I googled jOOQ and it looks like ActiveRecord/AREL for Java. Nice but it would have cost me more time for this kind of quick hack.
Yes, one of the benefits of Rails most overlooked by it's opponents is how immensely productive it is for small to medium sized apps. This comes from not only the DRY perspective but also from having strong standard ways to do things, and quite a stable API.
I don't agree on the sentiment in the article that it's hard to follow what happens in rails/activerecord. It's pretty well documented and all the quirks are thoroughly discussed on stackoverflow. Ruby has excellent tooling and it's easy to find performance bottlenecks.
On the negative side though, I find that I use other languages when I need performance or better concurrency, but that always comes at the price of lengthier development.
I have 2 main concerns going forward with any Rails alternative (ie. Trailblazer and the like): community support and jobs.
I have no idea how big the community behind each library/framework is and honestly I don't have the time to properly test-drive multiple and research the health of their respective ecosystems. With Rails I can rely on 10-15 gems that can help me with 80% of my projects. Perhaps I overestimate my reliance on 3rd party code, but that leaves me with my second issue.
Ruby jobs are de facto Rails jobs. I have weekly email newsletters set up for Ruby jobs and in the last 3+ years only a handful were Sinatra/Rack based. It would be interesting to see a reliable source of non-Rails Ruby jobs out there.
At some point you'll be in a position to decide which tech stack a company should use. I suspect you'll find there's a bit of a chicken and egg problem here - you'll want access to the largest pool of good candidates possible so you will also be disincentived from straying from the well worn path.
Even if you grant that good programmers can pick up new languages or frameworks easily (which I'm not entirely convinced of - there is a wide gulf between "can follow the tutorial" and "successfully used in anger"), you'll incur a penalty in velocity while all your new hires learn Framework X.
Anecdotal example of the perils of going off the beaten path: I often see a job advert on StackO for a company looking for Python/Django guys. When you click through to the job description, they are actually using Perl/Dancer. Not that there's anything wrong with that, but for me personally that's a deal breaker. I have no interest in investing the time to become proficient on that particular stack.
> Even if you grant that good programmers can pick up new languages or frameworks easily (which I'm not entirely convinced of - there is a wide gulf between "can follow the tutorial" and "successfully used in anger"), you'll incur a penalty in velocity while all your new hires learn Framework X.
I think the question is more "Does what we're doing require good programmers, or can we get by with shitty ones?" More often than not, you're not doing anything special, and you want to pick a platform that the cheapest, most common programmers out there can add features in a non-disastrous amount of time (different depending on industry + your competition), and not generate enough technical debt to collapse everything before the next rewrite/upgrade cycle.
...but these are the same people who made what Rails what it is today. What is concerning is their occupation of top seats on other hot projects (Rust, Elixir etc.).
A few years ago if you said anything negative about Rails, you were either pure evil or unbearably stupid; or both.
If you didn't fully embrace tableless design with CSS, despite the latter's glaring defeciencies for that task, it was the same treatment.
I also recall great pressure to adopt EJB with its deeply flawed architecture, etc.
I could go on, but the point is that there seems to come a time when all of these things face a moment of truth, wherein sober minds feel a little freer to speak aloud on their shortcomings. This frequently snowballs into all out backlash against the tech in favor of The Latest Shiny Thing.
The enforcers of what's hip and smart for everyone now move on to browbeating Developer Land with the new tech, and we all allow it to happen again. Why do we keep repeating this process when we've all seen the movie so many times?
Reminds me of "The programming language lifecycle"[1] (written in 2006), which essentially implies that the reason programmers continually search for new languages is simply out of a desire to 'distinguish' themselves from their peers, and have little to do with the actual merits of the languages in question.
I think rails has plateaud in terms of improvements. The article is pointing out the tight coupling of activerecord with business logic which is the consequence of a belief that I strongly disagree with in the rails community. 'fat models, skinny controllers' has caused a lot of mayhem as minor database updates (or update intention) triggers a cascade of actions.
This behaviour is counter to the model2 MVC implementation that rails is using as controllers should really be in charge of coordinating (helped by specialized classes if need be).
The author correctly points out that the way rails deals with views is painful however rails views are not tied to the model at all, they are tied to controllers and this can be modified if need be.
I personally maintain an approach of tying dedicated ruby classes to view files (e.g. SidebarComponent) and compose the view in the controller using a chain of these classes. This approach is much more object-oriented and avoids the weird pass-along view-hierarchies that many rails projects have.
There are much things to improve about rails but the project doesn't seem to absorb more object-oriented approaches over time and is tilted heavily towards DSL's for everything and doesn't value creating a more specialized class hierarchy to encapsulate more complexity.
I don't see a need to move away from Rails yet though as you can easily work inside the framework in a more Object-oriented approach. I guess you can characterize my approach as skinny models, skinny controllers, fat business logic objects and every partial is powered by a view object.
Quite a huffy, histrionic (self-described) rant. My advice to OP is to take a Xanax and relax. Rails is just one tool -- like all tools, it excels in some areas and is deficient in others. If Rails isn't the right tool for the job, use something else. If you have a better idea, write some OSS. Personally, I've been using Rails for 9+ years, but I also use vanilla Ruby, Rack, Sinatra, Java, vanilla SQL, Go, and C when appropriate. If you only use Rails, You're Gonna Have A Bad Time™.
454 comments
[ 3.3 ms ] story [ 400 ms ] threadDisable the box-shadow on .widewrapper.main and it works fine.
We fixed in in Firefox 47, but the fix was deemed too risky to be uplifted to Firefox 46. That was probably a mistake. Anyway, Firefox 47 is going to be released in two weeks on June 7th. In the meantime you can remove the box-shadow from .widewrapper.main using the devtools, or you can use Firefox Beta (47) or Firefox Developer Edition (48), which you can get here: https://www.mozilla.org/en-US/firefox/channel/#developer
Now, this line of code is not simple, it’s easy to write it, but the code is extremely complicated under the hood because:
- params must often go through db-specific coercions
- params must be validated
- params might be changed through callbacks, including external systems causing side-effects
- invalid state results in setting error messages, which depends on external system (i.e. I18n)
- valid params must be set as object’s state, potentially setting up associated objects too
- a single object or an entire object graph must be stored in the database
This lacks basic separation of concerns, which is always damaging for any complex project. It increases coupling and makes it harder to change and extend code.
This feels like the core of the argument of the whole post. It does not seem correct. In isolation, the call to User#create seems magical. But there's not enough context here to criticize it. We don't know enough to say whether there's inadequate separation of concerns.
No matter how we handle "users", we are going to need to do all 6 things in the list the author presented. No matter how we structure those 6 things, there is going to be a single entrypoint function that kicks them off --- end users won't be pushing 6 different buttons to drive them. So: what's the better design here?
This is very much not Merb's design. But that doesn't make it an invalid design; it just means that understanding a Rails app might best start with the models, not the controllers.
(There's a lot not to like about Rails! It's been years since I worked in it full time and I don't miss it.)
In 2016, with systems regularly decomposing into services for both perf and code management purposes, I'm trying really hard to find a reason to say this isn't an invalid approach except for what amount to toy problems (the kind where "if you don't know where you're trying to go, any road will get you there"). ActiveRecord being a mudball of "what X is" and "how to get X" is a really, really big problem, and my view of it as an observer--heavy in Ruby, heavy in avoiding Rails at all costs--is that it seems to be sourced from an unwillingness of the Rails community to consider that not everything is Rails. Services become intractable, as I note in my reply to your first post--and I don't even mean "microservice all the things", just the profoundly unsexy and unbloggable "SOA".
Source: "The Rails Doctrine" http://rubyonrails.org/doctrine/
There's enough context for me to start putting up the horns and cheering, because AR is one of the more persistent boils on my ass when I'm building things in Ruby (because I use Ruby for Ruby, rather than Rails, my frontends are all JavaScript and my services are all Grape). His last point is sufficient to me to demonstrate inadequate separation of concerns--the better design is the one that doesn't require an active database connection to know what fields the object has in it. Answering "how do I build an SOA without every service having a line to every database?" inevitably becomes "don't use ActiveRecord, ever".
What solnic has done with Virtus (which I use in all my projects, it's awesome, he's one of my favorite current Ruby people because of it and I'm sad that he may be leaving) is to return to the novel notion that an object knows what's in it. Dumb data objects are in almost every case a better long-term strategy, and solnic's frustration, if not expressed perfectly, is one that inevitably burns even Rails projects that grow to scale. And while this is a single example of Rails's monolithic nature choking out a lot of the Ruby ecosystem, it's not the only one (see his comments on ActiveSupport).
They are both critcisms of ActiveRecord, for sure, but quite a bit different in content. One (AR objects not knowing their own properties) feels, at least to me, like an unfortunate early design decision, while the other (encapsulating everything involved with saving a model in a single statement, "magic avoidance" be damned) is very much in line with the core philosophy of ActiveRecord and Rails.
Hence "the last point" (though you might have caught me mid-edit). I view these as functionally the same problem: not only are you instantiating the object, but it must immediately go to live in the database or it's useless.
But you're right in that it is a philosophical problem. Rails is wrong. =)
Also, in Django models are explicitly defined. There's no ActiveRecord magic of reading the database to define the model. Which is not to say that AR's approach is bad or wrong, but it is pretty significantly different from Django.
I feel like people really forget what it's like to be a beginner when they say "read the source".
Further smaller changes have been made since then for the same purpose: explicit over implicit, code or configuration over convention is part of Django's philosophy.
IMO that also makes it easier to graduate from a beginning to an intermediate level use of the framework because while there are sane defaults in many places, in others you're required to define your specific implementation explicitly from the start. It's a tiny bit more code up front, but all the details are exposed and it's obvious how to override default behavior. And at the same time the framework supports keeping your code reasonably DRY and takes care of much of the tedious, repetitive stuff.
There's still tight coupling in some places (ModelForms, for instance, are arguably part of the controller layer and are tightly coupled to the ORM). But they're reasonably optional (you can use plain Django Forms instead of ModelForms in your views or not use the Forms library at all.)
My experience with Django (for instance: class-based views and admin parts) is actually that you have dozens of magical classes or methods and if you don't know them all, you're screwed. Often when I try to do something, many aswers on StackOverflow boil down to "just override a_method_that_is_hidden_somewhere()" or "just use ListButWithSpecificBehaviorView(), easy you see?".
Are there any specific example you have in mind where Rails do something magical that requires more code in Django but where Django is more explicit?
PS: not trying to start a flamewar, both are OK-frameworks, bla bla bla ;-)
http://www.monkeyandcrow.com/series/reading_rails/
Sure, Rails is complex, but it takes on that complexity to let us be productive. When you run into that complexity, read the source.
However, just because something is heavily abstracted doesn't mean it's a bad approach, at least from a productivity standpoint. Without certain things being heavily abstracted, we'd go insane.
Just as
gets translated to thousands of lines of Ruby, so also gets translated to thousands of lines of C, and gets translated to thousands of lines of assembly.Are they all heavy abstractions? Yes. Is it oftentimes very nice to be able to use heavy abstractions? Also yes.
Also I would like to point that "translates" is a little misleading word. There are two ways of implementing an abstraction from a higher level system to a lower level one.
You can generate code or you can write a runtime framework that does the work dynamically. Although from the higher place both may seem the same, there's a huge difference between them that has consequences.
I wouldn't doubt it; compilers have become amazing at optimizing. But printf is hundreds of lines of C, at very least: http://opensource.apple.com//source/Libc/Libc-1082.20.4/stdi...
And most important, a call is not the same as the implementation of the called function, my point to begin with, please see my comment in the context of yours.
In any case, the complexity of the called function is exactly what we're discussing — it's why the author objects to "User.create(params[:user])"
http://zverovich.net/2016/05/13/giving-up-on-julia.html
printf has a well design side effect (printing to stdout). Coolclass.new has an expectation of an instantiation of object in memory. If Coolclass.new also called an external service, then that would be a violation in my opinion. Thankfully, we generally don't do that.
User.create is not only capable of tons of side effects (just like Coolclass.new) but it is encouraged to do so (via callbacks and such).
I think maybe your broader thesis is we almost always need all 6 things. And if that's true for you then Rails is a good tool for you.
If we only ever need one out of the 6 things at a time then ActiveRecord is only adding extra complexity for us.
I think OP is basically saying I usually only need one or two and that they'd rather not have the extra layer of indirection... "save(andValidate)" is fine for them. They don't need the orchestration abilities that the declarative "afterSave(validate)" step affords.
DHH's suppress really is a good example. If you are calling save(andValidate) everywhere, you can't really do something like suppress(), because your validation logic is disbursed.
My opinion, and I think maybe OP would agree, is that there's usually a nice, composeable way to get the same problem solved, without resorting to a giant engine that understands all the different parts. But that's just an empirical assertion on our part. Obviously your mileage will vary.
I think you want "dispersed" here.
I've never written a line of Ruby, but trying to read Rails code evokes me all this: it seems like a framework created with the sole purpose of hiding everything possible from the programmer.
Obviously if you follow a framework from day 0 you don't even notice it. For newcomers, it's a source of frustration.
For example, ActiveRecord class names map to table names through a simple pluralizer (UserProfile -> user_profiles). That's a convention, no configuration needed. Just write a class and off you go. You can override this behaviour, but you can also write huge apps that just follow the convention. Other frameworks would typically make this mapping explicit.
You do need to read the documentation to see what the conventional behaviour is, but it's not very deep knowledge. It's not much worse than other frameworks, where you need to find how things are configured.
It takes a little getting used to, but once you are, then the tooling is there to help you make sense of these things:
1.method(:year).source_location
The bigger issues with Rails I see are the monoculture issue raised in the article, plus the intractable issues with ruby around performance, memory bloat, concurrency, and last but not least, the multi-paradigm nature giving you functional features, but without any of the usual immutability guarantees (unless you follow a constrained and unconventional coding style which no one does in the ruby community).
You can explain those two things you mention in a few seconds ("Ruby allows adding new methods to anything; the 'hours' method is defined by ActiveSupport"), and then the confusion has been eliminated. That leads to an increased understanding of Ruby.
FWIW, I've had a whole bunch of junior colleages learn Ruby, and those things were never a point of confusion. If anything, I have the opposite experience; Ruby and Rails are superb for newbies because of all the sane (convention over config) defaults.
Unfortunately, one segment of the Rails developer culture has perpetrated a lot of ugly overdesign (mini-frameworks such as Devise, ActiveMerchant, etc. that inject themselves into Rails in brittle ways) that certainly will confuse newbies. But that's not Rails' fault.
Explicit configuration may teach a new developer about a codebase, but it also means that there's more upfront work when developing. If the conventions are already there, in the form of good developer habits and good workflow, it's more pragmatic to encode them as explicit conventions, rather than introduce lots of un-DRY boilerplate.
Some of my favorite Rails devs are former Python devs. They appreciate conventions and the freedom they give you.
The most common criticisms are: it's slow and it has too much "magic."
At the end of the day, it comes down to this: every framework has its pros and cons. When you use a framework, you gain certain benefits but sacrifice certain things and have to conform to the framework's opinions. In the case of Rails, the primary benefit is extremely fast prototyping. But that's only possible because the framework hides a lot of complexity from you, which can bite you in the ass if you try to go outside its conventions.
[1] https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&sor...
The author is right, competition is important, the Rails/Merb scenario is the open-source version of Microsoft E.E.E
https://github.com/datamapper/dm-core/graphs/contributors
I did maintain DM for a few years, but burnt out as there wasn't enough time to keep up with the community demands and work a full time job. There were a couple of years I effectively worked 40-60 hours a week on DM and only 5-10 on work; this wasn't tenable long term and burned me out.
The small dev team, of which solnic was a core member, are an amazing group and there's no way I could've maintained DM for even a fraction of the time I did without their support.
> if your use-cases don't fit into "Rails way" your screwed
Of course.
If a startup service doesn't fit Rails, they should have picked something else. I'm not using Rails for everything.
The only really common startup use case it's decidedly bad at is realtime/sockets/streaming data, where Node takes its place as the hack-it-together tool of choice--at a significant productivity penalty compared to Rails.
It's also, of course, pretty bad at all kinds of tasks unrelated to web development or REST apis. You wouldn't want to write machine learning algorithms or do statistical analysis in Rails, just like you wouldn't want to do 3d game development in Rails. And while you do occasionally see startups who have bolted some heavy data processing or pseudo-ML monstrosity onto their Rails apps, I've never seen anyone in the Rails community claim that was a good idea. The vanilla recommendation there is to keep your main server stack in Rails and then write services in something more appropriate for those needs.
I agree with the author wholeheartedly, but there is certainly value in getting something that works quickly.
I've always heard people blast Rails b/c of Twitter's experience but Twitter did survive it and scale. Maybe Twitter would have never gotten to the level of success they did without using Rails? Also, I'm not convinced that the original developers at Twitter did a great job implementing the first Twitter infrastructure. It is possible to write bad code using Rails that would be bad no matter what language or framework was used. It's a huge unknown in that story that entirely changes how to judge the outcome.
I think your statement is patently false.
So yeah, survival bias. If startups failed and used Rails, it's because they were bad startups for reasons outside using Rails.
As a framework for building comventional HTML templated database backed websites I still think it's near unbeatable, especially with the addition of a few common gems. However it so often gets shoehorned into other places - API backends, rich client apps, and massive systems. Places where the Rails conventions rapidly go from everything falling into place to getting in the way and needing to be worked around, or heavily tuned.
I completely agree that ActiveRecord is the core of why big Rails applications are complex to work with and often exhibit disproportionally poor performance. It doesn't lend itself well to composition, and results in data persistence being intertwined with business logic. That's fine for early prototypes, and in all honesty will get you to market quickly, but it makes extracting the concepts you discover during development into a coherant API much more complex than I'd like.
These days I still use Rails for the aforementioned HTML generating web applications, but it's often acting as an API client to systems built on top of a Grape based backend, with an API built around service objects and a simple data access later.
The project is very lightweight right now (benefits of being a young project with a sole full-time contributor), but I'd be interested to hear your feedback as to what you think is or isn't necessary for continued development. :)
[1] http://github.com/keithwhor/nodal
We serialize models to JSON automatically in the response layer, and all models have a `.toObject()` method that takes an optional interface (which keys to actually serialize).
There is full API documentation but I still have a lot of work to do creating more fleshed-out tutorials. :)
http://graphql.nodaljs.com/
I think everyone has different needs, and you have your personal needs which Rails no longer satisfies, so you are moving on.
Rails still solves a lot of problems for a lot of people I believe. I work as a consultant for a few companies and in some cases I see people losing time and money on what would be resolved immediately if they had just made the right call by using Rails.
Good luck on your journey, and remember the rails community will always have its door open for you :). Your projects on github look exciting, I will take a look at them. Very cool stuff!
[0]http://harmful.cat-v.org/software/ruby/rails/is-a-ghetto
True. And yet, it reminded me of that article Zed wrote, which I summarized as a vulgar critique of the internal politics of the rails community.
Simple as in simple, fast, productive, beautiful Ruby-like syntax. Favors a functional and immutable workflow over object-oriented and mutable spaghetti code.
It sounds great in principle. I'd love to move from Rails toward something more functionally-inspired, but I worry that lack of libraries and google results is going to be a net productivity killer over the Rails + evolving into micro-services approach.
Can't comment extensively on the library ecosystem but you have access to everything from Erlang via trivial interop.
(Edit: Btw I happily accept Rails' monolithic nature for all its conveniences, and I don't really identify with this author, but I'm curious to hear your opinion whether Phoenix would be a good fit for him.)
Phoenix apps aren't actually monolithic, but I'll let the creator of Phoenix explain this himself (https://news.ycombinator.com/item?id=11749741):
> A new phoenix application is not a monolith. The `phoenix.new` generator generates a regular Elixir application for you that sets up a default Endpoint worker in your supervision tree, as well as a web directory to put phoenix related files (routers, controllers, etc). wrt to collective process, we add `worker(MyApp.Endpoint, [])` into your supervision tree, so we do exactly what you are wanting. Building a Phoenix application is building an Elixir application, not the other way around. Your phoenix dependency and related workers are just one component to your larger Elixir/OTP infrastructure. Note: Lance Halvorsen, who gave the "Phoenix is not your App" talk, is on the Phoenix core team. We have been pushing these ideas since the beginning and as Lance I and laid out in our ElixirConfEU talks, we're taking a stronger stance on isolation with upcoming changes to guides and phoenix resource generators.
I think it's really quite a testament to Phoenix that so many people think it too is monolithic. A client can request a Phoenix application and I can get productive immediately without worrying about creating an unmaintainable, unperformant mess. No wasting 2 days on configuration hell. I can even jump into an existing project and be productive.
Another point is that the libraries around Elixir aren't (in my experience) Phoenix-focused or obsessed with magical Phoenix integration. In most cases, things work well together. Just call functions.
Monkey-patching, thread-unsafe operations, and uncontrolled shared global state are all non-problems in Phoenix. Decent code architecture and testability aren't usually a problem either because proper separation is enforced. Functional/immutable programming makes a huge difference here too.
Ecto 2.0 is really what ActiveRecord should've been. It's incredibly well thought-out. I suspect the author would be really pleased with Ecto.
Finally, Phoenix favors simplicity over ease in most cases. Complexity is not hidden in 100 layers of abstraction and callbacks.
The author also mentioned DHH's... colorful personality. So I'll take this opportunity to mention how much more welcoming and humble Jose Valim and Chris McCord are.
Check "Phoenix is not Your Application" at http://www.elixirconf.eu/
It starts with the right claim but it ends with workers inside Phoenix. Instead the router and the http server should be at the same level of the other workers. Actually, they shoul be much less important, an implementation detail.
And yes, phoenix will end up bogged down like Rails, and hex will end up chock full of crap, it is the Rails developer mentality I'm afraid, they just can't help themselves.
I like to think of Phoenix as an interface to my app. It's less intrusive than Rails.
You don't have to use Ecto (the "ORM" thingy that is actually not an ORM) to get get the full power of Phoenix, it's also decoupled.
Regarding Hex, it's like every package managers out there. Sure you can publish anything. Rubygem is full of crap, npm is full of crap etc.. But I can also find some very small and focused libraries that wouldn't have been published, had a quality filter been setup to publish anything.
To make them have to go back to coding academy school in two years?
So that they maintain legacy codebases and don't touch the new shiny features the experienced engineers are working on until they get their training wheels off?
Because there is actual demand for ruby on rails despite all the hate and sunsetting of rails I see on HN?
Also, and I'd love to see actual demographics on this but I know it's impossible, while lots of posters on HN/proggit/whatever are professionals, a lot of them are also high school or college students that are still coming at it from a hobbyist perspective (i.e., focused on what's new and exciting rather than engaged in the relatively boring world of getting paid to solve other people's problems). For that matter, a lot of the professionals approach their work from a hobbyist perspective (not necessarily a good thing for their customers).
I don't mean to sound like I'm down on hobbyists or students at all, just that different people care about different things, and just because most HN posters know a lot about the technologies they post about doesn't mean they know or care about the actual state of the industry (just their corner of it)(that applies to me too of course, we're all like the blind men and the elephant).
https://en.wikipedia.org/wiki/Blind_men_and_an_elephant
Big companies use enterprise Java unless they're stuck with a legacy VB/ASP/Coldfusion stack, with C# less commonly.
Fintech companies use a mix of C# and C++.
Small companies started before ~2010 use PHP, with Rails less commonly.
Small companies started after ~2010 use Rails, with hipster Java (Scala/Groovy/et al) less commonly.
I can only remember offhand seeing one job ad for a company using Sinatra instead of Rails for their Ruby stack.
Chicago, the land the MEAN stack skipped.
1. it's easy to get something up and working, which for a lot of students helps keep them motivated 2. Hartl's Ruby On Rails Tutorial. So far, it's the best book/course on how to get from knowing pretty much nothing to being able to work in a 'modern' dev setting (good editor, git, bitbucket, testing, backend, front-end, etc.). 3. if they want to actually get a job as a junior dev somewhere else, I've found that joining a startup or company that uses Rails is pretty easy. Much easier than jumping into a front-end React/Redux shop, for example.
I do not necessarily intend to use Rails actively with them in their first projects, and for those who can and want to I'll probably have to introduce them to the complexity and horrors of front-end javascript development, but at least with the Rails Tutorial they can get started by themselves and learn some degree of 'best practices'.
There's too much purism in those kinds of arguments, arguments that really are more about spectrums. It sounds like Rails is really great for learning the shallowest 40% of a wide variety of programming concerns, and a lot of web solutions for small clients aren't ever going to dip below that 40%. And as soon as you get beyond that 40%, asking questions like "but what if it doesn't make sense to do it that way?" and "what is that weird runtime bug that doesn't happen in my development environment?" and "why can't I refactor without being scared I'll introduce a weird regression bug?" then it's totally fine to be attracted to the idea of static typing, compilation, and libraries/frameworks that are more explicit.
[1] http://jamesgolick.com/2010/3/14/crazy-heretical-and-awesome...
When I started with Rails it felt like magic, you didn't know why things worked.
While at Google I became aware of Go and what that looked like at scale. I would highly recommend trying out Go. I think the simplicity will be a refreshing change but there will also be some familiarity coming from the Ruby/C world, can't quite pinpoint why but just feels that way.
And if you're looking for frameworks, shameless plug, I'm working on this https://github.com/micro/micro.
Do projects get complicated? Yes, some of then. Mainly because most customers pay for features and not for refactoring or design, which they don't understand (remember, no in house technical staff). Try to sell them a new page with attached the price of a major refactoring... good luck with that. So sometimes features get kludged together because of budget constraints. I have projects with suboptimal UX (understatement) because they rationally decide to make tradeoffs between usability and costs. It's their privilege. I bet this would happen with any language or framework. Your customers could be more long sighted than mines, I hope they are.
So, would I move away from Ruby and from Rails? Yes, when customers won't like starting a project with Rails anymore. This means that other tools don't have to cost them more. Do I care about Rails architectural shortcomings? A little, but I appreciate its shortcuts more. They work well in my projects.
Choosing Rails will definitely lead to problems in the long run, but at least they are well understood problems. You're going to do an in-flight replacement of your 1.0 eventually anyway. You just need one grayhair on the team to steer the younglings away from the worst abuses and you'll have a stable, if clunky, platform to build on. It's the definition of mitigating risk.
Java and C# are of course equally boring, but I think the fact that Rails is culturally open source provides a huge benefit over them.
JavaScript, Go, Haskell, etc are arguably better if you really understand them, but they're research projects. Lots of great pieces of code, but the story of how to use them together is still being written. I would use one of them if my intention was to hire slow and keep my dev team fewer than ~30 people in the long term.
Can't speak about the Haskell community though. To the extent I know the language I probably wouldn't want to use it to create HTML forms, either.
The result of this is that, yes, development of your standard CRUD app is probably not as fast as it would be with Rails. Also, moving from project to project is not as easy as it would be with Rails. But the advantage is that, if you have good developers who are good at architecting (a big if), you architecture will better reflect the problem at hand.
Compare to Rails, where you start of with OK infrastructure by default. That's not better, it just means you can hire a random person off the street and they're on the same page as you. If you want to keep a team of 50 JavaScript developers on the same page you need a really strong culture. Or just say "Use Ember and Express, end of story". But at that point you no longer have the "developer freedom" you correctly cite as the core selling point of Node.
And by "on the same page" I mean "we both have a similar understanding of a sensible default way to transport persist text fields from an HTML form". Put 10 JavaScript programmers in a room and you'll get 8 different approaches.
Or any correct way of doing one thing, starting with the language (JavaScript) and moving on from there …
And if you just want something to work quickly, Rails wins. JS encourages developers to spend days and weeks on picking each part of a framework for an MVP that may go nowhere. Rails is no longer the new shiny and it has moved into the 'get shit done' category of developer tools.
And they're the ones who don't write medium posts daily whining about how their frameworks are the worst in the world.
It's boring, it works, it scales.
There's plenty of "drama" in many programming communities, but a lot of it is hidden, because your median Java developer is less likely to be on Twitter, Medium, or even HN.
Dropbox has stated that pretty much their entire backend is written in Go. Go is also (obviously) used in production at Google. Neither Dropbox or Google is screwing around. Once a project is run at Google or Dropbox scale, it is no longer a research project.
Go is very simple (many people say too simple) and writing a web app in it doesn't really require a very good understanding of the language. This is because very few of its more advanced features are really required for writing a normal web app. Because it isn't really a framework, it does require a good understanding of web development.
I think Haskell can be fairly described as a research project and definitely requires a good understanding.
But you do have to know to how to use the standard libraries well to write anything beyond a Hello World web app in Go.
Just because the Go language itself is simple, it does not mean web development is easy in Go. Quite the opposite, you have to write a lot of boilerplate code in Go (even with Go frameworks) to do things that would seem trivial in other frameworks.
Java is culturally open source at this point; nearly every widely-used Java library is open source and there is a huge open source ecosystem around Java (namely everything maintained by the ASF, but there are plenty of other open source projects like Gson, etc.). Bonus points for tying in to any of the bazillion proprietary software systems also built in Java.
The problem with Java is that it's so damn verbose -- it can take forever to build a moderately complex system because you just have to worry about so many things (maven, spring, jetty, etc.) just for a simple web service. This means you're spending time up front solving a lot of technical problems just to get a simple web service up and running.
Rails is great because it implements a set of sensible defaults and lets you worry about product design rather than implementing yet another database backend for a user store. Its event-routing model also makes a lot more sense for the web; in Java everything is kind of a hack to link the web stuff back to the JVM. But yeah, once your project gets complex, it might as well be Java -- complex software is just complex to write. Rails kind of sucks when the "sensible defaults" don't make sense anymore because you need heavy customization. It's a great prototyping platform, and that means a lot -- but it still won't let you escape the problems caused complexity.
Could it work to include a "technical debt" figure in your quotes (where each feature without refactoring increase the debt and the "interests" on each future invoices)? Might be useful to explain them that quick-and-dirty is not always the best solution.
If I may also ask, have you run in to an older rails app when someone wanted some fairly minimal additions? Have you been the "next guy?" or do you avoid those projects? Did you migrate it to a newer rails? rewrite it? Or write old rails code? I've run in to a couple of ancient apps that were running untouched for like 4 years, they want to freshen the application, maybe add some features, you have to sell them a major refactor, or you can't touch it, like they depended on some gems that were orphaned. It's not exclusive to Rails, I've seen this with node too, once the application needs to be living and breathing to stay healthy, once you put it on the shelf, it's dying. An express.js 2 to 4 migration is effectively a rewrite, it's not super terrible but it's a chunk of work that isn't adding their new features.
I've simply never heard a long term success story with rails or node when it comes to maintenance. It's maybe not a technical thing but it seems like it's the culture of both communities. Blue sky and green field code? It's a blast, fixing up or adding to someone else' existing code? I probably wouldn't touch it. Oddly, I don't feel the same way about a lot of Java stacks though.
Basecamp, Shopify, GitHub aren't long term successes? smh...
I don't know whether Rails maintenance issues played a part in either of those things. However I do know that YAGNI and tight coupling are traditionally things than come back to haunt you 5+ years later. Front ends may change in that time but the fundamental logic of applications, especially their data structures tends to evolve much slower. Isolating the two can only be a good thing if you're not building a throwaway project.
No, those customers only know that Rails is mainstream and so it's a safe choice. If I propose Phoenix to them I bet they will look puzzled and ask me about PHP, Python, Node, Rails, maybe even Java. I'll make a test.
I've been the next guy many times. Rails makes that easy because I know where to look. The worst are custom PHP projects because I need to understand the original programmer's way of thinking. It can be a smart architecture (usually it's not) but it's time consuming and inefficient cost-wise.
I migrated every single version of Rails.
Never total rewrites, no need to do that.
I'm maintaining Rails 3, 4 and 5 beta apps right now. The customer with the 3.2 one has very little budget (we atarted and paused the upgrade to 4.2) and it's going to be EOL very soon. We'll see what happens. I was the next guy, that app started in 2011, I got it in 2012.
Orphan and incompatible gems happen. They make upgrades more difficult but I always handled them. With node it's an order of magnitude worse because of the much more rapid pace of change. It's the main reason for I would not recommend using Node.
Java just costs more to the customer. I use it only when I'm the next guy in a Java project. It's always a pain to work with it. It's like those ten lines would be one if this was Rails and I would have delivered two days ago (small new features). I just don't understand why developers want to inflict that environment to themselves.
Because Java is a huge chunk of the job market (at least in the Sacramento area), not because it's a "language of choice" . Actually, the JVM is a nice thing, even if the Java language is primitive and verbose.
Too bad the jFoo alternate language implementations haven't got more traction yet. (jRuby, Jython, Nashorn, et al)
Because it takes so long to start and you feel it whenever you run the tests. It gets a little better if you disable the JIT compiler and so... in dev mode, where developers spend all their life, it's not faster than RMI. Because it used to support only the syntax of older versions of Ruby. Basically devs get all the pain of the JVM and none of the gains. Guess what they want to use? A customer of mine asked me how to migrate from jRuby to MRI because devs where having problems. I explained and suggested they could try using MRI in dev and keep jRuby in production. They're a JVM shop. I'll ask them what they decided to do.
Java 8 is not bad but still trailing Ruby by a long shot in terms of readability. Thinking in Ruby I wanted to implement the Java equivalent of
where validations is a List<String>.I ended up with a small nightmare with streams and collectors. That boilerplate shouldn't belong to this world, probably it's there because of the Java way to static typing.
They use Spring, don't know which versions, but it's got @RequestParam annotations to extract parameters from the request body. I think this is Spring Boot. It looks like Sinatra because of the @RequestMapping. Having @RequestParam in the action arguments looks a little like Phoenix pattern matching but I didn't have time to dig into the web and understand if it can really route requests to different actions according to the RequestParam. Overall is more or less where Ruby frameworks where ten years ago unless it's got pattern matching.
The webapp I had to work on still use ctags, which are a major PIA which slows down work and raises costs.
Queries are written in SQL, which is perfectly OK, and executed on a connection returning a java.sql.ResultSet. Not shiny but everybody can understand that. I googled jOOQ and it looks like ActiveRecord/AREL for Java. Nice but it would have cost me more time for this kind of quick hack.
I don't agree on the sentiment in the article that it's hard to follow what happens in rails/activerecord. It's pretty well documented and all the quirks are thoroughly discussed on stackoverflow. Ruby has excellent tooling and it's easy to find performance bottlenecks.
On the negative side though, I find that I use other languages when I need performance or better concurrency, but that always comes at the price of lengthier development.
That's the only justification anybody ever uses for choosing Rails, so I'd hardly say it's overlooked.
I have no idea how big the community behind each library/framework is and honestly I don't have the time to properly test-drive multiple and research the health of their respective ecosystems. With Rails I can rely on 10-15 gems that can help me with 80% of my projects. Perhaps I overestimate my reliance on 3rd party code, but that leaves me with my second issue.
Ruby jobs are de facto Rails jobs. I have weekly email newsletters set up for Ruby jobs and in the last 3+ years only a handful were Sinatra/Rack based. It would be interesting to see a reliable source of non-Rails Ruby jobs out there.
Even if you grant that good programmers can pick up new languages or frameworks easily (which I'm not entirely convinced of - there is a wide gulf between "can follow the tutorial" and "successfully used in anger"), you'll incur a penalty in velocity while all your new hires learn Framework X.
Anecdotal example of the perils of going off the beaten path: I often see a job advert on StackO for a company looking for Python/Django guys. When you click through to the job description, they are actually using Perl/Dancer. Not that there's anything wrong with that, but for me personally that's a deal breaker. I have no interest in investing the time to become proficient on that particular stack.
I think the question is more "Does what we're doing require good programmers, or can we get by with shitty ones?" More often than not, you're not doing anything special, and you want to pick a platform that the cheapest, most common programmers out there can add features in a non-disastrous amount of time (different depending on industry + your competition), and not generate enough technical debt to collapse everything before the next rewrite/upgrade cycle.
If you didn't fully embrace tableless design with CSS, despite the latter's glaring defeciencies for that task, it was the same treatment.
I also recall great pressure to adopt EJB with its deeply flawed architecture, etc.
I could go on, but the point is that there seems to come a time when all of these things face a moment of truth, wherein sober minds feel a little freer to speak aloud on their shortcomings. This frequently snowballs into all out backlash against the tech in favor of The Latest Shiny Thing.
The enforcers of what's hip and smart for everyone now move on to browbeating Developer Land with the new tech, and we all allow it to happen again. Why do we keep repeating this process when we've all seen the movie so many times?
[1]https://quoderat.megginson.com/2006/03/06/programming-langua...
This behaviour is counter to the model2 MVC implementation that rails is using as controllers should really be in charge of coordinating (helped by specialized classes if need be).
The author correctly points out that the way rails deals with views is painful however rails views are not tied to the model at all, they are tied to controllers and this can be modified if need be.
I personally maintain an approach of tying dedicated ruby classes to view files (e.g. SidebarComponent) and compose the view in the controller using a chain of these classes. This approach is much more object-oriented and avoids the weird pass-along view-hierarchies that many rails projects have.
There are much things to improve about rails but the project doesn't seem to absorb more object-oriented approaches over time and is tilted heavily towards DSL's for everything and doesn't value creating a more specialized class hierarchy to encapsulate more complexity.
I don't see a need to move away from Rails yet though as you can easily work inside the framework in a more Object-oriented approach. I guess you can characterize my approach as skinny models, skinny controllers, fat business logic objects and every partial is powered by a view object.