Live data from Hacker News

Hard-won lessons: Five years with Node.js

blog.scottnonnenberg.com

331–340 of 365 posts

Re: Hard-won lessons: Five years with Node.js

#331
post #305

Earlier quoted context omitted.

> Erlang is great but its ecosystem is tiny compared to Node's, and as a programming language it's at least as quirky as JavaScript. I disagree with this; while the syntax is unusual for many, its semantics are extremely simple and clear. I don't think it has anything quite like: * JavaScript having `null` and `undefined`. * JavaScript lacking have proper integers. * JavaScript strings being UTF-16, so things like ""…

Does it have a non-hacky way of handling record types yet?

It has maps now! This chapter speaks of them being fully supported in future versions, which have since arrived. http://learnyousomeerlang.com/maps

And even records are hardly a quirk like the ones I listed for JavaScript: as long as you remember that they're just syntax around tuples, you're hardly ever surprised by what they do. You'll never get a runtime behavior you didn't expect.

Re: Hard-won lessons: Five years with Node.js

#332

This looks like how I used to work with BASIC back in the 80s: > I finally added extremely verbose logging ... started adding logging ... Verbose logging to the rescue ... I had the right logging in place ... My first step was to jump in and add some key logging statements ... added extremely verbose logging Weird to see people happy to be limited to such stone-age work-flows when fully capable debuggers have existed…

>Weird to see people happy to be limited to such stone-age work-flows when fully capable debuggers have existed for almost all proper languages out there the last 30 years. Even though node has a debugger with breakpoints, etc., an effective programmer will still use logging in situations like the ones in the article. Taking the first example, before he knew that NaNs were causing the problem, setting a breakpoint wo…

I disagree. He simply had to inspect the live DB and see what the state was when someone said the order was wrong.

Re: Hard-won lessons: Five years with Node.js

#333

Earlier quoted context omitted.

I've read the article. Obviously I haven't seen the actual problem, but as an experienced developer, I feel that: NaN bug doesn't sound like it needed logging Mutability bug doesn't sound like it needed logging Dependencies and versions bug doesn't sound like it needed logging The Documentation and versions bug doesn't sound like it needed logging Obviously we're not seeing the whole picture or the whole bug. But tha…

My comment about the NaN bug: https://news.ycombinator.com/item?id=14156595

I disagree with that assessment. Users reported the order was wrong, he simply had to look at those users and their live data to replicate it.

Even in those scenarios, I rarely have to look at live data, reading the code is often enough to identify it or playing around a little bit. The patience to replicate a bug before trying to fix it.

This is the essence that sets apart a good debugger from a bad one. A bad one resorts to littering the code with print/log statements because either they can't replicate the problem or they simply can't run the code in their head.

I'm being unfair, it's not even that, they simply need more experience. When I was younger I remember complaining that exception stacks were utter gobbledigook, utterly useless. Now, I read one and often know exactly what the bug is. I was completely and utterly wrong, impatient and unwilling to admit my ignorance. At the time I thought I was wise and knowing. They're very useful, I simply didn't understand them.

My "simply" from above belies the years of experience I have.

Re: Hard-won lessons: Five years with Node.js

#334
post #316
post #206

Earlier quoted context omitted.

> Then it generates stupidly deep Java structure. It generates enough structure to scale up to reasonable projects. The nesting is a price well worth paying for consistency. Every maven project puts its source in the same structure, with the result that you can jump into any project and know how its build will work and where to find the source. > All of this stuff is verbose and built to be generated by IDEs. It's no…

> It generates enough structure to scale up to reasonable projects. It generates stupidly deep structure because Java requires a stupidly deep structure. > Every maven project puts its source in the same structure, with the result that you can jump into any project and know how its build will work and where to find the source. Rust, Elixir and Erlang achieve this with tooling that is practically trivial to use. Witho…

> It generates stupidly deep structure because Java requires a stupidly deep structure.

All of the depth is useful. The folder structure corresponding to the package structure makes it much easier to find the source for something.

> Being concise is a big factor in clarity.

True when there is large-scale structure that varies for the reader to comprehend. Less important in an inert declarative structure. Again, look to the example you linked.

Re: Hard-won lessons: Five years with Node.js

#335

Earlier quoted context omitted.

The default behavior for Node when there is an uncaught error is to crash the process, killing all requests in flight. Even if you go out of your way to stop this default behavior, errors still likely leave the process in an inconsistent state. Node can't just unwind a few stack frames like synchronous platforms. Do you read JSON from ajax post bodies? Do you access fields in that JSON without sanity checking it? Try…

