
Thoughts on Rails, Node, and the web apps of today - paulbjensen
http://paulbjensen.co.uk/posts/2012/07/11/thoughts-on-rails-node-and-the-web-apps-of-today
======
ef4
Node is maddening for one simple reason: asynchronous code _shouldn't need to
look like asynchronous code_ , and in fact it's much safer and less verbose if
it doesn't.

The whole performance argument is completely beside the point. Yes, we get it,
in-process asynchronous parallelism is where its at. But it simply doesn't
follow that we need to live in inversion-of-control hell.

Even the simplest node program ends up drowning in error-handling code,
because there's no way to automatically propagate errors back to the right
place. Every function needs to handle error conditions immediately, because
you can't throw an error up the stack, because your stack is completely
meaningless.

This is a huge step backward. It feels like coding directly against system
calls in C.

It doesn't need to be this way. There's no reason your language runtime can't
be smart enough to switch contexts automatically, so that your code gets to be
"blocking" even though the actual OS-level process is never blocked. Erlang
does this, Stackless Python does this, any Lisp with good old call-with-
current-continuation does this.

~~~
IsaacSchlueter
> It feels like coding directly against system calls in C.

I disagree. Coding directly against system calls is much harder in C, because
you don't have the advantage of closures and flexible typing. But, that aside,
node _is_ intended to be a very low-level library that facilitates higher-
level extensions and abstractions in userland. It is more like C than it is
like Python, and that is by design.

Node is JavaScript on the server. It is not JavaScript-like, or Compiles-to-
JavaScript, or Erlang-with-semicolons-and-braces on the server. We don't mess
around with the language runtime, we take it mostly as-is, and there is a huge
benefit to doing that.

When and if V8 implements generators (as they are likely to do somewhat soon),
then I expect we'll see a lot of experimentation in this area in userland
modules. They'll have to be run with a --harmony_generators flag, most likely,
but they won't need to be compiled or do scary bad-touch things with threads
and stacks.

When the area has been explored a bit in those userland modules, and one or a
few of them are popular and good and intuitive to use, and V8 moves generators
out from behind a flag, and they're fast enough to be used in node without
introducing performance regressions, then we'll investigate adding something
like this to node-core.

Part of the reason why you meet such backlash from people in the Node
community when you complain about "callback hell" is that the model _is_ very
simple, and it really is not as bad as it looks at first. JavaScript's bulky
"function" keyword does make CPS quite a bit uglier than it is in Scheme, but
it's a very reasonable approach to the problem which is extremely extensible.

The crappiest part in my opinion is doing `if (er) return cb(er)` all the damn
time. Domains make that a little bit easier, but you're just trading one bit
of boilerplate for another, so I don't know. Generators are probably the ideal
approach to that problem, but I'm personally not sure they're worth the
complexity cost they introduce. I am often wrong, and try to be quick to admit
it. We'll see how they change the shape of things once they're a real thing
and not just an idea.

In the meantime, use named functions. Use the "async" utility. Use Stream
interfaces and .pip() them to one another. And most of all, _Don't write big
apps! Write small modules that each do one thing, and assemble them into other
modules that do a bigger thing_. You can't get into callback hell if you don't
go there.

~~~
tjholowaychuk
If you're writing really sensitive things then callbacks are great, but I
strongly disagree that this should be considered "good enough" for app-level
code, but with the current state of node as a community it seems like would be
very very awkward to even introduce something else right now. node-fibers is
definitely annoying since you have to compile but even if you didn't you'd
still be wrapping all of your favorite existing libraries to have a nice
interface. As for back-pressure etc there's no reason why that doesn't work
well if not better and implicitly with sync-style, many languages do this
already and do it really well. I love node but the core community needs to
stop being ignorant towards other concepts thinking that callbacks are simply
"the way to go" when they're simply codesmell for many if not most
applications.

Stuff like "hey @nodejs people lets make a website called
<http://fibersarestupid.com> in which we provide education on how to use
callbacks and streams" certainly doesn't help, it just makes node as a
community look childish, maybe the site should be called
iDontUnderstandFibersThereforeIDismissThem.com... come on.

