29 comments

[ 3.3 ms ] story [ 73.3 ms ] thread
> Use Javascript everywhere

And here I thought the author was trying to simplify their life. Using Javascript on the server is not simplifying your life.

By writing Javascript on the server, they have made it all but impossible to reason about code's execution order and performance - it's going to depend entirely on epoll and the underlying threaded IO implementations. They are also relying on the developer's ability to understand and use continuations properly.

There are some developers who can do this (just as there are some developers who can write threading code without any race conditions), but most others will rely on so many layers of abstraction (which they don't fully understand) that they are hardly writing Javascript anymore.

"In the past year I think I have finally come to understand the ideals of Unix: file descriptors and processes orchestrated with C. It’s a beautiful idea. This is not however what we interact with. The complexity was not contained. Instead I deal with DBus and /usr/lib and Boost and ioctls and SMF and signals and volatile variables and prototypal inheritance and C99FEATURES_ and dpkg and autoconf.

Those of us who build on top of these systems are adding to the complexity. Not only do you have to understand $LD_LIBRARY_PATH to make your system work but now you have to understand $NODE_PATH too - there’s my little addition to the complexity you must now know!"

Your distaste for JavaScript aside, writing your app in a language that can run the same exact code on the server and client is a giant win for companies that have been doing redundant work for years.
I always hear this but I don't buy it.

The client and the server have different jobs to do, how much code re-use is really happening in real world apps?

My guess is that they probably share the models at most, but even so they have different funcionalities on client side and sserver side.
The real benefit of one language everywhere is reduced penalty for context switching and flexibility with your architecture.

The promise of "code reuse" is very alluring but reusing application code rarely happens in reality. However, reuse of patterns and libraries is very common – solve a generic problem once and you don't have to research how to achieve the equivalent in another ecosystem. Just grab the exact same library, browserify the thing and you're done (ideally).

"One language everywhere" grants you lots of flexibility – where your code executes is no longer locked in stone – you can shift responsibilities from the server to client & vice-versa without significant overhead. No need to port to a different language which perhaps lacks similar paradigms or tooling. Doors are opened to optimisations and architectural changes that would not have even been a consideration otherwise.

To get the benefits of "one language everywhere" doesn't necessarily mean "use JavaScript" but it's a safe decision to choose the lowest common denominator; JavaScript is not going out of fashion any time soon, it runs on nearly every platform and has an ecosystem that's competitive in a wide gamut of problems. An investment in vanilla JS will pay out in long term, while any investment in Framework-X or compile-to-js Y or AltJS-Z is high risk and usually only pays out for the 18 months or so while said tool is in vogue.

JS may not be the best choice, but it's a smart choice.

>reuse of patterns and libraries

While this sounds alluring, in practice I think it would mostly be limited to the kind of thing where you check something client-side (like whether a username meets the requirements) and then re-check it server-side because security 101.

Client-side code is about displaying things, turning JSON into buttons and widgets, etc. There is no point having that on server-side. The server does not have a human user clicking buttons and scrolling bars.

Server-side code is about performing calculations and facilitating communication between different clients. If these can be done client-side, then there's no reason to do them server-side in the first place.

>An investment in vanilla JS will pay out in long term

This is true, but a lot of JS investment is not in vanilla, it's in whatever framework is popular that week, and next week that framework will be dropped like bellbottom pants.

> Client-side code is about displaying things

Actually, JS developers are learning that this is frequently better done on the server; there are more and more articles every week about the benefits of pre-rendering the application page on the server side, then letting the client JS take over and make the server generated code responsive.

I believe the term being used is "isomorphic" javascript.

However, since the Node.js server is inherently single threaded, the cost of generating these templates server side impacts every connection being handled by that particular instance.

What JS developers call "pre-rendering" is what everyone else has been calling "not a static webpage" since forever. It takes willful blindness to ride around on a bike with square wheels, ignore the round-wheel bikes around you, then eventually switch to round-wheel yourself and act like you invented it and it's the next big thing.
Well, some of these guys are also riding single-speed fixies over a century after the invention of the derailleur and freewheel. I'm not hip enough to know if (extraordinarily dangerous) penny-farthings are coming back yet.
> you don't have to research how to achieve the equivalent in another ecosystem

is somewhat contradicted by

> browserify the thing and you're done

Browserifying a library might seem conceptually simple, but if it was written with a particular usage in mind, it will really include writing a set of non-trivial shims to make it work with, say, Ajax instead of `fs`.

If, on the other hand, you actually understand the problem at hand and are willing to write code instead of plumbing libraries together, you can frequently express the solution to that problem in remarkably few concise lines of code in any language. This alleviates the need for others to learn both the problem domain and the quirks of the library chosen to address that problem.

Also, having just looks at the article:

> having the same language in client and server can simplify the data management between them

That isn't called "simplified data management" it's called tightly coupled. What backend language/framework doesn't support json, xml (and even html fragments) for working with a JS frontend?

So if the server side stuff was written in node, that is a js framework and still requires a learning curve for developers if they don't already know node. Also you shouldn't choose your server side language/framework based on the fact it's the same as the front-end code. And you still need to have a clear and well documented API for the server side app - just using js isn't going to solve that problem.

If you do solve that problem, in any language, then is implementing it in js really a necessity (apart from maybe a skill issue i.e. do you need people with a mix of skills or just js devs but again, I can't see why this is a problem)?

Except that you're only reducing the complexity of your stack by exactly one syntax. You still will have different semantics for the front and back ends. You still will have a giant wall between the server and the client with the only way of getting stuff over it is throwing it with a really strong arm, i.e. passing it in through HTML or after the fact with AJAX. You still will have to drop down to HTML and CSS, with a template language and perhaps a CSS preprocessor. If you don't think HTML and CSS are both powerful, complex languages in their own right, you haven't made anything truly complex for the web yet. You still have to manage devops, which has its own ecosystem and suite of tools.

Javascript and its prototypical object system is great for client-side scripting code, but a poor fit for server domain concepts. You're going to have to learn multiple tools, languages, paradigms anyway. So just suck it up and use a proper back end framework too. Node's pretty good, but it's not Rails.

(comment deleted)
(comment deleted)
I haven't found languages that let you be lazy (looking at you javascript) to be maintainable long term as a server, especially as a companion to a SPA. The complexity of maintaining a SPA is high enough as is. Having things like stronger typing and more enforced patterns on the server help keep it organized over time, where having looser more flexible patterns always leads to a spaghetti server. With a SPA, you really do need as organized of a server as possible.
Cut 80% of your product’s features

lol

Yes, it's easy to be clear and readable when what you're trying to do is simple. The hard case is keeping the complexity managed in the face of complex demands. The real-world analogy for most software is not JK Rowling but the 60,000 page set of contracts running the privatised London Underground.

The writer doesn't quite make the link I wanted between product and code. Regardless of the number of features, the product should be understandable and then the application design and tests should be able to be clearly mapped to the product features, and is well documented.
Please proofread your articles. Even running it through spell check in Microsoft Word would have caught many of the errors I've found.
April fools is early, huh. Who actually writes "Zen Javascript" in Production? Examples, please.
The only time I feel "zen" writing Javascript is when I'm writing it as much like C as possible, without touching the DOM, without using 3rd party libraries (the API of which invariably ruins any "zen" I've got going on) and certainly without using Node. I don't mind it as a kind of toy language for playing with algorithms in JSFiddle.

Real-world Javascript, in my experience, is a constant struggle to cram a dozen call styles for your various npm-fetched libraries in to something resembling coherence, and god help you if you have to dig in to the code of any of those libs, because there are so many different styles and commonly-used libraries serving the same purpose as one another that it's likely to be like reading a completely different language from what you've been writing.

A dozen competing approaches each for making the language suck less at doing useful things, code organization, call chaining, et c., and every goddamn one of them is present somewhere in your stack.

The language is kind of OK. Zen enough in small, controlled doses, once you know about the usual unintuitive (backwards, broken) stuff like variable scoping. The ecosystem, every place the language touches the browser (not Javascript's fault, really), and Node are ripping-your-hair-out un-Zen, IMO.

> Macro film photo from my Macbook Air’s display

This is why people make fun of us.

I tuned out immediately after reading that caption.

Why does it matter that it's macro film? Why does it matter that it's a Macbook Air? Because the author is all too happy with how tasteful and cool he thinks he is. It shows through in the rest of the article.

I write full stack js, and this guy is making me look bad.

In each, it took me between few weeks to few months to fully understand their code-base, and I have about 6 years of experience with JavaScript. This does not seem reasonable to me at all.

Correct me if I'm wrong, but for entire large codebases, isn't this normal?

The problem is that we still don't have enough developed tools to truly analyze internal/white-box code relationships (or perhaps we do, but they're buried in research circles). Expressive programming languages seem to only go so far. Most IDEs have symbol tables, tree visualization, but those are hardly enough. UML was a failure.

In contrast, our black-box analysis tools, like the various system tracers (DTrace, SystemTap, s/l/ftrace, etc.), debuggers, disassemblers, decompilers and fuzzers, are relatively well advanced.

I don't know if moving to image-based environments would help with this, though that'd be too profound a leap.

Hmm. This is an interesting topic to think about.

Why aren't the tools for analyzing White Boxes as good as those we have for Black Boxes? I would say it's due to the differences in boundaries.

For example, Black Box tools have it simple. Capture anything that crosses in the direction of Black to White. Capturing what goes from White to Black is much harder, though, since there are less visible boundaries on what can be accessed. For example - if I write a black box which utilizes a environment variable, you have to be tracking what memory a program accesses to see this from outside the program.

White boxes, on the other hand, have very few boundaries, and those which exist are fuzzy at best. Sure, there are technically functions and modules and scopes, but these boundaries are soft; frequently and easily pierced. Global variables, shared memory, inlined functions, tail call optimization, continuation passing... all of these make it incredibly difficult to reason about and trace program flow, because the program flow depends so heavily on the global context.

Functionally pure programming paradigms might be our best bet in the long run: when a "function" produces deterministic output for given input, we suddenly create a network of predictable black boxes within our white box, giving us the edges we need in order to implement our tracing and automated reasoning tools.

Correct me if I'm wrong, but for entire large codebases, isn't this normal?

Perfectly normal for large codebases. You can have a low LOC that leverages only well known platforms, libraries and frameworks but you'll get a pretty cookie-cutter product. You can choose to do something technologically novel, but expect to pay for it in LOC.

> Cut 80% of your product’s features

... closes tab

This is either bad satire or bad advice.
An article about writing good code without any code examples.