I for one consider that a feature - it is easy enough to write bad code in JS as it is, so anything that encourages defensive coding and solid unit/functional tests is very appropriate for this particular language. A crash certainly draws attention to a problem much better than an error in a log that no one usually looks at. Yes it's a pain, but you deserve it for writing buggy code and then not catching it in testin…

That crash, in your high-concurrency environment, produced "bad gateway" responses or closed connections for your users. I'm pretty sure they don't consider this a feature.

Re: Hard-won lessons: Five years with Node.js

#336

Earlier quoted context omitted.

The default behavior for Node when there is an uncaught error is to crash the process, killing all requests in flight. Even if you go out of your way to stop this default behavior, errors still likely leave the process in an inconsistent state. Node can't just unwind a few stack frames like synchronous platforms. Do you read JSON from ajax post bodies? Do you access fields in that JSON without sanity checking it? Try…

The default error middleware built into my framework caught it and responded with a 502.

...and almost certainly left a bunch of dangling state in your app that, at best, is a memory leak.

Re: Hard-won lessons: Five years with Node.js

#337

Earlier quoted context omitted.

This is really simple. Do you use V8 to compile your code or to run it? Just because V8 has a compiler, doesn't make it a compiler. Do you see the difference?

V8 compiles code into bytecode and runs that. This is really simple. V8 is a JIT compiler. It both compiles code and runs it. For your original complaint about not being able to compile JS up front, you're talking about Ahead-Of-Time (AOT) compilation. You don't seem very familiar with the relevant terminology. In fact, I just looked it up and apparently V8 compiles JS directly to machine code rather than bytecode: h…

V8 compiles to native code with the exception of low memory devices (512M or less), for which it has a (relatively recently introduced) bytecode compiler, so it uses an interpreter in that one case.

Re: Hard-won lessons: Five years with Node.js

#338

Earlier quoted context omitted.

Syntax errors will be detected prior to runtime because the application will not be able to be compiled into whatever format it compiles down to (raw ASM, some IR, etc.). A fully AOT compiler will generally check more than a JIT compiler, but there is still compilation and it is still a "compiler" in a technical sense. And for the record, AOT languages also have "runtimes" provided by a platform. If someone combined…

It is my understanding that V8 provides you with the capability to interpret your code and run it, while gcc produces a resulting binary which be run independently of gcc. Can V8 be used to compile js to a artifact/binary which can later be executed independently of V8? If no, then it's not a compiler. It's as simple as that.

There is no interpretation involved; V8 has an unoptimized base compiler for compiling JS to machine code one function at a time, and a pair of optimizing compilers that work based on runtime profiling. V8 also has a bytecode interpreter for low memory devices, but it'd mainly be used on very low end mobile devices.

Re: Hard-won lessons: Five years with Node.js

#339
post #203

Earlier quoted context omitted.

You know what isn't as quick? Websockets, non-trivial asynchronous code, boilerplate, and build times. The vast majority of my company is built on Java and we're not encumbered by legacy code, so we get to play with all the new stuff. I don't need to be convinced that Java (or even more specifically the JVM) is a good choice for many practical reasons. I live in IntelliJ and Gradle (and Maven too) all day, you're pre…

I agree that Java's async support is bad (haven't had to use it much since I've been primarily Scala for years now), but I'm surprised a PoC would need to be async in the first place? Conventional one-thread-per-request is fine for non-prod, no?

I'm surprised that you consider it controversial that a highly dynamic language can be considered fast to PoC something in than Java. There is just less typing/code that needs to be defined (I know IDEs help). Also easier to do quick and dirty stuff that I imagine would be more restricted in Java. No classes to define, just throw your values in there.

I prefer python in general but for zero-to-simple-web-endpoint I may pick Node.

Re: Hard-won lessons: Five years with Node.js

#340
post #305

Earlier quoted context omitted.

Does it have a non-hacky way of handling record types yet?

It has maps now! This chapter speaks of them being fully supported in future versions, which have since arrived. http://learnyousomeerlang.com/maps And even records are hardly a quirk like the ones I listed for JavaScript: as long as you remember that they're just syntax around tuples, you're hardly ever surprised by what they do. You'll never get a runtime behavior you didn't expect.

That is definitely an improvement, although the document you linked to suggests that the old-style records would still be used for some purposes. If the language already has tuples there's really no reason why it shouldn't just have tuples with a fixed set of named fields.

The quirks of JavaScript that you mention never bother me at all in practice (and yes, bringing up 'with' is a very cheap shot, and Erlang's string handling is pretty wacky too), but I remember that not having real record types was a serious pain point.

Post reply on HN