HNHacker News
TopNewBestAskShowJobs

ericelliott

337 karma · joined November 1, 2014

submissionscomments
ericelliott··on Must-See JavaScript Dev Tools
The JS ecosystem has largely embraced small modules and microarchitectures over monolithic code, which pretty well sidesteps the need for cross-project refactoring tools that are popular with Java and C++.

If you have a refactoring problem, I suspect it's a symptom of a monolithic architecture problem. Solve that, instead. =)

ericelliott··on Must-See JavaScript Dev Tools
No, that's not why, but thanks for the complement. =)

I gave a talk at the O'Reilly Fluent conference a while back discussing lots of the developer tooling that was available for JS a couple years ago. I wanted to gauge general awareness of the tools, so I conducted some informal audience hand-raise surveys.

I was shocked at the number of people at a JavaScript conference that weren't aware of the great JavaScript tools that I took for granted. That's why I wrote the article.

I think there's a lot of value in a general ecosystem overview. What kinds of tools are there, what are the tools like? Are there interesting future trends to make note of?

I think raising awareness of the overall ecosystem is valuable.

The only reason I even mentioned rtype and rfx is because I'm not satisfied with the type tooling available for JavaScript right now. Flow and TypeScript are supersets of JS, so to really embrace those, you have to step away from the standard - something I'm not willing to do at that level.

JSDoc is not live code at all, and it easily falls out of sync with your source. It's also awkwardly verbose, and only loosely JavaScript based (essentially copied from Javadoc).

React users have React.PropTypes, which is pretty cool, but too React-specific and also awkwardly verbose. I am working on rtype/rfx to fill a void in this department.

If there was anything I believe to be better, I'd happily link to that, instead. =)

ericelliott··on Must-See JavaScript Dev Tools
Try restricting yourself to the ASM.js subset of JavaScript and see how things work out for you. JS is capable of supporting Unreal Engine 4 games in-browser by compiling to ASM.js. Of course JavaScript's dynamic features and garbage collector are going to have an impact on perf. See if you can sidestep them to improve on your results.

Another issue you may look at is that we don't have standardized support for SIMD yet (but it's coming soon). SIMD would help a lot for the Mandlebrot set. Try with one of the experimental SIMD implementations and see how that works for you.

You're right that I'm not familiar with the profiling features for C# tools, but DevTools' profile recording, flamegraphs, and memory profiling features are better than the tools I used in C++ and Java. =)

ericelliott··on Must-See JavaScript Dev Tools
Flow's type inferrence features are great, but I'm not a fan of the inline type annotations, which is one of the major reasons I didn't just use it instead of working on rtype/rfx.

I believe that both Flow and TypeScript are competing solutions that are precursors to what may eventually become standard in JavaScript. At that point, all the annotations written for Flow and TypeScript will become obsolete overnight.

This is essentially the same thing that happened to AMD, and one of the reasons that I advocated for users to chose Node-style modules and Browserify (and now Webpack) instead of AMD.

I consulted on several projects and gave exactly that advice. They didn't listen. Now they're stuck supporting a huge AMD legacy & Bower ecosystem and the authors of Bower are no longer supporting it.

That is the future that awaits those who build TypeScript + Flow-annotated applications. Fine if it's just a few modules here and there, but for large enterprise apps, you're building a mountain of technical debt what will eventually need to be paid.

Don't get me wrong, I am really excited that Flow and TypeScript are paving the way, and I blatantly stole some good ideas from them for rtype/rfx, but I'm also very wary about leading people down a road that I am pretty confident will dead-end within a few years.

Both projects still have great value though. We learned a lot from AMD, and it has influenced the new standards. I am confident that TypeScript and Flow with both influence whatever we get in the JS standard. I know the TypeScript team is already experimenting with additions to the runtime reflection specifications coming in future iterations of ECMAScript.

ericelliott··on Must-See JavaScript Dev Tools
You're right, but...

These features are available for JS using add-on features such as JSDoc, TernJS, etc... but you're right. Cross-file, these tools don't work as well as they do for Java.

BUT.