------
drharris
Am I the only one out there that _doesn't_ think single-page apps are the
future? It reminds me of the mid-2000s, "AJAX all the things!"

I might be wrong about it, just not on this bandwagon at all. I still find the
true power in the internet is hypertext, and single page apps seem to break
it. Of course, I also prefer articles over video and not having a firehose of
information thrown at me. Can someone point me to a way to use Node that
actually makes sense for something that doesn't have to be near-real-time?

~~~
kyledrake
You are not the only one.

Client side apps are strangely messy, and make it impossible for search
engines to index your site. This is exactly why Twitter is largely walking
away from their client-side web site.

~~~
why-el
There is a whole class of web applications where it does not even make sense
for search engines to index your site: todo lists, real-time chat, finance,
and so on. So yeah, if you think it is important for your app to export
content, then by all means don't build a single-page app.

------
jroes
I'm not sure why Sinatra was not considered in the mix here. Sinatra is great
for building simple APIs in Ruby. Heck, Express essentially started out as a
clone of Sinatra for Node.

One challenge in the Node community is the ecosystem. There are not nearly as
many libraries in npm as there are in RubyGems. Of that small set of
libraries, a large portion of these have been abandoned. Of that smaller set
that haven't been abandoned, there are large portions of missing
functionality, are not very stable, or are constantly changing.

There are certain cases that Node works really well for right now, like
building real-time chat apps. But having worked on some medium-scale Node
projects recently, I constantly find myself re-implementing Rails
functionality or rewriting common Ruby gems due to the lack of mature
libraries.

~~~
arturadib
I think the author emphasized _performance_. Sinatra might be Express's
precedent, but it doesn't have Node's runtime behind it to deliver performance
(async I/O, low-memory footprint, etc).

~~~
jshen
"deliver performance" is too abstract. I usually throw varnish in front of my
ruby apps to get performance. I find this gives me a more productive
programming environment (ruby), and insane performance.

Node only becomes useful for me when I need to keep a lot of connections open
and handle them simultaneously, and a few other rare situations like that.

------
davidw
I'm sure Node is generally faster and consumes fewer server resources than
Rails. How about speed of developing things though, that do involve a
relational database on the server? Rails has so much in terms of convenience
functions that it's hard to jump to anything else, outside of applications
where it's clearly not suited. Erlang has been faster and better at async than
even Node since before Node even existed, but it's painful to use after
getting used to Rails because it feels like a lot more typing and a lot more
doing stuff by hand that Rails handles easily.

