
Ryan Dahl addresses comments on his recent rant - collypops
https://plus.google.com/115094562986465477143/posts/VZJbdwwfiAD
======
antirez
I agreed with the general ideas in its original rant, but IMHO the problem is
not the POSIX API nor the C language (including "volatile"), those are both
well designed and simple stuff, for the most part (the C standard library is
horrid unfortunately).

IMHO most of the problems are about the other layers: tricks you need to know
about the operating system _implementation_ of POSIX, or dynamic library
loading, all the subtle things with different binaries formats, and so forth.

A few of this things are easy to solve, for me it is impossible to understand
how the libC can be in this sad state, and how the replacements and
improvements to it like glib are also a mess. If one day I'll not hack on
Redis anymore my mission will be, assuming I'll have another way to pay my
bills, to create a replacement for the C standard library.

While we are at it, not C++ nor Objective C are the final words on making C
better and more comfortable to use (but I think the latter is much better than
the former at it). This is surely an area where there is a lot to do.
Unfortunately "D" is diverging so much form C that it should completely
replacing it to get mainstream: very unlikely given the role C is playing
today and the code base. A backward compatible improvement is still what we
need I think.

~~~
kmm
What is so bad about the C standard library? What would you change?

I find it lacking a lot of essential features -- can you believe strdup isn't
part of the C standard? -- but simplicity and minimalism has always been C's
strongest point.

~~~
zeugma
Lack of real string type. String manipulation is a pain and you have to
allocate everything by yourself which result in inefficient and dangerous
code.

~~~
kmm
Shouldn't string manipulation be more efficient if you have to everything by
hand? Besides, using a recursive memory allocator takes away most of the pain
and it's more efficient than a garbage collector.

~~~
barrkel
It's quite easy to overuse strlen or strcat or otherwise turn an O(n)
algorithm into O(n^2). But the efficiency I'd be more concerned with is
programmer efficiency finding and fixing security bugs caused by off-by-one
buffer lengths and input length checking, and the like (e.g. copying k
characters into a char buf[k]).

------
cageface
_Can you not imagine a world where one could operate in native code without
the concept of volatile variables?_

Sometimes you want the compiler to do its best with register optimizations and
code ordering etc and sometimes you have to explicitly tell it to go to memory
every time. You could layer an abstraction over this but some people would
still need to burrow under it. The point of working at the C/C++ systems layer
is you have this control but also the responsibility that comes with it.

~~~
rapala
Or maybe he is hoping for something more elegant than plain shared memory, at
the hardware level.

~~~
bad_user
There are 3 problems with this statement that I can see.

1) people haven't even agreed on the best technique for utilizing multiple
cores, or heck, on the difference between concurrency and parallelism, and
quite the contrary, I think the x86 architecture is too smart and carries a
lot of baggage compared to the elegance and simplicity of pure RISC processors

2) most of the time you're not really working directly with hardware -- like,
for example modern kernels do not allow you to access the memory of another
process directly, and that value that you wanted to save in RAM may end up in
a swap file on your hard-disk.

3) what hardware does have is a separation between hard-disk, RAM, L2 cache,
L1 cache and CPU registers. In a perfect world there would only be one type of
memory, unfortunately that would be too expensive and without much benefit
versus the current state of the art.

For maximum performance (which is required in many instances) you do have to
know about the difference between these multiple layers of memory and take
appropriate action, even though many times this is abstracted away from you.

The problem with "volatile" is different in nature - the behavior of volatile
is not really portable and in practice it is also useless as higher-level
APIs, like POSIX threads, do have better atomic and fence semantics that are
more portable. Basically "volatile" was added in for good measure and it is
now a legacy generating lots of problems.

~~~
cageface
Volatile is useful in implementing things like lock-free queues, at least on
X86. For some real-time applications you can't afford to take a kernel lock or
spin on a spinlock.

------
skrebbel
His first point here really hit home for me. Indeed, people like Ryan Dahl
hate software for us so we don't have to.

------
sodiumphosphate
"""We should program as if we were perched atop of 20 floors of bamboo
scaffolding - because that's the state of the Unix userland."""

Genius.

------
rphlx
POSIX is beautiful. d-bus != POSIX.

~~~
slaughterhaus
why does he keep mentioning dbus and glib? I havent been following node.js
development and last time i checked in, node was written in c++.