If you need super-advanced cross-file refactor capabilities, chances are you're not using modern best practices for JS application design, including small modules with simple APIs & the open/closed principle (try to make APIs open for new features, but closed to breaking changes).

Using small modules generally means that you don't write one large monolithic app. Instead, your app is broken into smaller self-contained pieces that are independently usable and independently testable. Doing so dramatically reduces the need for the kinds of refactors that are harder to do in JavaScript than in statically typed languages.

There are also lots of advantages to languages such as JavaScript that allow for type inference without annotations littered all over your code.

Annotations come with a cost, and JS provides many benefits that are not available in languages like Java.

As I said in the article, the JS runtime tooling makes intellisense look like a baby chew-toy.

ericelliott··on 5 Questions Every Unit Test Must Answer
> Unit tests are usually too low-level to give feedback into the API design. My experience is that functional tests, based on use case scenarios, give much better feedback.

I was talking about the API of the unit under test. In JavaScript terms, this typically means the public API of the module being tested. APIs are developer UX, and providing a good developer UX is great for code quality.

> Standard TDD-based design doesn't really have a way to specify which is part of the "public" API vs. the testing API.

You should only test the module's public API. If there are functions used internally by that module that also need testing, those bits should be in their own modules with their own unit tests.

> Unit tests rarely encode performance requirements.

Correct, but mostly because the biggest perf problems don't happen at the unit level. They happen at integration levels where things like network communications and disk access happen. Unit tests document the unit's requirements, not the app's requirements. That's why it's also important to have functional tests, and depending on needs, integration tests as well, but even those usually don't measure perf. That's where load testing and app profiling come into play.

All of that is important, and I'm not trying to downplay any of that. However, none of those things can replace unit tests, and the benefits of documenting unit functionality in code.

> Manual QA is a skill in it own right. This is why you have QA staff

Agreed, but it would be extremely inefficient for a developer to ask the QA team for help testing every time they make a change to a unit under development. Automating unit-level QA can solve time by automatically checking the full behavior suite of the unit under test every time the developer saves a file. Studies have shown that far fewer errors make it into the released product when developers use a TDD process, which saves developer time, saves QA time, and improves the user experience, because there are fewer product defects.

> You’ll probably get better return on your investment by automating integration tests, bug regression tests, and system tests than by automating unit tests.

That's one person's opinion. The empirical evidence linked to in the article says otherwise.

In the article you refer to, James Coplien betrays his misunderstanding about the ideal role and use of unit tests by talking about refactoring already existing functions into smaller, more testable functions. Using the TDD process (test first), you write the assertions before you implement the functions, so no such refactoring is necessary.

He also talks about the futility of large code coverage from the perspective of somebody going back over code and adding tests later, which can indeed be quite challenging, but if you're following TDD, you don't write code paths that do not satisfy a test assertion, which guarantees 100% code coverage.

It would be silly to throw out a process that has been tried and proven because of the opinion of somebody who doesn't even understand the process to begin with. =)

ericelliott··on Get Ready for the Future: A High Tech Video Time Capsule
Do you have any particular technologies in mind?
ericelliott··on Get Ready for the Future: A High Tech Video Time Capsule
What future technologies are you most excited about?
ericelliott··on The “What Are Monads?” Fallacy
This is a terrible argument. I agree with the sentiment that code should be easy to read and debug for mere "mortals", but functional programming can radically simplify the process of understanding programs in many ways. Don't fear the monad!

See: https://medium.com/javascript-scene/the-two-pillars-of-javas...

ericelliott··on The Two Pillars of JavaScript
JS has some great features, but I sincerely hope we move on from JS as soon as possible. IMO, it's pretty well done its job, and it's most interesting now as a compile target (particularly with source map support!)

I'm not a fan of C++ (I'm a recovered user and abuser of C++), but I AM a fan of many things built with it, including the Unreal4 engine, which runs great when compiled to JavaScript. =)

I've been using and really enjoying CoffeeScript, which, IMO is what ES6 should have been. I also like to fiddle with Haskell, and there is a Haskell to JavaScript compiler, too.

Whatever catches fire after JS, I hope it has these features:

* Dynamic object extension + better abstractions around common prototypal OO patterns -- maybe something like built-in stamps? * Lambdas with closure * Immutability by default * Functional utility belt built-in to the core with a single API around streams, continuous data sources, and collections including arrays and objects/associative arrays/touples. This API should behave the same way regardless of whether data flows through the functions one value at a time (i.e. iterables / generators + yield), in response to emitted events (e.g. Node-style streams), and periodically sampled values (continuous data sources such as audio, electrical signals, UI inputs, even time-independent things like vector graphics, etc...). * The necessary primitives to support the above. Functor literals, promises, etc... * A better single number type for most use cases * The ability to easily define custom binary types, for implementing things like low level binary protocols more easily

ericelliott··on The Two Pillars of JavaScript
> Forcing both sides to pretend that each object is a unique and special snowflake when that is both counterfactual and inconvenient for all involved seems pretty silly.

That's not at all what prototypal OO does. A prototype in JS is very simple: It's an object, just like any other object. It's not pretending to be anything else but an object.

When another object links to that prototype (using the `new` mechanism or `Object.create()`) that object is not pretending to be a unique and special snowflake. In fact, exactly the opposite is happening: It's delegating everything that is "the same" to the prototype it references.

The primary advantage to that is a simple matter of memory conservation. Otherwise, you might as well just copy properties from the prototype to the new object. Some functional languages do essentially that every time you create a transformation, because state in some functional languages is immutable.

Under the hood, such languages are actually just copying references to shared data, which acts very much like prototypes, practically speaking. The difference being that the language users are not exposed to the mechanism.

These are very different paradigms from classical inheritance where everything you extend creates an "is-a" relationship and a single parent object hierarchy. It's a strict tree system.

Prototypes in JavaScript do nothing of the sort, because you can use dynamic object extension to build up a prototype from as many sources as you like. The practical upshot is a lot more freedom, no more need for hierarchies, which eliminates the need for "super" calls, which reduces coupling -- the children have no knowledge of the prototypes that have been composed together to create the API of the child.

See "Prototypal Inheritance with Stamps" for more detail: http://ericleads.com/2014/02/prototypal-inheritance-with-sta...

ericelliott··on The Two Pillars of JavaScript
Google "classical inheritance harmful" and you'll find articles with plenty of code examples. The point of my article was not to bog the reader down in implementation details, but to communicate high-level concepts in rant-style prose. ;)

Here's a bit of code, ranting against the same problems, but coming up with different solutions: http://berniesumption.com/software/inheritance-is-evil-and-m...

Here's a nice quote:

> I once attended a Java user group meeting where James Gosling (Java's inventor) was the featured speaker. During the memorable Q&A session, someone asked him: "If you could do Java over again, what would you change?" "I'd leave out classes," he replied. After the laughter died down, he explained that the real problem wasn't classes per se, but rather implementation inheritance (the extends relationship). Interface inheritance (the implements relationship) is preferable. You should avoid implementation inheritance whenever possible.

Link (with code samples): http://www.javaworld.com/article/2073649/core-java/why-exten...

More ranting: http://sebastiansylvan.com/2010/12/03/implementation-inherit...

Fairly decent list of rants, with some pointed quotes from software development luminaries:

http://harmful.cat-v.org/software/OO_programming/

As for the IGG campaign, yes, I'm selling something. I make a living writing software, and teaching other developers how to write software better.

That has nothing to do with the validity of my arguments, except to underscore the fact that there is plenty of real experience behind the words.

"The way to be a 10x engineer is to teach 5 other developers how to be 2x engineers."

ericelliott··on The Two Pillars of JavaScript
> it seems to be working pretty okay.

These things have a tendency to balloon out of control over time. I've seen class hierarchies start out very benign. Convenient and well-designed, even.

But as the codebase grows and new objects need to be modeled, it inevitably gets stretched beyond the limits of its original design, and that's where things start to crumble.

Also, the more layers of inheritance there are, the more brittle the code becomes due to tight coupling between child and parent classes. Super calls start to turn into a tangled nightmare.

Here's a different perspective on the same topic: http://berniesumption.com/software/inheritance-is-evil-and-m...

← PreviousPage 3 of 3