~~~
paulbjensen
I agree, Erlang is very interesting (especially for the hot-code swapping
capability). I've been looking into it recently, specifically a project called
Elixir (<http://elixir-lang.org>) which is a language built on top of the
Erlang VM.

~~~
_nato_
Also, check out Chicago Boss!

------
arturadib
> _I see a picture emerge where the back-end will become purely an API
> component_

Not so fast.

That makes sense for highly interactive apps with private content (Trello,
Gmail, etc), not so much for public-facing and content-driven sites.

That is, unless you're OK with sacrificing that organic Google traffic to your
site?

If not, you have two options: do the entire rendering + biz logic on the
server (in which case Rails still makes a lot of sense, though some Node
frameworks are getting there), or duplicate your client-side code on the
server so that Google's hashbangs work.

The bigger picture is that the web + search engines are kind of broken right
now: There's a tremendous opportunity to make progress and use the
architecture pointed out by the OP, but as of today there is no simple
solution to make the architecture play nicely with Google without duplicating
the work on the server (Meteor seems to be making progress there).

Until a simple solution is found, I think we're stuck with the dilemma and
will have to continue to do MVC both on the client and on the server.

It sucks.

~~~
facorreia
I assume he's talking about web apps, not web sites.

~~~
arturadib
> _I have abandoned Ruby and Rails in its entirety_

So I thought he was talking about both. (As I once considered doing, too).

Also very frequently the distinction is rather blurry: Is Twitter an app or a
site?

~~~
facorreia
When you have a content-driven site that has to be indexable while supporting
user interaction, usually server-side generated HTML with client-side AJAX
(preferably with graceful degradation) can be an effective pattern.

For line-of-business apps or apps in general that can benefit from a rich
interface and possibly local storage, full client-side presentation layer
(HTML or native) coupled to server-side pure web services can be effective.

------
lucian1900
Dammit, it's not real-time web. There are no time constants considered,
designed for or proven.

At best it's "live" web or "quick update" web.

~~~
paulbjensen
Sorry.

~~~
lucian1900
Sorry, I didn't mean to come over as angry. No need to apologise.

It just bothers me that the term real-time is being misused a lot nowadays.

~~~
bergie
Yep, I like the term _Live Web_.

------
masto
Rails developers seem to be having this revelation a lot recently. I don't
think it's a particularly new idea, and I don't see why Rails vs Node vs Java
has anything to do with it. MVC is ok for a backend that's "just an API"
(although there are probably better ways to structure things, such as CQRS).
The language is irrelevant apart from the reasons it's always been relevant
(speed of development, ease of deployment, testability, etc.).

I think the point at the end is worth expanding on, though: as long as your
API is an API and not a thin connector to a specific backend technology, you
can in theory swap out parts or the whole thing. Some time ago my company
decided to build a new "web application", and there was some debate over how
to structure the communication between (at the time) Flash and the backend.
Some argued in favor of a proprietary protocol that makes it very easy for
Flash to talk to Java and share data structures. Had we gone with that
approach, we would have: 1. not had an easy path to having an "external API"
by leveraging the identical internal API already built, 2. been stuck with
Flash or at least had a much harder time converting to HTML when it became
obviously the right thing to do, and 3. been stuck with Java on the backend
and no clean service interface between the backend and fronted models.

It's always necessary to take some shortcuts in development, and I believe
it's very important to choose the right shortcuts. Compromising on interfaces
and encapsulation is almost always a terrible idea; better to spend the time
hiding an ugly implementation behind a clean interface so that you at least
have the option to fix it later.

~~~
pjmlp
We had this revelation already back in 2002!

Back then, I was working for a startup that had a product similar in concept
to Rails but based on Apache/TCL developed around 1998. The initial
architecture ideas were taken from AOL Server, in case anyone still remembers
it.

Around 2001 we reached the conclusion that it wasn't scaling any longer for
the type of loads that we needed, and more a better language infrastructure
was required.

After some research, the framework was ported to .NET, on those days still
beta, but their JIT could already yield much more performance than our home
grown solution.

~~~
davidw
> Back then, I was working for a startup that had a product similar in concept
> to Rails but based on Apache/TCL developed around 1998. The initial
> architecture ideas were taken from AOL Server, in case anyone still
> remembers it.

Which Apache Tcl thing? Who are you, by the way? Your profile doesn't show
anything.

BTW, Rivet can be scaled, like anything else can, although you're right that
given the same resources, a compiled language is going to be more efficient.

These guys use Rivet successfully:

<http://flightaware.com/>

\- A former developer of Apache Rivet.

~~~
pjmlp
This was way before Rivet was known, at least in Portugal.

I'll be sending you an email describing how it was.

------
programminggeek
Having built with node, ruby, python, php and even did a web services
framework in node, I can say that the author is both right and wrong. Right -
node is fast/faster and that rails is probably overkill for making web api
stuff. Wrong - single page apps are the future.

I write single page apps, especially mobile JS apps, BUT rails style
frameworks are still incredibly important for 1 huge reason - search engines.
If you have a content site, you will have a web front end that is indexible
for at least the next 5-10 years. Single page apps are not as
indexible/crawlable yet.

So, will you write some single page apps? Yes, are they the one true future,
no. The future is probably a combination of native apps on various devices, a
traditional web front that is indexable, and probably some single page
javascript stuff powering admin panels and highly interactive portions of your
site that don't need to be indexable.

For example, in creating ReMeme (<http://reme.me>) it has a web front that is
indexable by google, it has mobile apps and the whole thing is backend API
driven by a sinatra app. At this point I have potentially 4 different
platforms talking to the api, not just a "single page web app". If it ever
gets on more mobile platforms or even on the desktop, that's even more.

The web's a big deal and will stay that way, but you'll probably find yourself
writing a bunch of interfaces in different languages, platforms, etc. before
you know it. Rails vs. single page isn't the debate. Pick a tool and ship your
API, it doesn't matter if it's rails or node or python or php.

Once you ship your API, your bigger problem will be how do you manage the
complexity of developing for so many platforms?

~~~
stdbrouw
> BUT rails style frameworks are still incredibly important for 1 huge reason
> - search engines.

A project I toyed with a while ago, but never finished (because I don't need
it right now), was an app server that can render and serve Backbone views on
the server, for search engines and to speed up the first page load (after
which most clients would switch to client-side rendering.) See
<https://github.com/stdbrouw/backbone-express>.
<https://github.com/developmentseed/bones> does something similar. There's a
ton of reasons why people would want to stick with Rails or another server-
side framework, but searchability isn't necessarily the big problem.

------
_nato_
I am involved with a Rails project where the creative developer decided a
single-page app was what we needed. We use the views/partials as fetching
pieces, calling them via ajax calls and all is well. The added benefit is
every unit of namespace has its own home, so SEO for everything is achieved. I
am a huge advocate for the newer and better, but Rails is a great solution for
single page applications. Also, it's great to write code in Ruby whenever one
can; cmon, life is too short!

------
charliesome
> _This decoupling of MVC is well-supported, but you then find that you're
> using Rails as an API alongside being a web application; It's not a clean
> definition of responsibilities._

I'm not so sure about this part. To me, it feels like the difference between a
web app and an API is simply the fact that an API returns machine readable
data (be it JSON, or XML, or whatever). The JSON/XML/etc is just another way
of presenting the same data - you should still be able to share a lot of the M
and C between your two Vs.

------
radagaisus
We've been using both NodeJS and Rails for the last 4 months. Javascript is an
amazing language, and coffee makes it even better. After writing a lot of
Resque jobs today I have to say my Ruby-fu is not strong, and yet - NodeJS
ecosystem is so so so so not mature enough for prime time.

The reason I wrote my jobs in Resque? Confidence. If shit will break - it will
be on my side, not inside a package required by another package somewhere deep
inside node_modules. I'm reading the source of almost every node package I
use. I check all the issues on GitHub before trying to play with it.

While node core is stable, and everything is so damn fast (thanks Redis) and I
enjoy every minute of developing with this stack, I find myself too many times
inventing the wheel all over again - instead of focusing on my product.

------
jawr
What about that old saying: "The right tool for the job"?

------
robot
Can you not mix Rails with backbone.js and the like? I thought it was
possible.

~~~
taterbase
You can, it just makes some of Rails' niceties unnecessary. Views and
"Controllers" are handled up front by backbone. You just need routing and
models from Rails.

~~~
irahul
> You can, it just makes some of Rails' niceties unnecessary. Views and
> "Controllers" are handled up front by backbone. You just need routing and
> models from Rails.

backbone.js sends CRUD requests to rails app which are handled by the
controller, and the main page is rails view.

------
js4all
Very good article and exactly how I experienced my last projects. There have
been other articles lately on HN about the changing role of the MVC pattern.
The views and models are now on the client. This is ideal because this way the
client can respond to several actions without calling the server. The server's
role changes to a data driven backend via an API. The API however can also be
built using MVCs on the server.

Node.js is an ideal candidate for the server, because it is very well suited
for building APIs.

------
scrozier
Paul has articulated clearly what I had as a visceral reaction after attending
this year's RailsConf: Rails is being relegated to being an API machine, and
DHH et al are none too happy about it:
[http://amillionbetterthings.com/2012/04/26/the-rails-
times-t...](http://amillionbetterthings.com/2012/04/26/the-rails-times-they-
are-a-changin/)

------
jondot
I heard the first call for "Rails is dead" around 7-8 months ago. While then I
completely disregarded it, now I'm even more so disregarding it.

I choose the right tool for the right task. Linger on that over-used saying
for a moment.

I use Rails when I'm not familiar with the domain enough (this is the business
of Software Engineering, we never are as familiar with the domain as the
domain experts) and it provides me a platform for radically fast development,
in the end I may also have a product that can withhold 2-3 years of evolution,
before we need to scale, if even needed (premature optimization..).

I also use Rails when the quality levels are set high, and when I need tons of
libraries, and I need those fast. In node, the quality level of such libraries
are much worse (if you haven't seen it, you're not doing Node enough time -
because I haven't seen it at my first half a year on Node). The number of
quality libraries / npm modules are probably several magnitudes of order less
than that of Ruby gem world. You're going to need to wait 4 years until you
get that level of diversity and quality and it sets up in a comparable way.

And I use Ruby when I don't care about slow clients, or doing system-level
work.

At any given time, I keep myself the option to use JRuby, which has comparable
to MRI (the "normal", C implementation of Ruby) performance and better on a
considerable number of criteria. IMHO DynamicInvoke on the JVM will be a game
changer in terms of people considering JRuby against, Groovy, or Scala.

I use node.js when I know the domain will remain small, non-complex, and I'll
be dealing with slow clients (real users).

To top all of that, backend systems will NOT turn into thin api servers. Not
by any chance. Twitter themselves are rolling back their SPA and bringing back
server side template rendering. The number of problem you get into while
moving all of your logic and rendering to the client requires a huge blog post
which I'll probably make one day. Most people are not aware of that because
they never came from full-fledged enterprise level desktop apps -- I used to
design CADs and pretty familiar with complex client-side architectures, there
are so many dragons there, I'm very happy I now live on the server side, where
things are much more predictable.

So no, Rails is not dying and neither is Ruby. With the advent of progress on
the JVM and JRuby they never will -- this whole discussion reminds me of "Java
is about to die" when Scala came around and "Java is about to die" when Oracle
came around. And guess what - it didn't (go read about Java 8).

tldr; I use both, and I'd recommend anyone would, too. Server-side will never
be just a thin api, Ruby or Rails will not die (at least not by that sword),
and the only thing one might want to work on is a good foundation of intuition
of when to use which of those.

@jondot

------
VeejayRampay
Ilya Grigorik is the man. He had all the best ideas, he had implementations
and presentations about asynchronous Rails, about how Node was nothing
special, nothing that could not be done with Rails. I wish he would still an
integral part of the Rails community. Huge loss.

------
Void_
How big an application have you built with Node.js?

How complicated was the business logic?

~~~
js4all
I see where this question is going. The logic was rather simple and even
though the client-side minimized JS code was already more than 200KB. The
optimum cut probably lies some where in between and having logic on both
sides.

------
tubbo
The reason why Rails is going to continue being awesome even in the API-
dominated web apps of tomorrow, is the asset pipeline. There's just __nothing
__else out there that manages your assets quite the same way. In fact, the
asset pipeline makes it dead-simple and even efficient to program big, high-
performance apps in CoffeeScript. Sure, it doesn't _force_ asynchronous
behavior, but I feel that's more of a feature than a flaw. Sometimes,
asynchronous calls are just not possible (like in the case of Authorize.Net's
API), and you need to build something a little more robust, and easy to test
when things go wrong. Therefore, I feel Rails is actually the best choice for
an API backend, because it has so many drop-in monitoring tools available as
well as ways to enhance performance by dropping frameworks you don't need,
plus you _can_ code asynchronously with it but you don't _have_ to.

------
tferris
Great article and still wonder that not more people got the idea of Node,
Mongo and related tech. Rails isn't bad and full of good ideas and a rich
ecosystem but at the same time it's terribly aged in lots of areas.

~~~
pjmlp
I don't get it, because I have being doing asynchronous server side
programming for years in C, C++, C#, Java.

It is already enough that I have to deal with JavaScript on the UI side.

~~~
rch
Could you imagine a dedicated JavaScript developer accessing your code through
a messaging service? Then you wouldn't have to deal with it at all...

* why the downvote? Is it for being stupid, or for sounding snarky?

