Node.js is one of the worst things to happen to the software industry in recent times, a whole generation of programmers are being taught the worst of all ways of doing concurrency, in a system that doesn't scale either in performance or project size and with one of the languages most plagued by pitfalls ever created.
JavaScript was already painful enough in the browser, why on earth anyone ever thought it was a good idea to use it on the server boggles the mind.
We will be paying the price of this misguided hyped fad for decades to come.
Of all the ways of doing concurrency, callbacks are by far the worst, Twisted was plagued by them and is the main reason why it failed, and that was with a much more sane and reasonable language like Python (stackless Python was a much better alternative and used a model similar to Go's CSP).
And the sad thing is that there are much better alternatives around with much more sound models and environments, Erlang and Go are the two obvious examples, and that is for the highly specialized situations where you have great concurrency needs, for any other problem anything else will be much better than Node.js, even PHP.
I agree that the Node.js model of concurrency is one of the weakest models out there. CPS is for the compiler writer, not for the programmer.
The underlying problem is that sequential languages do bad when you "bolt on" concurrency to them - unless said language is expressive enough to make it bearable (Haskell and some MLs come to mind). For all other language, you are just frankensteining your system.
The reactor-model, of which Twisted, Node.js and a couple of like systems are built around has one advantage: It is fairly easy to get going. It is by far the simplest model you can get bolted onto a system with relative ease. The crux of the problem is that we have a lot of sequentially oriented programmers who suddenly need to do full concurrency. This is the first attempt.
To a professional Erlang programmer like me, it does look rather odd that one would hail a reactor model as being anything decent to work with. There are other concurrent calculi out there, which may be better than what Erlang provides, but none of them worries about callbacks in the style of Node.
I have a hunch the kid must be dragged screaming into the concurrency shop.
> The underlying problem is that sequential languages do bad when you "bolt on" concurrency to them - unless said language is expressive enough to make it bearable
Really?
I'm not familiar with Erlang, but have you tried Go? Concurrency fits seamlessly into the language.
Go is not sequential, but concurrent. It has built-in primitives for handling concurrency, witness the `go` keyword. It also has special syntax for doing selective receive over channels, which in turn means that the concurrency of that language is definitely not "bolted on" in the sense I meant.
Perhaps you are confusing my definition of "sequential" with yours. I tend to use "sequential" as the opposite of "concurrent" like I have another, orthogonal, axis for "serial"/"parallel". So you can be serial/concurrent (Node.js is close to this. So is a 4.4BSD OS without any SMP support). And you can be sequential/parallel (GPUs is my preferred example).
No JavaScript in all honesty was painful because the way it was designed (it was made in ten days). Equality operator ('==') is a cause of MAJOR headache and so is the global scoping, the bizzaro addition operator, etc.
http://stackoverflow.com/a/9033306 - this "wat" meme is getting old. At best, you people that keep posting this are automatically qualified as trolls. The fact is that probably none of you folks from the "wat" crowd didn't take the time to read the ECMA standard. I don't claim that the behavior is intuitive, or appropriate for some cases. But the lack of RTFM isn't excusable either.
And yes, developing under node is not the same as developing for the browser where you need to use the lowest common denominator, which usually is IE6.
I'd say that the issue is the "omg node.js" crowd that promoted it as the hammer for every issues that may pop out. It isn't. But this doesn't mean that it is completely useless.
Sorry, but please explain how is this issue somehow elevated by node when it is a part of language standard (ECMAScript standard linked in the article it posted)? Does V8 break ECMAScript? This is a gotcha of a language. It uses + operator that does something completely differently than what it usually does on almost any other language with similar syntax. It's the definition of counter-intuitive.
> I don't claim that the behavior is intuitive, or appropriate for some cases. But the lack of RTFM isn't excusable either.
You failed the read test. Twice. The first was the manual itself.
> please explain how is this issue somehow elevated by node when it is a part of language standard
You failed the read test. For the third time. Please indicate the part where I claim that node elevates the issue vs. standard ECMAScript behavior. I said something about the node vs browser runtimes. This is a totally different beast.
> This is a gotcha of a language. It uses + operator that does something completely differently than what it usually does on almost any other language with similar syntax. It's the definition of counter-intuitive.
The only gotcha is the coercion that some regard as dark magic vs statically typed languages vs the operators themselves. The "+" and "-" operators in JavaScript: "+" for summing Numbers or String concatenation, "-" for subtracting a Number from another Number (which basically makes it a strict arithmetic operator, you know, stuff for Numbers).
Besides:
- PHP uses the + and - as strictly arithmetic operators (it has the . operator for string concatenation), while summing up two strings equals int(0) since (int) 'foo' === 0: http://php.net/manual/en/language.operators.arithmetic.php
- C (and to some extent C++) uses the + and - as strictly arithmetic operators: invalid operands to binary + (have ‘char ’ and ‘char ’)
Yes, I may have skimmed a little. But this doesn't excuse language makers for not anticipating such a use common case and returning a result that can be said to be expected (i.e. error, trying to add one list on other). If there isn't a real comparison, you should take a couple of people that are likely to use this and say "what should [] + [] return". You can't say that they couldn't have implemented " []+[] " throws a TypeError or something, even in a dynamic language.
It is said that API is UX for programmers. Well this is UX for a computer language. And JS fails at it. Big time. And this isn't the only stumbling rock (see global variables, == operator, semi-colon insertion, etc.).
My point was that developing under Node.js is same as developing under a browser only the lowest common denominator changes to V8.
Edit: I'm pretty sure + operator in Ruby concatenates two arrays.
Couldn't agree more. But that's the standard. At some point I hoped that the ES5 'use strict' would fix all of this SNAFU, but it didn't.
However, not even once I tried to sum [] + [] or {} + {} till that "wat" video. Funny, but unrealistic, therefore: close, but no cigar. One could operate the "World's safest table saw", but the common sense tells us that usually finger vs. saw => saw wins. Safer tools are desirable, but it's up to the craftsman to use them properly.
> the lowest common denominator changes to V8
V8 is pretty much on par with its competition with the ES5 adoption, therefore we can hardly talk about a lowest common denominator that's actually low. The only thing that I actually missed in V8 vs. the Mozilla engines is the support for E4X (which most runtimes don't support anyway).
http://kangax.github.com/es5-compat-table/ - even if IE6 and IE7 are gone from the traffic stats, IE8 is there to stay with the XP users. Some of us still don't have the possibility to just drop those users as long as the analytic data shows a fair share of legacy users.
Ruby isn't part of the "similar syntax" family. The '==' operator isn't recommended in JS (and PHP). In fact, jslint yells at you if you use it. That's why '===' exists. The semi-colon insertion is one of the big failures on the "allowed" part. Wish that never happened. But any developer that doesn't try to adhere to some hipster JavaScript coding style uses the semi-colon at the end of the statement.
I don't find that makes much difference in practice because most developers learn about the good parts of JavaScript early on and so ignore these things.
Yes, the lack of proper standards made it even worse, and yes, JavaScript has 'good parts', but JavaScript is still chockfull of wat: https://www.destroyallsoftware.com/talks/wat
That video is completely misleading due to a quirk of the repl treating {} as a block not an object, not really a language wart.
Try it yourself:
var a = [] + {};
var b = {} + [];
Miraculously they are same (but only because the list is empty, string concat order matters obviously)! The only time that wat can ever happen is a case that would never exist in any actual code. The Dom is full of wat but I still havent seen any legitimate cases in js itself.
Why not? A thread allows for two parts of the program to be running concurrently. Whether or not they run in parallel is orthogonal. Why don't you think they allow for concurrency?
So who's wrong here? The world leading academics behind Haskell, Scheme and Oz? The industrialists and pragmatists behind Java? Or little old you?
The reality is that threads were created only to allow for concurrency. They were then re-used to allow for parallelism when we had multi-processors and then multi-cores.
Edit: does this guy work at Google? Unbelieveable.
>In computer science, concurrency is a property of systems in which several computations are executing simultaneously, and potentially interacting with each other. The computations may be executing on multiple cores in the same chip, preemptively time-shared threads on the same processor, or executed on physically separated processors. A number of mathematical models have been developed for general concurrent computation including Petri nets, process calculi, the Parallel Random Access Machine model, the Actor model and the Reo Coordination Language.
You can certainly build the actor model on the backs of threads.
What are you on about? Concurrent programming is the set of problems that exists when there are multiple 'computational processes' accessing shared state. This is a 'thread' (overloaded use) about JS, but Java has a package called java.util.concurrent and there's also a seminal book called "concurrency in practice", these are about nothing but threads.
Parallelism is just a new buzz word for people who have just discovered that threads\processes exist and they can have multiple things running at the same time. They just removed the shared state cause they don't want to have to deal with the headaches of concurrent programming.
And I quote, "In computer science, unbounded nondeterminism or unbounded indeterminacy is a property of concurrency by which the amount of delay in servicing a request can become unbounded as a result of arbitration of contention for shared resources while still guaranteeing that the request will eventually be serviced. Unbounded nondeterminism became an important issue in the development of the denotational semantics of concurrency, and later became part of research into the theoretical concept of hypercomputation."
If you haven't even read the wiki page, what have you read about concurrency exactly? Are you just making it up as you go along? Is confabulation about topics subject to factual review a habit for you?
Unfortunately can does not mean always will. For example, lock-free algorithms do not have any contention, ergo we can have concurrency without running into unbounded non-determinism. Please try to actually understand what you're talking about before being so rude to people. Copying and pasting the first thing you find on Google is no substitute for learning and careful research.
I'm actually pretty familiar with the current state of deterministic concurrency as a field of research and it has little to do with lock-free algorithms at all.
For that matter, what little of deterministic concurrency exists (FP interleaving, coroutines), it is only the palest imitation of true concurrency and how it gets used in practice for which one can SAFELY assume that useful and meaningful concurrency DOES IN FACT constitute non-determinism which also happens to be an apt way to summarize and contrast the subject with parallelism.
What? You can't just dismiss coroutines as not "meaningful concurrency". Given that every major language outside of C and Fortran has a native implementation, I'd call that pretty useful, and pretty meaningful.
> Concurrency is by definition, non-determinism.
The fact is that you are wrong: coroutines are a form of deterministic concurrency. They're also very useful.
I get the impression that a lot of people are trying to use Node for things it isn't particularly suited for. That being, 95% of the things you'd want to build on the web.
My take on Node is that it's what you use when you want to build an Etherpad. If your app will have 1000 people messing with one thing at once, with all their interactions propagating out everywhere instantly, you're going to want to use Node. If you're building a mmorpg-in-a-browser, you'll probably find Node will be a good fit.
If you're building a CRUD app, however, Node is likely the worst choice you can make in terms of productivity lost versus advantage gained. I mean sure you'll pull it off. But the kid who wrote the same thing in Rails will be on his third failed startup by the time you get your MVP launched.
There's probably a balance that you can strike for apps that "sorta" need Nodeishness. Use a standard, non-insanity-inducing stack for the bulk of the site, then keep a Node instance off in the corner to run the "App" bit that needs the realtime communication.
I think this message got lost somewhere along the way, and now we're seeing a lot of frustration from people using this cool, specific, technology for stuff that it's just plain not suited for.
I understand node is quite good at those scenarios but is there any real advantage over say Ruby/EventMachine or Python/Twisted or if you're serious about it scaling, Erlang/OTP? Evented systems are great for those scenarios but I can't work out if there's some secret sauce in Node I'm missing or whether there's a lot of excitement from people that don't realise there are mature solutions to those scenarios in other languages.
If anything Node is much more limited than the alternatives, both because of the language it uses, and because of limitations of the implementation, which basically (rather ugly hacks aside) doesn't scale at all beyond one core, and if any of your code turns out to be CPU bound, your performance goes right out of the window.
Go and Erlang are much better both in the concurrency models they provide and in their performance and scalability. Not to mention they are real languages carefully designed over many years by talented language designers, not the result of unfortunate accidents of history hacked up in two weeks like JavaScript.
Node has multi-core via message passing. Erlang has... multi-core via message passing. Now there are other differences in their concurrency models, but they're not worlds apart, and the idea at node does not scale beyond one core is false (see the Cluster module).
There are a number of reasons. I work on one of the larger node apps out there, and its working great for us (admittedly, we use CoffeeScript, which eliminates half of the arguments made against node).
- Server/client sharing. This sounds like its not a big deal, but it is if you're writing an app for which node is a good choice. Our code is close to 50/50 client/server (maybe a little server-heavy), and the amount of shared code is fairly surprising.
- Native JSON. All of the data that we send from our servers is JSON (with a few exceptions for errors). Mongo speaks JSON as well. Its extremely useful that all of our data is in the same format, including that going over the wire and that inside our code.
- One language. I've used server-side Python before, and it is way easier to only have to think in one language, especially if you jump between server and client code often.
- CPS. Everyone's hating on it, but its hard to see the advantages of it without working on a large project first. I was very skeptical when I started, but it really works well. Most people are immediately turned off by the amount of nesting involved, but a simple async library resolves this nicely.
- Javascript. It has problems, but most of them are ways to shoot yourself. If you avoid shooting yourself, it really is a beautiful language.
The biggest problem with node is that the average programmer* probably can't grok CPS. Its honestly a lot harder than most code you'll see. That said, I can't imagine the codebase that I work with being less than an order of magnitude larger without it, so its well worth it.
*In my experience, the average programmer can't grok recursion or pointers, either.
luriel wrote a nice answer, like a good, old hater would write.
(You can't just go around and insult programming languages. They have feelings too, dude.)
is there any real advantage over
I think that's the wrong way to choose a platform. Are you good in Ruby? Then use RoR. Are you good in JS? Then use node.js.
Maybe RoR is a much better platform than node.js, maybe it's not. But I finished writing my framework/application 10 times, before you even typed RoR. :D
Furthermore: You. Don't. Use. node.js. For. CPU heavy. tasks! Don't do it.
For everything else I think it's a wonderful framework, if you want to write something I/O heavy.
btw: The strict asynchronous programming style, using JSs closures, is pretty much the same thing you would write in C (except for that you don't have closures). I recommend everyone to look at least once into https://github.com/joyent/libuv/
But unfortunately many "programmers" here won't do it, since C is stupid and for old farts. I mean: I can do anything in C# in a tenth of the time compared to you with C (http://programmers.stackexchange.com/q/164017)
> But I finished writing my framework/application 10 times, before you even typed RoR.
You are never 'finished' writing, code requires almost perpetual maintenance and improvement. (Unless the project is a total failure or you are DJB.)
I'm sorry, but if you are only good in JS, or PHP, the very first thing you should do is become good with some better tools.
Yes, it is possible to write working code in any language and platform, but languages and platform still matter and have a cost you will pay during the lifetime of your application, in security, reliability, scalability and maintainability.
Please don't just grab some random words from my post. I'm pretty sure you know that the sentence in question was just an idiom. And just so you know: I have experience in, and still regularly use C/C++, C#, Java, Haskell, Ruby, Python, Javascript, PHP.
I don't know what node.js did to you (maybe you tried something as writing a whole webframework with node.js? or something as foolish as a file server?), but you should know that there are many projects out there which use node.js where it fits and it's running good (prime examples are Microsoft and LinkedIn).
> I'm sorry, but if you are only good in JS, or PHP, the very first thing you should do is become good with some better tools.
And I don't know what the hell is wrong with you, that you assume that you are the wisest of all men and know what is wrong with everything and what to use in any situation and what I know and what I do and what I should do...
> and have a cost you will pay during the lifetime of your application, in security, reliability, scalability and maintainability.
So thanks for this lesson. I swear I will spread the word, but before I will go and worship JS/PHP, as the little, stupid fanboy I am. (fyi that's called the language of sarcasm)
As I said: Don't go around and "insult" programming languages, because most of them have their right to exist and nobody forces you to use something you don't like, nor anybody else. Most programmer choose to use node.js and if they fail it's not necessarily the fault of the "tool" (though it can be), but also the fault of the programmer in question, by choosing a "tool" which didn't fit. I mean: You wouldn't try to put a screw in the wall with a hammer. Am I right?
> Are you good in Ruby? Then use RoR. Are you good in JS? Then use node.js.
Unless you're talking about getting a working prototype up-and-running, I could not disagree with this more. Classic "all I have is a hammer so everything looks like a nail" sentiment. Make your tool choice based on the problem you're solving.
I did build something extremely similar to an EtherPad using node.js a couple months ago for a toy project, and let me tell you, it would have been a lot easier with Go. We only went with node.js because of existing library support (google auth and the like).
I think that a much better alternative to Node than Python or Go is Haskell. Why? Well, for one, it makes writing asynchronous code very easy--you essentially get it for free. Haskell web servers perform very well while keeping the code readable.
However, ignoring performance, there are also all of Haskell's other advantages. The type system is great--you can do stuff like ensuring links within your app work using the type system. Haskell is also very good at embedding DSLs, which can make writing web-specific code much nicer. In my experience, Haskell code tends to be more concise and declarative than Go or Python, making it easier to read. And, crucially, you can program at a higher level of abstraction which makes it both easier to write and maintain relatively complicated code.
Now, admittedly, going from almost any other language to Haskell is quite a shift. For most programmers, learning Haskell will take a bit longer than learning yet another imperative language (e.g. Go). However, I think this is well worth it, and web apps are a particularly convenient field for it.
This[1] StackOverflow question and an associated paper[2] are very interesting to read about how a Haskell web server could work and have good performance.
It would also be useful to look at a Haskell web framework like Yesod[3], Snap[4] or Happstack[5]. I'm currently a little biased towards Yesod (which has, coincidentally, recently received commercial backing), but I think the choice of framework is largely a matter of preference.
/second Haskell. If I could do everything in it I would (stuck with JVM for some things though). Ryan Dahl even looked at Haskell before choosing V8, said the language is ideal but hacking GHC was too complex:
>I was into Ruby for a while, I said, but eventually the VM just drove me insane, because it's just so slow, every time you try to make it faster you realize: "OK, I am just going to write this part in C" and every single line of Ruby that you add to your application, actually just slows down the server noticeably. And so eventually I just kind of ended up with this big C thing that I was kind of happy with, like OK I could write a web server with it and I could do file IO and so I had for a long time the idea of "I would have this kind of library that abstracted some part of the problem away and people can write it in C and they can write their little web servers.
People don't like writing stuff in C. Basically I want to put people in this non-blocking environment because it is the right way to design a server, it just kind of maneuvering around all the other pieces of the computer system and I would really like to do such a thing in Haskell or some sort of declarative language like this, where you could literally be purely functional when you receive events off of the socket, because all your side effects would happen on the event loop and you would just allow that to happen and then you kind of get a function call with some data and you would do whatever with that, make some call which would not have a side effect, you just write something to some buffer that would get flushed to the kernel and then you drop back down to the event loop.
Side effects would happen, everything would happen and then you get another call from that. But when you are receiving an event from the event loop you could be purely functional, you could really have nothing to do with anybody else and that is attractive. But you look in the GHC code and it's very hard and I am not such a good programmer and I gave up on that. And then V8 came out and it just kind of clicked. I am not a Javascript originally, have nothing to do with that really, but it just seams like a natural sort of thing once I started poking around VA.
Learn you a Haskell for Great Good is one of the best introductory programming language books I've ever read. I don't use Haskell very often, but after carefully reading this book, I'm now able to easily use functional code in my Python and CoffeeScript/JavaScript when I need to do so.
The online version is free, but I bought the book. It's worth it.
you're out of your skull if you really think that Haskell has a shot in this market. Node.js is popular because it's easy to learn. Haskell fails there. That's probably the most important factor for web frameworks. Remember the total fucking trainwreck that is Rails, and how popular that was (and still is)?
Technologies don't become popular on technical merits alone. Haskell fails at psychology.
I never said Haskell would become popular, I said it was the better alternative. I don't expect every web developer to drop what they're doing and pick up Haskell--but I do expect some of the best ones to do so :P. I honestly don't care that much about what most people are using anyhow.
You really shouldn't choose your technology just based on popularity. Sure, it's a metric. But I don't even think it's an important metric. So next time you start a company, think Haskell and ignore the peer pressure to choose something common :).
To me, popularity is not really a goal in and of itself. As long as something is the best to use, I'll use it even if it's not terribly widespread. Sure, popularity is nice and brings some benefits, but I'm never bound by it. After all, I use Linux too!
I don't think Haskell will ever enjoy wide-spread adoption (although I wish it would happen). Haskell really does have the best constructs for parallelism. You have sparks, which can map to Haskell threads, which can map to OS threads. Using an evented system would be similar to using Haskell threads except Haskell can utilize more than one CPU core.
"You lose expressiveness, you lose maintainability, you lose peace of mind"
Really, you found all that out after your experience...wait, what experience? You said yourself you failed to build a single simple app. So it seems to me you can only comment on expressiveness.
I'd love to read your review of, say, Haskell next. I have a feeling if you applied the same (lack of) rigor you demonstrated here, it would be double extra terrible. The point being, there's no substance here, but it confirms people's negative feelings about JavaScript, so they'll upvote it.
It's pretty easy to find alternatives to Node.js that are a lot more sound, a lot easier to work with, and a lot more performant if you need asynchronicity. You gain nothing save for the ability to use JS itself, for which the supposed benefits of sharing code are a total wash.
Node.js is async for people who don't actually know what they're doing, but are still willing to push an unnecessary boulder up the hill for the sake of a familiar language instead of learning how the industry's been handling async for the last few decades.
Node.js users "lack rigor", not this guy for questioning the ridiculousness of it all.
Go look at SFS/sfslite and its ilk to see how async is supposed to be done.
Actually, it's more like, "Write your web apps in Python/Clojure/Go/Java/Scala/Haskell/Erlang/C++/C/Common Lisp/Racket which all have better concurrency and async mechanisms than Node.js"
I was mentioning SFS/sfslite more as exemplars of clean ways to abstract asynchronicity than recommending C++ for web app development.
But you don't learn something like that if you don't learn to code without jQuery and npm packages.
> Node.js is async for people who don't actually know what they're doing
"Node.js is rubbish and if you like it and try to argue otherwise then, as I've already said, you don't know what you're doing so I can just ignore you."
You lose expressiveness, you lose maintainability, you lose peace of mind, and you get speed.
- I don't think my JS/CoffeeScript code is (significantly) less or more expressive and maintainable than the Python code I would have written. Use coffee if you want a whole bunch of language features, including some missing in Python. Oh, and a much cleaner way to write lambdas.
- Yes you need to understand async. It is of course, increasingly relevant with services and devices talking to each other. For example, in Microsoft's WinRT anything taking more than 50ms has to be async by design. After a while you might even wonder why async isn't the default way of doing most I/O.
- Flow control is hard in async, especially when you are getting started. But there are libraries which help, such as
https://github.com/caolan/async.
- The library approach works for me and is a safer bet, but isn't the cleanest. If you are adventurous you could try iced-coffeescript, which introduces keywords to give you simpler code.
- Finally, you need to have a really good grip on JS.
Those wanting to succeed with node.js should listen more closely to the parent post. IcedCoffeeScript promises, "Say goodbye to callback pyramids; say adios to massive code rewrites when synchronization requirements change slightly. Say hello to clean, readable, maintainable control flow for network and asynchronous operations!" (http://maxtaco.github.com/coffee-script/)
Personally though, I haven't yet tried/loadtested it, so can't speak to its effectiveness.
In any case, simply using plain CoffeeScript + async + underscore, will greatly cut down on node.js's complexity. Sure, you still have some async callbacks when doing I/O like calling some service, but it's much less awful.
Node has many advantages that make it really nice - V8 is awesome because of an interesting case of technological path dependence; the standard library has a lot of modules that take great advantage of asynchronous I/O; the standard library is very high quality; the community is great - but I think the two issues above really leave room for another project to take the good parts and not the bad ones, and steal Node's thunder. It could be Go or Python (with some badly needed extra work on coroutines, concurrency, performance/adoption of pypy, etc), or something new.
I write applications professionally in Python, Javascript, and Java. While there is some overlap, I find each platform to have merit.
* I like Java for projects that I know are going to become big and complicated. When you have thousands of classes and multiple people working in a codebase, static typing is a godsend. I don't care if it involves a little more typing. As an added bonus, the JVM performs great.
* I like Node.js for small projects, especially ones with large concurrency needs. I recently did a project that involved being able to aggregate repeated barrages of several thousand requests with a finite deadline of a couple seconds. Node.js handled twice the throughput of Twisted or Tornado, and was considerably more stable. Gevent and coroutines would have been even slower.
* I like Python for stuff "in between". Rich libraries, blocking i/o, exceptions, and proper stacktraces. Even has halfway-decent IDE support (PyDev). Execution is slow by JVM standards but Python makes a great swiss army knife.
There's no perfect platform for all situations. Use the right tool for the right job - sometimes that's Node.js. There's a lot of overlap with Python, but not as much as you seem to think.
I had the same experiences as you did because of jumping on the bandwagon. Hasen, when you opined "Node.js is a terrible platform", I thought you would also say something about the bad decisions we make because of it. This is how I made mine:
Day 1: Let's Node.js because everyone is doing it. In that context, no-sql databases gel very well with it, so let's do that.
Day 3: Whoaa! Prototype is already done. Great
Day 4: My databases entities are so thin, sql databases are so overrated. I don't need sql.
Day 6: Uh-Oh, I did not think of that database entity. Oh no, look, it has a relationship too.
Day 7: Frack, the no-sql CRUD operations code is damn mess.
Day 8: More relationships! "If I only had used sql". Sighs. Oh wait, look a node.js-mysql library. (Code Hustle). No no, it is still a mess. Well, it is still working so let's have a little patience.
Day 15: Why my code looks like a puke?
Day 20: Ok, I/O code is now like 7-8% of my complete project. Why did I go for Node.js again? This doesn't make sense. I am going on a vacation.
Day 27: First thing back from vacation, farewell Node.js. Let's go for Flask(python) + SqlAlchemy(oh I missed you so much) + Gunicorn + Gevent + Juggernaut(for websocket.Node.js, you found your rightful place).
I think the reason for such hype around Node.js is due to the rise of a new class of startups which are born with a "fail-fast" mentality. Node.js does help you to fail fast. But I think that it is a pessimistic view of idea and software development. Agreed that node.js removes the initial inertia to implement an idea, but I think that this is it's greatest failure. A little inertia can be good. It forces you to sit down and think hard about the architecture and the idea itself. It's same as a small group of lean mean soldiers can extract a defended fort from the enemy, but holding the fort would take a lot of strategic thinking, resources and more soldiers. I think it's time to get a bit optimistic about our own ability to do that. Well, unless, you never wanted to hold the fort. In that case, everything is just fine.
I've seen many people and organizations run into problems like you describe. I don't mean to come off as insulting to you, but the only reason I can see a path like that being taken is out of complete ignorance.
At the beginning of your project, how did you ever think that it'd be a good idea to use JavaScript, Node.js and NoSQL? Yes, there may be a lot of hype around them, but after a brief analysis of them it's clear they're inferior to most other options that are already available.
I can completely understand JavaScript being used for browser-based scripting, where it's basically the only practical option. But why would anyone ever consider it for server-side development, given that so many better options are available?
The same goes for Node.js. Reading a brief introduction to it only serves to make Erlang and Go, among other options, look far more appealing.
And again, the same goes for NoSQL. Cursory investigation reveals that anything that can be done with a typical NoSQL database can be done with any capable relational DBMS, plus you at least get the option of using proper SQL queries if necessary.
So how can a month (or much longer, in some cases I've seen) be wasted on obviously-inferior technologies? Was it really not obvious at the very beginning that the outcome would be disastrous?
The project started out as a minor one, but after a few successes it kind of snowballed. If I didn't had those earlier successes, I would have introspected about my decisions earlier. Unfortunately I got fooled into thinking otherwise. These small successes turned out to be red herrings. Also, it's hard not to give into mass hysteria and perhaps I wanted to taste the impracticability for myself. Thus, despite reading all about node.js, nosql and their horrors, I got greedy.
Japanese is a terrible language. I tried speaking it for a while, but I can just get my ideas across so much more easily in English. It's just easier. This must be because Japanese is terrible.
That seems to be the basic reasoning at work here.
And btw, I actually love the Japanese language, I find it more poetic and actually more expressive too, because you can nest expressions more easily than in English or even Arabic (my native language).
Then I don't know what was, because your point certainly seemed to be that you used Node and had a harder time reading and writing code with it than an environment that was more familiar to you, and therefore Node is terrible.
This post shows exactly why "just use code to get things done" can be taken too far and why a solid theoretical background can be essential to growing as a programmer. The author bravely admits, "The async-style of programming is almost entirely inaccessible to my brain." There comes a point on the road to being a great coder where you can no longer really approach it as a craft; the theory and philosophy start to matter. A common plateau is the point where it becomes necessary to see the commonality between essentially the same computation being driven by different control approaches. I've seen many a competent procedural programmer be unable to write their first GUI app because they can't adjust to an event driven model or unable to make the most of SQL because of its semi-declarative nature. Coders need to see such mind expansion as an essential and fun part of the job.
I've been using NodeJS in production for a few years, and I'd agree that is probably not the best way to write an application with many layers of business logic.
That said, it's wonderful for networking, child process management and handling subscription connections (via Socket.IO, etc).
Effective evented programming does have a radically different style, and many times it boils down to tastefully drawing the line between when to bind and trigger events vs when to pass functions as arguments.
What bothered me is that I couldn't find a way to find out what code had triggered an event, or what listener was attached where. So, suddenly you're getting an error in code and you can't figure out why it's even being called, because it was attached from one of eight libraries that you picked up as to not reinvent the wheel.
...and grep emit isn't an effective solution. :)
I put a question up at SO and never received a response. http://stackoverflow.com/questions/12215273/how-are-event-tr... -- the problem itself I finally worked through, but then I ran into another. And another. And while I know my fair share of JS, and have no problem with async programming, node.js still felt awkward after a month. So long as I was in my own code, I was fine, but reasoning about code I hadn't written was painful not because of the language, but because of the flow it took.
Your question doesn't provide enough details for anyone to offer any insight, unless they've seen this exact error before.
From the error, I'd guess that you were trying to insert an email into an integer field. Check the db code in the event handlers, add some debugger calls (you can even step through code using node-inspector), done. There aren't magical solutions to application-specific errors.
Well, that's why I was asking for the general case. I couldn't find where the event was being emitted. It was somewhere in the passport code that called my code that implemented an authentication strategy, and it was calling with the email rather than the id.
And I was trying to figure out where the code was coming from in passport. The only tool for that was "grep emit". That's ridiculous.
The problem went a level deeper, but that's irrelevant to the task at hand -- I was overriding the prototype (as per the passport example) and yet my code wasn't being called, and there was some order of execution issue going on with how the initialization was interacting with express, which is when I decided to scrap the code and rethink the implementation.
And for multiple reasons, I'm rethinking that implementation in Scala instead. :)
> I'd agree that is probably not the best way to write an application with many layers of business logic.
Exactly!
Which, to me, means that it doesn't scale well. (Scaling here refers to growing the size and complexity of the program - as opposed to handling an increasing number of concurrent connections).
And, given this point, why should anyone use it as a platform to build their product on?
Just today I devised a pretty solid method to build a fairly complex node.js app while keeping it simple, maintainable and scalable.
I like the way node kind of enforces modularity, but for something as complex as the backend (super-flexible api for a frontend dbms) required for my project, it would save a lot of time/effort/ugliness-of-code to have a few objects on the global scope while allowing individual parts to be split up into their own files; e.g., a few utility functions, String/Array.prototype functions, a socket.io instance, and a redis client instance, among other things.
And to make things manageable and more extensible all while minimizing duplicate code, I ended up using John Resig's "Simple Javascript Inheritance": http://ejohn.org/blog/simple-javascript-inheritance/. I like being able to simply call Class.extend({}) to create/extend any class with access to its "super" functions. Each class is contained within its own file, of course.
The method is pretty simple:
1) Organize and order the files like you would on a client (web browser) where "global" variables are allowed.
2) Use some program to concatenate the files in the correct order into a single node app.js file for testing or production.
I'm currently using a batch script (yes, I use Windows :P) that looks something like this:
del app.js
type global.js >> app.js
type appBegin.js >> app.js
type loggur.js >> app.js
type classes\Class.js >> app.js
type classes\Client.js >> app.js
type get.js >> app.js
type post.js >> app.js
type set.js >> app.js
type socketsOn.js >> app.js
type appEnd.js >> app.js
Don't get me wrong, node's module system is used when it makes the most sense. But for what I need to do, this works perfectly. It doesn't promote spaghetti code the least bit; everything is easy to read and follow (could even call the code pretty!); it's 100% clear which objects are shared (especially since most files contain a single object or class); and as long as the method is used consistently, you get all the benefits of node/socket.io while maintaining cleanliness and scalability.
Global objects are not as much a sin as in the browser, since the environment is usually completely under your control. And of course, you wouldn't use more than a couple.
Node is not for everybody. Node is not for everything.
2 hasenj: try using coffeescript to get expressiveness if you're coming from Python(like I do). You'll be much more comfortable with it. Especially when you're using it for both frontend and backend.
Node was a "why not?" choice for my last small inhouse realtime analytics. I could write it in python, but I've been writing LOTS of CoffeeScript recently so I've tried to go with node and redis. And it was a perfect fit for this task.
I'm pretty sure I wont use it for some complex business logic or number crunching. But that's not because I'm afraid to loose maintainability or peace of mind. It's because that would be just stupid, there is a lot of better tools for this. You should keep in mind whats your platform nature, whats it good for.
Every contending platform or language has it tradeoffs. I like ErlangVM features and philosophy, but I can't pass over the language weirdness. And VM speed sucks. And the community is much smaller. Nodejs is booming, you should agree on that.
Go is great, I'm planning to use it for my next "why not?" project. But it takes a lot of things you love in dynamic languages away. You choose between "program performance vs programmer performance". And again, the community and adoption is taking its first babysteps.
Looks like the author got upset that he needed to learn a platform in order to use it.
Another issue is that JavaScript doesn't really lend itself to continuation passing style, leading to ugly nested callbacks. There are many libraries that make this more manageable, like async: https://github.com/caolan/async
I'm upset because I invested a substantial amount of time without really reaping much of a reward (other than knowing to avoid it). I'm upset because there's a lot of unreasonable hype.
So because you were unable to figure it out, no one else will ever have success with it?
> unreasonable hype
Welcome to the real world. Not everything that deserves accolades gets them. The things that are successful- they don't necessarily deserve it. Just look at top-40 music.
So anyway, your post is against the attention the framework has gotten, not the framework itself?
It was hyped here in HN, a community which should (in theory) have a very strong BS filter. So it's very natural that most people here would think that this hype is perfectly reasonable.
If it was hyped by some corporate giant like Oracle or Microsoft, I would probably scorn at it from the start.
I find that stretching my head around a new and different paradigm is it's own reward. Everyone's different and has different goals.
If your goal is to implement dynamic web content as productively as possible, no one will fault you for sticking with what you already know and are comfortable with. But it's not valid to conclude that everything else is terrible if it doesn't improve the type of things that you do.
Personally, I've lost count of the number of times I'd wished a blocking API call was instead non-blocking. Do a survey of how many desktop Windows applications are able to exit gracefully while a File->Open dialog box is still open.
Stretching my head around functional programming was rewarding. Stretching my head around lisp was rewarding. Stretching my heard around continuation[1] passing style was rewarding.
Stretching my head around everything-is-async was not rewarding. Just because it's different, doesn't mean it's good.
I agree that FP, Lisp, and CPS are rewarding. I find async IO very appealing because so very often I've had to implement imperfect workarounds when it wasn't available.
But I still feel really conflicted about Javascript.
I encountered the same issue. I found the callback oriented programming style to be confusing and overly complex for the sake of a fast application. Although I managed to build something and still work with it, the uses for Node.JS are quite limited.
Want to build a realtime analytics platform? Node has you covered. Want to build a super lean and powerful server for an iPhone game? Node also has you covered. Want to build a web application that doesn't require anything realtime? Not so much.
Node serves a purpose for a lot of things, anything that requires a lot of connections and continuous streams of data it is a perfect fit, but nothing much else.
As for the Python remarks and websockets, I find Beaconpush does the job well: http://beaconpush.com/ - the server that drives Battlelog on Electronic Art's game Battlefield 3 is a python framework with websocket support, I believe it uses Beaconpush.
Another "mommy I quit because it's too hard for me" post. Why is that tolerated? He doesn't even present an interesting perspective on the technology. "I cannot build cool things with Lego, so Lego is terrible". Yeah awesome.
"I wasted a lot of time trying to learn node and do something useful with it (other than a dumb file server), but couldn’t. I just didn’t really know where to begin...The APIs might have been documented, but it wasn’t clear how to piece things together to make something useful."
I haven't had this problem myself. To me, piecing together different libraries in Node feels much the same as it does in any other language. You find the libraries via Google, you learn the APIs, and you write glue code to hook them in to your business logic. I'm not sure what would make Node at all different in this respect.
"The async-style of programming is almost entirely inaccessible to my brain."
I'm guessing you're referring to the mess of ultra-deep, nested callbacks that plagues many Node apps. If you just keep nesting callback after callback, then yes, your code will be ugly and unmaintainable. But there are solutions to this. Look into control flow libraries like Step.
"So what exactly is your excuse for choosing Node.JS as your backend platform?"
Here's my main reason. When building for the web, Node can sometimes be far more maintainable than many other platforms. That's because you can share code between client and server. Admittedly, the community hasn't yet settled on a best practice for implementing client-server code sharing. But folks have found ways to do it that work, and you can just pick one that feels good. Sharing code is a big maintainability improvement if you have a thick client that knows a lot about business logic.
Whenever I read something like this I always just tack on 'for me' to the end of the title. The article makes a lot more sense if you read it with this perspective. I always did the same thing when a developer would tell me something was too hard to do.
Right, you think that Node.js is a terrible platform for you. I'm pretty sure that everyone here would agree with that statement. You really can't make any more general of a statement than that though given your limited experience.
I actually would advice that it's bad in general, not just for me.
If node.js works for you, then I'd argue that Go would work even better for you.
If you don't mind losing some of the expressiveness of python/ruby, then surely you wouldn't mind transitioning from python/ruby to Go. And, what's more, Go is much better suited for large and complex programs than Node.js.
The async nature of the language and platform is very easily managed with libs like https://github.com/caolan/async, I came from Django and to me, once I mastered the async nature and understood it, nodejs was a breath of fresh air.
I have been doing async-style programming for a while and still consider it terrible. I had to do it because at the time there were no better alternatives given my constraints. I could have told you then it was a bloody mess when evaluating it and I can tell you the same now. In other words it seems "accessible to brain" and a "better platform" can be independent.
I've never jumped on the Node bandwagon either, because I detest Javascript, but...Shouldn't async-style programming be fairly familiar to Javascript developers? At least those who have ever made an AJAX app?
It seems like it was a paradigm shift for the author, but I wonder if it actually is for most people who Node is primarily targeted towards: those who like and regularly use Javascript.
On the client you have callbacks every time an object has an event handler. It's not just AJAX. And yes, anyone familiar with client side JS should understand and be using callbacks everywhere.
It's not that async is hard, it's that callback-based frameworks like node.js force the programmer to structure their code in an entirely different (and more verbose!) way to what they would writing synchronous code. It doesn't help that the shortest way of declaring a function in Javascript is function(){...};
Look at coroutine-based frameworks like gevent if you want to see what easy async looks like. You'll still have to remember you're writing async code, but instead of do_lots_of_io(function(){wrap_up_afterwards();}); you can just do_lots_of_io();wrap_up_afterwards();. It makes code infinitely more readable.
Async event-driven programming is not going away, it's probably always going to be the most performant model because incoming packets translate into interrupts and kernel mode and thread context switches are expensive.
Javascript is not going away, and has become shockingly efficient with V8.
These are both forces of nature in their own respective domains. So somebody's gonna combine them to implement an async IO reactor system in Javascript. This is Node.js, which looks to me like a pretty decent implementation of the idea.
It may not be your cuppa tea, or the best way to implement every dynamic website. It just is what it is: inevitable.
> Async event-driven programming is not going away,
I just made it go away -- started using gevent. You can make it go away also by using an actor based language like Erlang.
If we were in the 90s you'd probably would have said C++ is not going away so that's what all web services should be written in.
> thread context switches are expensive.
Green thread context switches are pretty cheap and Erlang's processes are very light weight. I was running with 100K processes at one point all with long polling (comet style) connections. That's very cheap.
> It just is what it is: inevitable.
Yap but that wasn't his argument. I don't see (even in general) how inevitability of something turns that something into a good thing.
If we were in the 90s you'd probably would have said C++ is not going away so that's what all web services should be written in.
Actually, I work on some C++ web services today (but I wouldn't advise everyone do that :-)
Erlang's processes are very light weight
Yeah, Erlang is great that way.
I don't see (even in general) how inevitability of something turns that something into a good thing.
In this case it's inevitable precisely because there are application domains where the use of V8 Javascript is a big advantage (say you want to leverage the same code base on the client side). There are other domains where the use of the single-thread async model is a big win, particularly when a runtime environment can support you by eliminating inadvertently-blocking calls. These domains were overlapping for some capable implementers, so I think Node.js was inevitable for that reason.
That doesn't mean it's a terrible system if it doesn't turn out to be a great replacement for your favorite PHP framework.
> Async event-driven programming is not going away, it's probably always going to be the most performant model because incoming packets translate into interrupts and kernel mode and thread context switches are expensive.
That's like saying "assembly isn't going away, because it's the language of the CPU". Of course assembly isn't going away, but other than the Kernel and device drivers, there's not much reason to use it else where.
Coroutines are a much better way to write performant network services. In Go, when a goroutine blocks on I/O, it yields execution to other goroutines. You, the programmer, never think about it, because the platform handles it for you.
> Coroutines are a much better way to write performant network services. In Go, when a goroutine blocks on I/O, it yields execution to other goroutines. You, the programmer, never think about it, because the platform handles it for you.
Not only that but, unlike Node.js, Go (and Erlang) actually do scale to multiple CPUs and don't make your whole app crawl to a halt if you got some bit of code somewhere that is CPU bound.
This fantasy that Node.js supposedly scales because it is async is so laughable I don't understand how anyone ever took it seriously.
Of course assembly isn't going away, but other than the Kernel and device drivers, there's not much reason to use it else where.
Assembly largely has gone away. It used to be that all serious PC apps were written in asm. Eventually though, C compilers and RAM improved enough to not require that. Today the only things written in asm tend to the absolute lowest-level system routines and a few hand-tuned loops.
But you might also be interested to know that MS embeds the web server in the kernel using async IO (http.sys) and that the WinHTTP client library runs async as well.
Coroutines are a much better way to write performant network services.
I agree native coroutines or CPS would better. There are better choices of development language than Javascript, too.
But it's not the tool, it's the hand and the attitude that wields the tool that determines the quality of the result.
WebSocket protocol is pretty easily implemented in pure Python; my co-founder and I did this just recently to support some of our game client functionality.
Node.js can be made to be plenty writeable and readable once you wrap your head around asynchronous programming. I'd write everything in my life in an asynchronous way if I could.
Yeah but I've seen several people who tries node dismiss it on the grounds that this programming style is immensly complex and incomprehensible. In this guys words "The async-style of programming is almost entirely inaccessible to my brain".
I just find it contradicting then that every man and his dog seems to be able to whip up some client side Javascript which works in the same way..
Funny, I think Python and JavaScript about even in the amount of syntactic sugar (programming shortcuts) they provide. They both have some little things that the other doesn't have, but overall there is nothing that makes me think python is preferable to JavaScript (except perhaps older and more mature libraries for server side code, don't know about that).
No comment on the callbacks - I suppose you don't have to use them if you don't want to.
Nose.js is a great platform , but not for YOU needs. You don't like Node.js, so you won't like Twisted and Tornado in Python too. The thing you hate is not Node.js, but it is its approach. And the reason is, that it is not designed for YOUR needs. That's all.
It's being hyped as a platform for writing scalable web applications. Not simple networking tools or little glue utilities, but large, complicated web apps that people have been using ruby and python to develop.
from nodejs.org
"Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices."
That doesn't say to me "create large, complicated web apps with this". As a matter of fact, in my personal use node has showed its usefulness most when I am replacing small parts of my app that function slowly or poorly in some other way and moving toward a more modular approach.
to be honest, I think one of the key issues with "javascript" and "fast" in the same sentence. (yeah, this reply would be better beneath you, but HN says I can't reply to that guy.)
The reason why NoeJS is "fast" isn't JS. It's being event-driven.
I also believe JS isn't as easy to work with as python by design, even thus there are zillions of JS coders. Most of the people indeed follow the hype, more than "wait, is this actually something I should use" (you also did follow the hype and got bitten by it, in fact)
To be fair, V8 (the JavaScript engine under Node) is really, really fast. Even without introducing any event-driven code. Normal procedural code will (in general) be an order of magnitude faster than standard Python and Ruby runtimes.
"standard" run-times .. yeah, right. But try PyPy - same perf class as V8. And LuaJIT - probably faster than V8 - apart from GC. And for GC perf: Erlang does parallel (per "green thread") GCing ..
Javascript performance has come a long way since the days of IE6.
Saying that node.js is more difficult to work with than Python is just a matter of perspective isn't it?
Like any technology, in the hands of individuals that know what they are doing it is really not any more difficult than anything else.
For me personally, the fragmented Python community was what scared me to Node.Js in the first place. This was year's ago now, so perhaps Python has gotten better at that, but from a getting started point of view Node.js was and still is pretty easy, at the time the only thing that compared in Python in terms of ease of use was CherryPy, but It was not stable enough at the time for me to feel comfortable staying with Python for the one library that was not production ready.
The entire post was an opinionated piece of crap based on the author's opinion that anything to do with callbacks are evil.
I couldn't help but see in the comments that the author states that avoiding callback hell in node.js is somehow different to using the same javascript design patterns in browser side javascript to avoid callback hell. What's the difference?
The author's problem is he doesn't understand JavaScript, so he never had a chance at properly understanding Node.Js and where it's strengths and weaknesses are let alone how to build something in such a way to ease developer pains associated with learning any new language.
All in all I'm very happy with the stack I've built - I get the performance and low memory usage of Node combined with the ease of development of RingoJS.
I too was interested in Node.js but I don't like the idea of using JavaScript - I simply prefer python for coding. I looked into it, found the counterpart of node.js in python and am happy with it.
People fear and inevitably hate what they can't understand especially when they fail to associate with it while others do so easily. OP should learn java script before learning "Node.JS".
"The async-style of programming is almost entirely inaccessible to my brain. Certainly not a fun way to write programs." does not equals to "a terrible platform"
JavaScript was already painful enough in the browser, why on earth anyone ever thought it was a good idea to use it on the server boggles the mind.
We will be paying the price of this misguided hyped fad for decades to come.
Of all the ways of doing concurrency, callbacks are by far the worst, Twisted was plagued by them and is the main reason why it failed, and that was with a much more sane and reasonable language like Python (stackless Python was a much better alternative and used a model similar to Go's CSP).
And the sad thing is that there are much better alternatives around with much more sound models and environments, Erlang and Go are the two obvious examples, and that is for the highly specialized situations where you have great concurrency needs, for any other problem anything else will be much better than Node.js, even PHP.