------
MostAwesomeDude
I wonder if perhaps he doesn't realize that Ted Dziuba is not a fan of Twisted
either. He's generally recognized as a very belligerent, assertive
personality, in the same vein as Zed Shaw, and you have to have a certain
amount of thick skin when reading his commentary.

That said, the fact that Node doesn't provide the tools necessary to defer
blocking JS code to a thread does pose a problem for these sorts of
situations. Apparently (and correct me if I'm wrong; I'm not a Node expert!)
Node won't let you run JS in any thread which is not the main thread. Twisted
_does_ let you run Python in non-main threads with the
deferToThread()/callFromThread()[1] functionality.

I also agree with him about JS being a poor language for server-side work, but
that's because I don't think JS's object model is well-suited to large,
interface-driven/service-driven applications, and that isn't really a gripe
with Node.

[1]
[http://twistedmatrix.com/documents/current/api/twisted.inter...](http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorThreads.html)
and
[http://twistedmatrix.com/documents/current/api/twisted.inter...](http://twistedmatrix.com/documents/current/api/twisted.internet.threads.html)
document threading in Twisted.

~~~
ehsanu1
What's wrong with JS's object model? It's certainly more flexible than say
Java's. If the problem is the flexibility, do you feel the same way about
Ruby?

~~~
glyph
There's plenty not to like about JavaScript, but the biggest mess is this:

js> x = 1 1 js> z = x.y js> // WTF??

In other words: it's not an error to access an attribute of an object which
isn't there. It's dicey enough that you can have attributes in Python and Ruby
that can be misspelled, and mismatch their declarations, without an immediate
compiler error. But, that is reasonable to deal with as long as you have
pretty good unit test coverage: after all, if you run the code that is
actually accessing the attribute, you'll quickly see that there's a run-time
error and fix it:

irb(main):001:0> x = 1 => 1 irb(main):002:0> z = x.y NoMethodError: undefined
method `y' for 1:Fixnum from (irb):2

~or~

>>> x = 1 >>> z = x.y Traceback (most recent call last): File "<stdin>", line
1, in <module> AttributeError: 'int' object has no attribute 'y'

... and you need unit test coverage _anyway_ , because the compiler can't save
you from a huge variety of other violations, so it's not like this is really
making much extra work for you.

In JavaScript, by the time you actually encounter an error, it's too late to
figure out where the heck the erroneous object is getting generated. So, if
you have some code like 'this.observers.push(object.somefunc);', every test
case which adds an observer must also verify what happens when the observer
gets called: and it has to be _the same test_ so you have some idea where the
observer came from, whereas you can easily make those things different tests
in Python.

Then, in order to get reasonable error-reporting behavior from quick things
which aren't tested, you have to have tons of manual type-checks anywhere that
objects are put into a persistent container, because by the time you have some
random 'undefined' in your list of observers, it's far too late to figure out
how it got there.

This type of paranoid defensive programming is a bad idea in Python and Ruby,
because you can just let the language runtime do its job and inform you if
there's an error, and your stacktraces will give you a good idea where it is.

The fact that sometimes unknown things are 'undefined' and sometimes they're
'null' and sometimes they're '"undefined"' and sometimes they're the empty
string and sometimes they're 0 really compounds this problem. Python has None,
Ruby has nil, and nobody uses random ad-hoc sentinel values because why would
you do that?

The thing that just blows my mind is that the designers of JavaScript must
have _known_ that this was a terrible idea, because:

js> undefined.undefined typein:1: TypeError: undefined has no properties js>
null.nothing typein:2: TypeError: null has no properties

so when you are _two_ steps out from the misspelling that caused your error,
you can figure out that something has in fact gone wrong. And:

js> blub typein:3: ReferenceError: blub is not defined

since the assumption that everything you _really_ care about in JavaScript is
going to be a global variable, and prototype attributes are kind of an
afterthought. After all, why would you store data in organized structures when
you can just stuff it all into an undifferentiated bag of crap in the global
namespace! It's all going to go away when you reload the page, right?

Except then Node comes along and changes the equation so you actually have to
live with your persistent data structures and you probably want to know when
things go wrong in your long-running servers. Oops.

Here I really have to agree with Ted: despite the fact that there are
advantages to be had from keeping your client and your server in the same
language and leveraging your investment in utility libraries in both places,
JavaScript really is bad enough language that it's worth the effort to use
something different when you can.

