Napa.js: A multi-threaded JavaScript runtime - <AUTHOR> https://github.com/Microsoft/napajs <comment><USER3> This looks great, but it's important to bear in mind the architecture you intend to run on. I recently made an application blazingly fast by - <USER2> other things - parallelization using the node cluster module. On my 4-core laptop it flies. Imagine my surprise when I deployed to the cloud environment and found the typical virtual server in our cluster has only a single CPU core. The worker threads just sit around waiting for their turn to run, one at a time. On the other hand, the platform for serverless functions has 8 cores. At a minumum, before you jump into multi-threading, know what `require('os').cpus()` tells you on your target platform.

<comment><USER4> Which platform for serverless functions has 8 cores? I have a CPU intensive data deployment script (Node.js) that takes 12 hours on a single thread but can be chopped up to take advantage of more cores. Our build server on ec2 has 2 cores so it's about 6 hours. It would be great to know if we could push the job into serverless and get it done a lot faster.

<comment><USER5> How can a "serverless function" have cores if it doesn't have servers and "it is just code" :/

<comment><USER6> Because "server" started taking on the meaning of "configurable box" to people who were frustrated with configuration, so "serverless" means "unprovisioned/unconfigurable" machines.

Now if we started talking about "computeless" architecture I'll be confused. (Though maybe that'll be the trendy name for serverless data sources/sinks in a few years...)

<comment><USER5> > so "serverless" means "unprovisioned/unconfigurable" machines

I am pretty sure in English serverless means no server and "unprovisioned/unconfigurable" machines means you didn't provision them and you cannot configure them. Even in analogical sense this makes no sense. Something i could relate to is something like "Pay as you use" or "configurationless servers".

But that is just me, and if you think it is ok to randomly change the meaning of words that means me personally and randomly don't need to accept your new meaning (not giving out, just trying to explain my rationale)

Downvote all you want, but please do point out where i am wrong.

<comment><USER7> In a very literal sense, you're not wrong. But the concept of a _serverless_ architecture (as of common parlance today in 2017) has a lot of nuances which are hard to convey in _any single_ word.

So eventually people picked one. Today, the most common are "serverless architecture", "FaaS", or simply "Lambda" (borrowing from AWS).

 _You_ don't _have_ to do anything. But it's simply a _fact_ that many people know what you're talking about if you say the word "serverless". And that's what language is, a (kinda) agreed upon set of words which let you communicate with other people. If everyone but you understands a word, and you are crusading that they change it to something else, what is the point?

If you're interested, the concept of "prescriptivism" may be enlightening.

<comment><USER5> My point is that i was not aware what "serverless" meant when i first came upon it and the word itself did not convey any meaning without a lot of context as it does not lend it self to analogies such as "server", "container" or even "cloud" for that matter.

<comment><USER8> True. I regularly encounter words whose meanings in whatever context I don't understand. Usually, if a word sounds confusing or used in the wrong context, a quick Google search will clarify what I was missing. Sure its a bit irritating when words are recycled to have a different meaning, but its rarely an issue in practice, in my experience and opinion.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER9> An alternative approach to concurrency is the one that Erlang (and your operating system) take: memory-isolated processes, preemptively multi-tasked, where neither IO nor computation in one process can adversely affect the others because the scheduler prevents it.

I wrote this up: [https://news.ycombinator.com/item?id=15499629](https://news.ycombinator.com/item?id=15499629)

<comment><USER10> Ryan Dahl wanted Node apps to use a multi-process model. Hence the name. The vision wasn't as evolved as Erlang, but conceptually closer than what Node looks like today.

"I believe this to be a basis for designing very large distributed programs. The "nodes" need to be organized: given a communication protocol, told how to connect to each other." ttps://www.americaninno.com/boston/node-js- interview-4-questions-with-creator-ryan-dahl/

</comment></comment><comment><USER11> You can get rid of the need to multi threading by deploying more containers in the same machine or via orchestration.

I don't understand why people keep insisting that the lack of multi threading support is a Javascript problem when there are better and more scalable ways of using your machine resources.

<comment><USER12> > You can get rid of the need to multi threading by deploying more containers > in the same machine or via orchestration.

What if you have a large shared in-memory data structure that you want to update with lots of irregular translations in parallel? Like many graph problems? How are you going to do that with multiple containers? As in industry we just don't understand how to distribute that kind of problem effectively.

<comment><USER13> Shared data structure among multiple threads... this sounds utterly fimilar and evil! Redis is single-threaded, probably one of fastest,has data different structures, can handle high loads, code is easy to reason, something that just works.

One of the reasons Node is successful is the simplicity of single threaded code. Way easier to reason, I would question the usage of Node if you are doing something CPU bound with it. You can use golang or C# with tasks for that.

<comment><USER14> So just because shared memory is hard you are ok with sacrificing performance and replacing memory access with io hops? That sounds like an overkill and not suitable for every task.

<comment><USER15> I like node.js and use it very often (had my first package reach over 100 stars, woohoo :) ) but I don't understand why it needs to be suitable for every task.

If you really want to do something creative with the shared memory, I guess you could do that in a "native module" written in c++ or even Rust[1].

I'm not saying that it's not doable with JS, it's just that it's already been done (as in, has a solution that works).

[1]: [https://github.com/neon-bindings/neon](https://github.com/neon- bindings/neon)

<comment><USER16> Why should i learn a new language for that? It's good to have as many options as possible in js and you take the one that fits you best.

<comment><USER17> Because JS isn't good at everything just like C++ and Rust aren't good at everything.

Right tool for the job.

<comment><USER18> But if you take that to an extreme, you end up with a hundred tools. I think it's good to have the option to do parallel computing in JS, for those times when it's worth the tradeoff versus having to adopt a completely new language/platform.

<comment><USER17> Sure, anything taken to an extreme is bad. I wasn't suggesting to do that.

I think if there is a sensible use-case for parallel computing in JS, it would be good to have. However, trying to make a solution before we have a (clear) problem is foolish.

I'm not saying there isn't already a use-case, but I haven't seen one that isn't already covered by languages better suited to solving those problems (e.g. Rust).

Edit to give a different example: parallel computing in JS is like trying to write a web framework in Rust. Sure, you _can_ do it, but Node is already better suited to doing that. At best, you're making a worse version of something that already exists.

<comment><USER18> > parallel computing in JS is like trying to write a web framework in Rust. > Sure, you can do it, but Node is already better suited to doing that. At > best, you're making a worse version of something that already exists.

I agree with you, but my point is it's not black and white. For a sufficiently small or simple project, it might make sense to write a web backend in Rust, or do parallel computing in JS, if the cost of learning a new platform outweighs the cost of using the "wrong tool".

In most circumstances, yes, you probably shouldn't use Node.js for parallel computing tasks, just like you shouldn't use C++ for web development, but for some use cases it might be useful. And maybe those use cases don't exist (I don't have much experience in this area, so I don't know), but I just don't like when blanket statements like "use the right tool for the job" dismiss the work other people have done. Surely if Microsoft created this, they have a use case in mind for it?

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER19> I will circle back in a year or so to see if this 'sticks' \-- very few Microsoft open source projects provide enough value / demonstrate enough inertia this early in their lifecycle to justify any investment on my part.

[https://github.com/MicrosoftArchive/redis/issues/556](https://github.com/MicrosoftArchive/redis/issues/556) (Jun-Sep 2017)

> _Why do MS always do this??? Start something, announce it aloud "we are now > open source, we are now this and that blah blah" then quietly do a 360 and > moonwalk away_

<comment><USER20> Perhaps a 180? :-)

<comment><USER19> To be clear for non-Michael-Jackson-fans: 360 + moonwalk works out the same (by sliding away backwards).

[https://en.wikipedia.org/wiki/Moonwalk_%28dance%29](https://en.wikipedia.org/wiki/Moonwalk_%28dance%29)

> _moves backwards while seemingly walking forwards_

It's actually a near-perfect analogy here, where actions speak louder than words re: Microsoft's commitment to maintaining adaptations of existing open source projects. I think the example provided is enough to trigger a careful analysis before jumping in, and I would love to see counter-examples to help balance the evaluation.

(Please note: very specifically requesting counter-examples of Microsoft- official, intended for production, open source repositories demonstrating long-term maintenance of tweaks of/dependencies on established open source projects that for whatever reason were never up-streamed.)

<comment><USER21> In the case of Microsoft specifically it's a silly meme that started due to the Xbox 360.

'Why do they call it the Xbox 360? Because when you see it you do a 360 and walk away.'

</comment></comment></comment></comment><comment><USER22> Looks almost the same as something using fork and message passing, which also scales over several machines. The examples should show use cases that use shared memory or examples where it wouln't be possible to use worker processes.

<comment><USER23> V8 doesn't support (real) forking, unfortunately

</comment></comment><comment><USER24> Here is why napajs is started: [https://github.com/Microsoft/napajs/wiki/Why- Napa.js](https://github.com/Microsoft/napajs/wiki/Why-Napa.js)

</comment><comment><USER25> This is far from the first attempt to do bring multithreading/parallelism into JS. A (failed) example:

[https://en.wikipedia.org/wiki/River_Trail_(JavaScript_engine...](https://en.wikipedia.org/wiki/River_Trail_\(JavaScript_engine\))

Another attempt (although a different approach) is here : [https://github.com/tc39/ecmascript_sharedmem](https://github.com/tc39/ecmascript_sharedmem)

Hopefully, Microsoft will learn from the errors of others. Interestingly, napa is build on V8, not on MS own javascript engine.

<comment><USER26> Webkit is also working on this:

[https://webkit.org/blog/7846/concurrent-javascript-it-can- wo...](https://webkit.org/blog/7846/concurrent-javascript-it-can-work/)

</comment></comment><comment><USER27> Nice, but:

1\. It is exposed as a nodejs module, but some other modules may be at conflict because they may wrongly assume that they are the only thread running. E.g., some modules may be using global variables in C++.

2\. Still, it doesn't support fast immutable communication (structural sharing) to other threads through shared memory.

<comment><USER28> What would it take to get number two to become a reality? Some sort of special module? This is the one main drawback I've found doing "production stuff" with Node.

Does Java offer cross-thread shared memory? Go, Haskell, Python, etc.?

<comment><USER29> Java does shared memory by default and even has concurrency related concepts as fundamentals of the language (Object.wait(), etc.) .

Python supports threading but is not very useful due to the infamous GIL. However, multiprocessing is usually a decent alternative and it supports shared memory on forking (copy on write, though). Also you can use mmap easily for IPC.

</comment></comment></comment><comment><USER30> One of the great practical examples of this repository is to serve as a counter-argument against people, who complain that NodeJS is not multi- threaded.

For anything else, IMHO the use-case will be so narrow, that I wonder how MS will justify the development resources for maintaining it.

</comment><comment><USER31> I know that the history of projects at a giant company isn't always straightforward, but it's interesting that they chose V8, even though Chakra is maintained by the same company (and supports Node APIs).

</comment><comment><USER32> I think this could be useful but I really hope they get it right (especially the broadcast and other cross-worker communication features). Right now it looks like the broadcast feature cannot target specific workers - That's already a red flag. If they push too hard on thread locking and data consistency across workers, then it's not going to scale and it may lose all the advantages of being able to run on multiple CPU cores.

<comment><USER24> A key design goal is to make all workers within a zone symmetric, broadcasting/executing to specific workers is an anti-pattern. Please see: [https://github.com/Microsoft/napajs/wiki/introduction#zone](https://github.com/Microsoft/napajs/wiki/introduction#zone)

</comment></comment><comment><USER33> I'm excited. My friend is working on extending rpgmaker, a game engine built on node. Say what you will about building a game engine on top of Node but this could be a very useful way to offload CPU heavy tasks from the main render thread

</comment><comment><USER34> Any informed commentary on the pros/ cons of this vs cluster?

As far as I can see, cluster workers are all uniform (no task-specific pools) and cluster has no broadcast (just `worker.send(message)`.)

<comment><USER13> Cluster runs multiple processes, this is multi-threaded. So everything is isolated there, communication can happen only through IPC mechanisms, and high memory overhead. In case of threads its typical synchronization with of course shared memory side effects. It's a typical thread vs process debate.

</comment></comment><comment><USER35> This looks very similar to the concurrency and isolation patterns of the Dart VM.

"Use Isolates for secure, concurrent apps. Spawn an isolate to run Dart functions and libraries in an isolated heap, and take advantage of multiple CPU cores." \-- [https://dart-lang.github.io/server/server.html](https://dart- lang.github.io/server/server.html)

</comment><comment><USER36> This is interesting. I see some negativity in the comments, but I think this was really a missing piece of the Node ecosystem, and I hope this solution ends up getting good adoption. On a slightly related note, I wonder if ClojureScript + Node would be the best way to take advantage of this. Has anyone here used ClojureScript with Node?

<comment><USER37> If you were wanting multithreaded Clojure, you're probably already using the JVM. It's much more mature and performant and tunable for that use case.

<comment><USER36> True! One thing I have noticed, though, is that a lot of Clojure code is blocking (database drivers, and such), so some subset of problems might be easier to write on Node. In addition, we are currently running Node in production, but not the JVM, so targeting Node with ClojureScript is an easier sell than creating a whole new deployment target.

</comment></comment></comment><comment><USER38> One of the reasons npm modules are largely compatible with each other is the fact that they share the same threading model, which is what the event loop offers.

Then, this has a lot of compatibility issues, and release-wise it will be hell. I don't think this is a good idea.

</comment><comment><USER39> This looks a lot like web workers, which Node.js does not have. Hopefully they will add it. [https://github.com/nodejs/worker/issues/2](https://github.com/nodejs/worker/issues/2)

<comment><USER40> fork works fine in node.js

<comment><USER40> why down vote ? fork is fine as long as the communication between the two processes is low-bandwidth.

<comment><USER23> Shared memory & low overhead sharing of expensive objects is probably _the_ primary reason to use Napa

<comment><USER28> I don't think Napa features shared memory though, does it?

<comment><USER24> Since everything is in a single process, they can be shared via native structures. Each JS thread has its own heap, there will be a cost to transfer the shared native structures into JS object.

For complex objects, usually JSON is used thus marshall/unmarshall is needed. But for objects like UTF-8 string or ArrayBuffer, the same layout is used across JS and C++, thus at almost no cost.

Another thing is that between addon-modules, they can pass pointer of native structures (like Buffer) using 2 uint32 through JS. In this case, JS works as a binding language.

</comment></comment></comment></comment></comment></comment><comment><USER41> It makes you wonder why they choose V8 instead of their own JavaScript engine

[https://github.com/Microsoft/ChakraCore](https://github.com/Microsoft/ChakraCore)

<comment><USER42> My personal theory is that they're trying to improve the JS engine in Electron so they can improve VSCode. The VSCode people have posted some performance complaints in the past.

I would assume this would benefit desktop JS most, so it'd undoubtedly help Electron apps.

EDIT : There's a better explanation at [https://github.com/Microsoft/napajs/wiki/Why- Napa.js](https://github.com/Microsoft/napajs/wiki/Why-Napa.js)

</comment></comment><comment><USER43> What does this give you over using fork in node? The zone concept seems nice but I'm not understanding why I would use napa when node is designed to easily spawn nodes of parallel execution?

<comment><USER36> If I understand correctly, it looks like it allows some basic sharing of data without duplicating it in a bunch of heaps. It's not 100% shared memory, in that if several threads are accessing an object, that object will be duplicated in each thread, but it has a store mechanism which essentially can serve as an in-process cache that is shared across multiple threads.

<comment><USER24> That's correct. Think about a scenario that each worker needs to access a 1GB hash map. In node cluster, we have to load this 1GB map per process, but in the same process, all JS threads can access the map via an addon.

</comment></comment></comment><comment><USER44> I was expecting something like this for a long time. Thanks!

</comment><comment><USER45> I dont think JavaScript needs threads.

<comment><USER46> > I dont think JavaScript needs threads.

Seriously... when publishing a project like this, the authors ought to give a least a bit of insight into their motivation. Their examples include calculating Fibonocci in parallel, not exactly breakthrough.

<comment><USER47> I know it's addicting to be dismissive, but:

[https://github.com/Microsoft/napajs/wiki/Why- Napa.js](https://github.com/Microsoft/napajs/wiki/Why-Napa.js)

</comment></comment></comment><comment><USER48> Is this multi threaded Node workers that can only share read access to their parent process' pid?

<comment><USER13> Nops pure threads inside a process.

<comment><USER48> Is hiding the mutable shared memory and introducing mandatory serialization for message passing a design decision or technical limitation of v8?

</comment></comment></comment><comment><USER49> Can we please stop calling things ".js" if they are not actually JavaScript files or libraries written in JavaScript meant for direct inclusion in JavaScript source? Call it NapaJS, not Napa.js.

</comment><comment><USER50> How does it compare the (discontinued) JXCore?

<comment><USER24> JXCore is based on node codebase, while Napa.js is written from scratch with multi-threading consideration at its core. We evaluated JXCore before starting Napa.js, but found easier to re-architecture to get performance and memory sharing right.

</comment></comment><comment><USER51> Sounds great! Now, We can make memory efficient Electron with this kind of runtime. It will make JavaScript to be used in creating desktop application more reasonable.

<comment><USER52> Not really, multithreaded applications are not more memory-efficient.

<comment><USER24> Yes in common sense.

But for node cluster's case, if we need to load a data set for a worker to serve request, it has to be loaded on each process. While the multi-threaded model will have only one copy.

</comment></comment></comment><comment><USER53> This is good however IMO if you need parallelism you should not use node period.

</comment><comment><USER54> Shared memory!

</comment><comment><USER55> Took long enough for threads to reach JS as well

</comment><comment><USER13> Wait what? Why are they getting rid of simplicity and model that just works. Once again Microsoft managed to put on some C# programmers on JS. The first thing they thought was why doesn't it support threads! Let's build thread support and get a promotion!

Edit: I would question usage of Node if everything you are doing is CPU bound. I think people started down-voting me without going through docs, I mean just read this documentation page and tell me this is right [https://github.com/Microsoft/napajs/blob/master/docs/api/mem...](https://github.com/Microsoft/napajs/blob/master/docs/api/memory.md#memory- allocation-in-cpp-addon)

<comment><USER56> The README expained it clearly

> As it evolves, we find it useful to complement Node.js in CPU-bound tasks, > with the capability of executing JavaScript in multiple V8 isolates and > communicating between them.

Not everything MS did was evil.

<comment><USER57> It's not evil it's just dumb. If your workload is CPU bound you probably shouldn't be running it in Node.js.

<comment><USER58> There are some cases on the threshold that this can be useful for.

For example, let's say your Node application's requirements changed, and now you have to transform a set of five JSON objects to one JSON object, with some big arrays, indexing, and sorting required. The operation takes 10-100ms of cpu time, which isn't nuts, but with thousands of requests per second would normally be a catastrophe. If you can spawn a thread in this case you can save the day.

<comment><USER57> You say that 10-100ms of CPU time on the hot path of your requests isn't nuts, but we'll just have to agree to disagree about that.

<comment><USER58> All I meant was "transforming and merging complex documents can really take this much time", not "stopping your whole server application for this long is okay" (that would be nuts).</comment></comment></comment></comment></comment></comment>


Blub Paradox (2014) - <AUTHOR> http://wiki.c2.com/?BlubParadox <comment><USER2> This article discusses the Blub Paradox essay and some of its shortcomings.

The original essay is one of the few texts that stuck with me. I read it not as an affirmation that some languages are strictly superior to others (in particular lisp) but as a push to try new paradigms and ideas even if I cannot see, from my current point of view, how they could improve on my current practice. It is one of the reasons that had me trying Rust this year.

</comment><comment><USER3> If iOS had required Lisp instead of Objective-C, then Lisp would have been popular right now. Ruby really needed Rails to get people to try it.

I think the killer use problem is more an explanation then anything else. Java also showed a good marketing, well funded campaign does wonders.

<comment><USER4> > If iOS had required Lisp instead of Objective-C, then Lisp would have been > popular right now.

It could have dragged iOS popularity with it.

Pushing, promoting or forcing something is not enough for it to become popular and widely used.

<comment><USER3> Given the hype and the company, there was no way Lisp would have drug it down. The only way for it to affect iOS was to provide a worse environment than the web apps. People would have found a way just as the reluctant found a way with Objective-C.

Ask Sun about Java and their promotional campaign. When a teacher at a community college in North Dakota gets a call and sent a book to help him decide to teach their language, you can be very effective at pushing.

<comment><USER5> > People would have found a way just as the reluctant found a way with > Objective-C

But the people most likely to develop iOS apps at the start were likely already familiar with Objective-C, I think, due to it being the favoured app platform on OSX, no?

<comment><USER3> I would have thought the same thing, but if you look at a lot of the early app developers, they did come from other platforms. It was easier for an OS X developer, but there were a lot of new people who complained about Objective-C but just got on with it. A lot of early tutorials are really geared to the bigger group of new developers.

On a side note, I really do believe the people behind Swift hate Objective-C and a lot of the old complaints are "solved" by Swift.

</comment></comment></comment></comment></comment><comment><USER6> > C++ and Scheme are examples of (near) parity, in Graham's terms, anyway > because of C++ templates and Scheme macros doing nearly the same things

This one sentence to me is an indication that the author has completely missed the point. Templates and macros do the "same thing" only in the sense that all languages do the "same thing" at some level of abstraction, that is, model Turing machines. What matters is not what languages "do" when they are compiled, but in how they bridge the "impedance mismatch" between TM's and human brains. And in that regard, templates and macros are about as different as two language constructs can possibly be.

</comment><comment><USER7> I really hate these wiki-articles. (Not Wikipedia, articles like this one.) The conversational back-and-forth gets confusing when it goes for a while. And the article goes on long wandering digressions that make it hard to see any actual points that the article had.

If you want to actually say something, _don 't do it like this_.

</comment><comment><USER8> Is this some kind of Dunning-Kruger effect?

Anyway, I don't think it's right mental picture, and thus context for paradox. Language power, I believe, cannot be defined with one dimension. What is more powerful, Java or SQL? Will SQL benefit from encapsulation or will Java benefit from window functions?

<comment><USER2> The linked article is not the original Blub paradox essay and does highlight this problem (the first element in the "A few problems with the BlubParadox" list).

</comment></comment><comment><USER9> The general concept becomes much more interesting when applied to spoken languages.

</comment><comment><USER10> Isn't anyone but me annoyed by the lack of scientific rigor in arguments like these?

PG: - It is more efficient to write software in Lisp. Others: - Nah, it doesn't matter.

But no empirical evidence has ever been presented...

<comment><USER4> There is some empirical evidence. I can't find it now but I've seen research showing Lisp beating all languages in terms of speed of creating some programs from scratch by both experienced Lisp developers and students new to the language. Obviously no research for large projects, those can only be researched through things like github data, etc.

<comment><USER11> [http://norvig.com/java-lisp.html](http://norvig.com/java-lisp.html)

Start there, some more links from there to details on the study and follow- ups.

<comment><USER10> Thanks for the links! Of those, the only one I can find dealing with development speed in Lisp vs other languages is [http://www.flownet.com/gat/papers/lisp- java.pdf](http://www.flownet.com/gat/papers/lisp-java.pdf) and that study is flawed due to the self-selection of test subjects. Given 50 years of [http://wiki.c2.com/?SmugLispWeenie](http://wiki.c2.com/?SmugLispWeenie) the amount of empirical results is very low.

<comment><USER12> Ulrich Stärk's empirical research (no Lisp):

[https://web.archive.org/web/2017/https://www.plat- forms.org/](https://web.archive.org/web/2017/https://www.plat-forms.org/)

It is hard enough to get study participants for the common programming languages, I deem it nigh impossible for the obscure ones.

</comment></comment></comment></comment></comment><comment><USER13> It's like... When the aliens in "Arrival" (or Ted Chiang's story of your life) speak Python but you only speak R. Different languages make you think differently.

</comment><comment><USER14> It's kind of interesting in the 2001 essay that invented blub it was suggested as a hypothesis as to

>And if Lisp is so great, why doesn't everyone use it?

Suggesting programmers in a blub language don't realise it's power. I get the impression in the 18 or so years subsequently that the main reason for the low uptake of Lisp is it's power enables people to write clever code that other programmers have quite a job to understand while languages like Python let you do much the same stuff while being easier to read.

So it's not that people don't realise the power so much as they don't want it.

<comment><USER15> I'd love to know Lisp, just like I'd love to know Python. I have no experience in either (I come mostly from Java, javascript with some Ruby and some ancient C/C++ experience). When I look at Python code, I understand what it does. I don't think I've ever written any Python, but I think I could sit down and be productive within a day.

Lisp looks like complete gobbledygook to me. I'd love to be able to understand it and write it, but the syntax doesn't look like it's meant to be human readable. It's almost as much work as reading assembly.

I should probably give it another try, though.

<comment><USER16> But that's because all the languages you know are basically dialects of each other because they all descend from ALGOL, not because they are inherently easier to understand. Similarly, someone trained in Lisp would find things like Scheme and Clojure easier to understand than something like Python because those likewise are dialects of Lisp. I'd strongly recommend studying languages different from ones you know -- they are mind expanding even if you never use them in practice. Not just Lisp, but things like Haskell, OCAML/F#, and Prolog will change the way you think.

<comment><USER17> > not because they are inherently easier to understand

I'm honestly not sure that that's true. I would bet money that someone who primarily works in Lisp would still have an easier time sitting down and reading Python code than someone who works in Python sitting down and reading Lisp, because I think it might truly be inherently easier to understand.

There is intrinsic meaning in:

        x = 5
        let x = 5

etc., insofar as these translate character for character, word for word, into human language, whereas this simply doesn't:

        (let (x 5))

<comment><USER18> There is no such thing as "intrinsic meaning", and I think you might be confusing "human language" and "english-like". There is astonishing variation in human language.

<comment><USER19> I really like Lisp and its macros and I don't even mind the sea of parentheses. But I do think requiring everything to be done in prefix notation is a weakness. This is an argument I have seen -- it may not be the one you are trying to make, but your statement reminded me of it:

"No programming language is more or less natural than Lisp. It is merely a matter of familiarity and the way most programmers were taught."

One obvious problem is that familiarity does matter. Even ignoring all other programming languages, there is a barrier to climb for the vast numbers of beginner programmers who know English and common math notation like f(x) instead of (f x) and x < y instead of (< x y). I've also seen (- x y) be confusing as one incorrect way to read it as English in your head is "subtract x from y".

The other is that for some things, it really does seem like infix notation is inherently preferred by humans. Is there a natural language where conjunctions _don 't_ go between terms, i.e. one says "und x y z" instead of "x und y und z"?

<comment><USER16> Functions are more like verbs than conjugations. And Verb Subject Object (which is rather lisp-like) is not uncommon among natural languages. Arabic and Biblical Hebrew (Modern Hebrew not so much due to influence from Western languages) use that order a lot.

<comment><USER19> That's just fine for things that are function calls in any language. I have no preference between log(x, 10) or (log x 10).

But I do want to read some functions like conjunctions, and in Lisp, I am forced to call `and`, `or`, `<`, `/`, and pals the same way as log, print, etc. I just don't think I'll ever find:

        (and (not (is-blocked door))
             (< (height player) (height door))
             (or (is-unlocked door)
                 (has-key player door)))

as readable as:

        not is_blocked(door)
        and height(player) < height(door)
        and (is_unlocked(door) or has_key(player, door))

Edit: to expand, I don't think it's a fundamental flaw of Lisp. There could easily be some syntax sugar that lets you specify precedence rules for functions and write them infix, just like Haskell lets you write either `(+) 1 2` or `1 + 2`. It would de-sugar to the same sexpr.

I know this can be done as a macro, in fact I did it for elisp several years ago ( [https://github.com/rspeele/infix.el](https://github.com/rspeele/infix.el) ) but it is really just a toy for personal use. If an infix operator system came out of the box and its use was encouraged for certain common operators, I think that would be a net positive, but most Lispers disagree with me there (if I had to guess).

<comment><USER18> The Lisp expression is a nice sideways tree, where we immediately see that three conditions are joined by _and_. When I look at it, I see this:

         and --.-- not (is-blocked door)
               :-- < (height player) (height door)
               `-- or --.---(is-unlocked door)
                         `--(has-key player door)

The other one looks like a bit of a _lorem ipsum_ paragraph to me.

<comment><USER19> I guess it comes down to different strokes for different folks. It would be interesting if there was a website that quizzed you on randomly generated expressions like these, giving you S-expr forms sometimes and ALGOL/infix operator forms other times, and asking you whether the expression is true or false given a set of variable values.

Naively I would guess that I would do best on infix exprs and you would do best on s-exprs.

But I could imagine other results, like s-exprs giving me a speed disadvantage but an accuracy advantage (either because I had to read them more carefully or because they eliminate reliance on precedence rules). Or there may be other quirks, like maybe S-exprs read better for larger, multiline conditions while infix reads better on short one-liners with <= 3 operations.

It reeks of effort so I'm not going to make such a site, but I do wonder what the results would be.</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment>


Ask HN: What makes a homepage great? - <AUTHOR>

What is the recipe for a perfect homepage? Navigation? Personalization? Quick access to important information? Suggestions for Call-to-action?<p>Let's take facebook and google+ homepage for example. According to you what makes them great or what improvement they need? <comment><USER2> From a user experience point of view it depends on your audiences needs.

for example if you have a holding page then a call to action to register your interest and the reason why you would do so are the priority.

for a generic landing page for your new users you need to think of origin

if from a google search then there is something the page that interests them, find out the search term and if in line with your businesses goals/product then make this information clear and leading into your product.

if its from recommendation i.e. 'hey steve visit x' then you want your landing page to explain what you do as clearly as possible, then a call to action for their most requested event e.g. how much does it cost, where do i register</comment>


Ask HN: I've grown to hate my colleagues - <AUTHOR> I've recently made the move away from being a senior web developer to being a Business Analyst and Strategist.
It's something new. I'm lucky to have it especially when most people look at my development career and not my aspirations.
On my first day, barely a soul spoke to me. I wasn't always a chatty guy but I figured with this role being what it is, I needed to do the opposite of what I'd normally do. Instead of sitting at my new desk and eating my lunch, I ventured into the lunchroom.
"Hey, how's it going?", I said to the Project Manager eating her lunch.
I get a soft whisper. I guess that means "ok".
crickets
Ok, I'm the new guy. Maybe she's the shy sort.
Lunchroom laughter and long coffee breaks.
Maybe I'm just making a mountain out of a molehill. It doesn't matter. I get along with the two bosses pretty well and that's enough.
Today I transferred a call to another developer. He yelled at me and told me that next time I should "shut up". Apparently he was in the middle of something at the time. He then answered the call, put the phone down and walked out for the routine morning coffee.
I've been in the IT game for a decade now and I've snapped at others but often it was in the form of an agitated response. Maybe a furrow browed "Yes?" or "What!?".
Now this is an open plan office so the boss heard all of this. He simply utters: "Well how were we supposed to know you were busy?". That's the end of it. Nothing more than that. I received no apology and the day went on as normal like nothing happened.
Maybe this is a rant. Maybe this is my attempt to understand whether others in the community have felt this way before or been through a similar situation. I don't know what to do. I want this job and I've only been here for two and half months. I don't want to quit and explain what happened but I don't want to work in an environment where I find more pleasure talking to clients than the people sitting next to me. <comment><USER2> Hmm - some teams are just toxic and there's nothing much to be done. Although having said that, there is abook about turning around a toxic team: [http://www.goodreads.com/book/show/206309.Fish_](http://www.goodreads.com/book/show/206309.Fish_)

I would either wait until the worst people have moved on (if there is a high turnover) or find a similar job elsewhere. If you explain this in job interviews, people should understand.

<comment><AUTHOR> Thanks for that. Unfortunately it's the good people that leave first.</comment></comment>


Human pancreatic beta-like cells converted from fibroblasts - <AUTHOR> http://www.nature.com/ncomms/2016/160106/ncomms10080/full/ncomms10080.html <comment><AUTHOR> And a popularized version of the article: [http://www.iflscience.com/health- and-medicine/researchers-ha...](http://www.iflscience.com/health-and- medicine/researchers-have-made-insuling-producing-cells-human-skin-cells)</comment>


Rethinking the iPhone lockscreen - <AUTHOR> http://thetechblock.com/rethinking-iphone-lockscreen/

<comment><USER2> This is alright, but which app really gets to own what's on the lock screen? I think there are better design solutions posted elsewhere, including the existing design. I imagine most people think it needs to be improved, but would any change actually make them happier? Probably not.</comment>


Yeti programming language - <AUTHOR> http://mth.github.io/yeti/

<comment><USER2> Would be great to hear if anyone has any experience using this.

edit: did find this off the main page: [http://chrisichris.wordpress.com/category/yeti/](http://chrisichris.wordpress.com/category/yeti/)

<comment><AUTHOR> I've just recently started trying to use it for some hobby Android coding (tired with Java), and for now I have very positive experiences. Feels refreshing, it reinvigorated my will to work on this project, also no bugs encountered yet. Slightly more on this here: [http://softwarerecs.stackexchange.com/a/11178/4980](http://softwarerecs.stackexchange.com/a/11178/4980)

</comment></comment><comment><USER3> Cool, is there any info of the history of the language? It has been in development for a long time, with one main contributor.

phd project perhaps?</comment>


Show HN: Timeline – a tiny, anonymous, plaintext version of Twitter - <AUTHOR> http://t-l.herokuapp.com/ <comment><AUTHOR> Hi, dev here! Comments and so forth are welcome.

<comment><USER2> The id's as unique user id's are currently not secure. You can impersonate any other id by changing the value in local storage in the browser. If you have logs see 5f2860 and fb86f7

<comment><AUTHOR> Thanks for the cheap QA!

</comment></comment></comment><comment><USER3> Please make the ENTER key work. This is nice and light. A more compact display without HRs would be even better--more like HN!

<comment><AUTHOR> Enter key is implemented. Good idea.

Edit: Also compactified. Thanks for the suggestions</comment></comment>


Ask HN: What tools do you use for creating diagrams? - <AUTHOR> We're looking for some open source tools for creating UML diagrams and the sort. What's your goto tool set for creating diagrams/visual organizations of systems? <comment><USER2> [https://www.draw.io](https://www.draw.io) works great for general charts. It has set of UML elements as well, tho haven't used it.

<comment><USER3> I came here to say this. I have to occasionally use Visio for work, and I prefer the simplicity of this way more.

</comment></comment><comment><USER4> OmniGraffle for hand crafted, and general purpose diagrams. Also for mobile diagrams since I have OmniGraffle on my iPhone and iPad Pro. (Apple Pencil support too)

Graphviz and a text editor for quick structured or hierarchical diagrams.

AsciiFlow, for rough and ready diagrams that I need to share quickly or for inclusion in documents where Graphviz is unsuitable.

Those three are my go to tools depending on what kind of diagrams I am working on. I'll use yEd from yWorks on FreeBSD and Linux.

Finally when push comes to shove I'll wind up with Microsoft Visio usually because of either compatibility or having to work on windows.

For UML I think your going to struggle with a pure open source stack. I've found diagramming tools to be one of the weakest parts of open source productivity suites. UML is quite likely to produce a lot of diagrams and your going to want _good_ tools to deal with this. I recommend you chose the best diagramming tool for your platform of choice and just pay for it if it's not free. Wrestling with poor diagram tools is a complete waste of time when good tools that make working with diagrams very easy. I've yet to see a diagramming tool that costs more than the time it saved me. Even Microsoft Visio earned its keep over the few years each license lasted me.

</comment><comment><USER5> Since you're asking the open source software, these are my recommendations:

1\. Draw.io [1] for general charts. Someone has already mentioned it. It's open source software. Draw.io supports flow charts and other diagram types. One thing that I love about Draw.io is compatibility. You can import and export the XML file that contains your diagram. So, I don't need to worry what platform I use. The final diagrams can be exported to SVG and images too.

2\. UMLet [2] or StarUML [3] for UML diagrams. I have no experience with UMLet. I recommend this because it's open source UML tool and actively developed (they need contributors [4]). I know open source UML tools are not as good as paid tools, like Visual Paradigm and Enterprise Architect. Alternatively, you can use StarUML (not open source). It's free although you have to buy a license for continued use.

[1]: [https://www.draw.io](https://www.draw.io)

[2]: [http://www.umlet.com](http://www.umlet.com)

[3]: [http://staruml.io](http://staruml.io)

[4]: [https://github.com/umlet/umlet/issues](https://github.com/umlet/umlet/issues)

</comment><comment><USER6> I've used this free program to make lots of diagrams: [http://pencil.evolus.vn/Downloads.html](http://pencil.evolus.vn/Downloads.html)

I don't know if it's the best thing out there, but it's pretty low risk to try it out. I haven't needed to look for anything better, and it does have some neat features.

</comment><comment><USER7> [http://chartmage.com/index.html](http://chartmage.com/index.html)

</comment><comment><USER8> [https://www.yworks.com/products/yed](https://www.yworks.com/products/yed)

</comment><comment><USER9> Dia, open source. It can draw many kind of diagrams

</comment><comment><USER10> Using PlantUML. [http://plantuml.com/](http://plantuml.com/)

</comment><comment><USER11> Not open source but with a free tier: www.breakdown-notes.com. Disclaimer: my project.

</comment><comment><USER12> I'm a fan of the web-based www.gliffy.com

</comment><comment><USER13> MS Visio, Google Drawings

</comment><comment><USER14> I use StarUML for drawing UML diagrams. [http://staruml.io](http://staruml.io)</comment>


The Incredible True Story of the Collar Bomb Heist - <AUTHOR> http://www.wired.com/magazine/2010/12/ff_collarbomb/ <comment><USER2> Definitely a crazy story and will likely remain one of the most perplexing "unsolved crimes" of our time.

On a related note, though, it seems Hollywood is making a comedy based on this. Yes, you read that right, a COMEDY. I'm not usually offended by things, but I think that's kind of sick. The movie is called 30 Minutes or Less and stars Danny McBride and Jesse Eisenberg.

<comment><USER3> While it's not everyone's cup of tea, dark comedy is a very popular form of comedy, and a way that a lot of people deal with tragedy.

<comment><USER4> Absolutely true. Steve Martin's "Novocaine" was a dark comedy that made fun of the issue of dentists that take advantage of their patients, sexually, while under anesthesia (and it covered drug abuse as well). That was a serious concern too, but they made a (relatively) good film out of it.

I'd say the issue is less the making of a dark comedy, and more that Americans have a hard time, in general, of coping with a tragedy. When is it acceptable to make a comedy about someone's death? Is it acceptable if they were complicit in the act?

</comment></comment></comment><comment><USER5> I am reminded of 'Fargo': a convoluted scheme which comes to no good for anyone and causes a great deal of hardship along the way.

<comment><USER6> Ya, me too.

 _ducks_

<comment><USER4> Hear me out for a second.

I really don't understand this mentality of "yeah me too". It's great to be heard and all, but why contribute anything if you have nothing to contribute.

Furthermore, if you have nothing to contribute, why offer <i>ducks</i> to point this out and make it obvious that you're trying to avoid something?

<comment><USER7> He's making a joke about the dialect used by the characters in Fargo.

</comment></comment></comment></comment><comment><USER8> I was living in Erie when this happened. My roommate worked in the same shopping complex as the bank, in fact. I still feel sick to my stomach every time I think about this. This is the reason why I won't ever become a pizza delivery person.

<comment><USER9> yeah i too have a fear of being lured to a remote location while delivering two small sausage and pepperoni pies, having a bomb strapped to my neck then forced to rob a bank and go on a scavenger hunt afterwards only to be blown up after finding the first clue, with the bomb squad arriving 3 minutes later.

<comment><USER10> You have to be very good at Greek to come up with a word for that particular phobia!

<comment><USER11> Piemuggacollarbombaphobia

</comment></comment></comment></comment><comment><USER12> Sounds like the shotgun-collar trap in Saw III.

<comment><USER13> Or one of the slave collars from Fallout 3.

<comment><USER6> Or one of those slave collars from practically countless other pieces of SF. Not exactly a new idea ;)

</comment></comment></comment><comment><USER14> all on one page: <http://www.wired.com/magazine/2010/12/ff_collarbomb/all/1>

</comment><comment><USER15> I feel bad for the guy having to die with his hands handcuffed behind his back. I mean - at least let him try to disarm his own bomb, he has nothing to lose.

Tell him you'll shoot him if he moves from the area, but otherwise back away and let him try.

<comment><USER16> I can't see how that would have helped anyone. He would have simply struggled to remove the locked collar, if not run into a crowd of bystanders before the bomb went off.

</comment></comment><comment><USER17> Clickable full page version: <http://www.wired.com/magazine/2010/12/ff_collarbomb/all/1></comment>


Fight Against RSI – VoiceCode – Thoughts? - <AUTHOR> http://voicecode.io <comment><USER2> $300 for something I may not end up using is a bit too much!</comment>


BMW passenger car lineup lags behind Tesla Model 3 sales in August - <AUTHOR> https://www.autoblog.com/2018/09/06/tesla-model-3-outsells-entire-bmw-car-lineup/ <comment><USER2> I am curious, is Tesla making a profit at this volume of sales or not. I did notice that the Atlanta delivery center was packed from end to end with model 3s in August but there were a few deliveries of S and X models as well. I am sure it is eating into those sales. I will also be curious if the standard range model will be available in numbers before the decked out version is sold in oversea markets.

personal experience follows.

I took delivery of my 3 on the 29th after ordering the 5th of August. I had no reservation nor was I a previous owner. The car was built in August though according to the VIN trackers the number was issued in July.

Overall quality is really good with only a few paint blemishes that were buffed out. Very slight alignment issue with the frunk but you have to look. Now I will admit this car has seriously changed my mind with regards to car interiors, I doubt I could ever go back to a traditional interior as they would feel cluttered. My previous car was a 2017 Chevrolet Volt and it sold me on driving EV.

</comment><comment><USER3> Misleading title. It only lags behind in the US market.

<comment><USER4> In Canada too, IIRC.

In other words, BMW lags in all countries where the Model 3 is on sales. Tesla is reportedly starting the production of left-hand drive Model 3 so one can expect deliveries of the performance version to start in UK or Australia soon. I'm curious to see how BMW sales will drop there too.

</comment></comment><comment><USER5> I wonder if the Model 3 having a backlog of 100s of thousands of orders due to production delays has anything to do with it?

</comment><comment><USER4> It's even worse for Mercedes, isn't it?</comment>


An implementation of phase-fair reader/writer locks - <AUTHOR> https://arangodb.com/2018/05/an-implementation-of-phase-fair-reader-writer-locks/ <comment><USER2> I don't really like the idea of having a coarse mutex handle the lock's internals.. I Wonder if that can be made a bit more efficient.

</comment><comment><USER3> Would really like to see a lock-free variant of this... Anyone can provide pointers to a lock-free implementation, preferrably in C or C++?</comment>


Ask HN: How do you write code so it's easy to change? - <AUTHOR> I work as a web developer in the startup industry. I've heard many times that code should be extensible – that it should be easy for engineers to make changes to the system in the future, especially as a product finds market fit. What tips would you give other engineers on writing easy-to-change code? <comment><USER2> You're going to get a bunch of extreme platitudes in response to this question.

Like "DRY", "YAGNI", SOLID, short vs. long functions, how to test, minimizing vs. maximizing reuse, static vs. dynamic typing, cyclomatic complexity, interfaces, functional programming, immutability, etc. You should definitely be familiar with these principles and their tradeoffs.

My advice though would be to take them all as suggestions, not absolutes, and to look at your specific requirements of your project, what you know about it and your customers (how it's likely to evolve over time, how it has already evolved, how your company will evolve, who the engineers are, etc.), and then find & adjust the principles that apply. There are no silver bullets here, and which techniques are successful depends very much on the context in which they're used. Work backwards from your team, your situation, and your customers.

<comment><USER3> I agree with this, but I'd like to add one more thing. No matter what you do, if you find that your code is hard to change, then change it so that it is less hard. Next time you visit it, change it again. Keep doing this until it is very easy to change the code. Write enough test support in your code that you can do this kind of work safely.

</comment></comment><comment><USER4> Only write code that's absolutely needed for what you're building.

It's very tempting to make it "extensible" by overgeneralizing. What you get then is overly complex code, most of which is never used.

Cut out everything that isn't currently used, and you have a small system where every line pays for its keep.

<comment><USER5> Agreed - and note that this principle is in tension with the junior/intermediate (heck, even senior) urge to make things "easy to change" by just making everything abstract and configurable. ("See, now if we want to do it this other way in the future, we only have to flip this bit!")

I still haven't found a pithy way to describe the limitations of this principle. Obviously, frameworks are helpful and also fail this principle, so even this principle has exceptions. But are you going to be so arrogant to believe your abstract extensible change will be adopted by all your fellow teammates in the future?

<comment><USER6> I think the core problem is that it assumes you know what part of the software will need to be changed. But you often don't so you end up with code that is too rigid in places that you need to be flexible and too flexible (i.e. complex) in places that don't need it.

</comment></comment></comment><comment><USER7> Less code, loose coupling. Do one thing and do it well. Keep the external API simple.

It's always easier to change a small thing instead of a large thing. So make a small thing, and only make it a big thing if you absolutely have to.

I think my favorite recent HN example of this was that article where Discord rewrote their "unread message count" service in Rust. They were able to make a huge change to a critical section slowly and incrementally because it was loosely coupled. The programming language they chose didn't matter, because it could just be changed. The implementation didn't matter because the consuming code didn't know about any implementation details. The change happened and all the other teams had to care about was that there weren't weird latency spikes anymore.

<comment><USER8> > Less code, loose coupling. Do one thing and do it well. Keep the external > API simple.

> It's always easier to change a small thing instead of a large thing. So make > a small thing, and only make it a big thing if you absolutely have to.

this is along the lines of what i was going to suggest. i prefer to code everything such that it does just one thing that is appropriately at the level or context it sits at.

a function should just do one thing and have reliable outputs based upon inputs. a class should represent one thing. class methods should do one action. modules should collect functionality that does a thing. processes and servers should do a thing. and so one. if you build your system out of things only doing the thing they say they do, then it becomes clear when they're being changed in incorrect ways.

</comment></comment><comment><USER9> Separate _policy_ from _mechanism_. [1] I usually reframe this as separating the _what_ from the _how_. Back in the 80s and early 90s people would commonly call this "data driven design" (this is distinct from "data-oriented design" which lives more in the _how_ ).

One area you can quickly see this in action is with user interfaces. So many modern applications construct their UI tediously by coding each component and all of the aggregations by hand. If you take a step back, it's usually very easy to see that the configuration of the UI is just data. Why not just build one layout "engine" and feed it data to generate your UI? The engine part can use whatever hotness you like, but you only have to write that code once. The configuration of the UI (the policy) is what changes frequently (the business requirements); not the mechanism underneath. (This doesn't mean you won't have to change the mechanism, you will. It just requires change at a much slower pace and the changes are bound within the context of the mechanism itself.)

This approach separates layers of a system which have different change vectors and velocities. The mechanism tends to have a much lower rate of change and it's where we programmers like to live. Build tools for "the business" \-- whatever that means in your context -- so they can maintain as much of the policy as possible.

If you think through designs like this; however, you will realize that our modern fascination with massive "scaling" of teams is no longer attractive. This may explain why it has fallen out of favor.

[1] [https://en.wikipedia.org/wiki/Separation_of_mechanism_and_po...](https://en.wikipedia.org/wiki/Separation_of_mechanism_and_policy)

</comment><comment><USER10> Documentation (document the "why"). Loose coupling (this goes for databases, programming libraries, languages and paradigms, and operating systems as well as function interfaces). Design data structures first. Make everything a program. Make every program a filter.

 _Those who don 't understand Unix are condemned to reinvent it, poorly_. - Henry Spencer

Many architecture tips here: [https://github.com/globalcitizen/taoup](https://github.com/globalcitizen/taoup)

</comment><comment><USER11> The answer to your question is essentially the entire field of software architecture and to some degree even software engineering itself.

Thus there aren't many simple always-applicable tips. Every tip requires experience to know when you apply it. Any tip that doesn't require that experience ends up not accomplishing much.

Keeping things simple is good. But sometimes you do need some abstractions, scaffolding, and structure that sacrifices simplicity but enables the code to grow.

Tests are good. But sometimes code can be so heavily tested that changing the tests themselves is a large maintainence burden when the requirements change.

Abstraction and encapsulation are good. But both add complexity and raise the amount of code someone has to load into their head to understand what's actually happening.

Documentation is good. But writing good docs itself an artform, and docs that aren't maintained well can cause more harm than good.

The best advice I can give is to not seek out "tips". Just work with the best engineers you can find, write code, reflect on it, and trust that your experience and intuition will grow over time. There is no shortcut to mastery.

</comment><comment><USER12> Be as explicit as possible. Use guard clauses. Don't couple things for the sake of less code. Very, very often, repeating yourself is OK.

</comment><comment><USER13> Factor out logical units early and often.

DO NOT try to generalize and abstract until the third time that you are writing something. (Having written it for other companies counts.) Until the third time your guesses about the right generalizations and abstractions generally work out badly.

Focus on simple over clever. I cannot count how many abstract systems that I have seen which were designed to achieve some general purpose reusability. They almost never actually achieve the asked for dream and almost always become a barrier to comprehension by other developers.

FOLLOW ALL STANDARDS IN YOUR ORGANIZATION. Code review. Unit tests. Formatting. Naming conventions. Doing what you think is the perfect thing is almost always worse than staying consistent with other developers.

</comment><comment><USER14> Lots of comments here on keeping this as simple as possible and not over- architecting. This is a good value, but its equally important to add architecture and abstractions before its too late. Software projects become tangled spaghetti messes slowly, over time, by adding "just one more thing" to existing modules and functions until they are large and impossible to fully understand. My simple rule of thumb is this - no file should be longer than 300 lines of code and no function should be longer than 15 to 20 lines of code. If your file or function is longer than these guidelines, its trying to do too many things and its time to break it down.

</comment><comment><USER15> I used to focus on making my code easy go extend. I still enjoy that style in personal projects, but on large teams, I find it is better to make your code easy to delete.

</comment><comment><USER16> Write code for use not for reuse. Write code that is easy to remove, not code that is easy to change.

</comment><comment><USER17> Assume the code is going to be changed by first semester CS students. Dumb it down as much as possible. Don't do any clever tricks. Make the patches as small as possible so they can be (i) easily reviewed and (ii) allow easier bisecting.

Example: if a computation requires some intermediate value, create a new variable with a proper name and assign the intermediate value to it, instead of just inlining it in a bigger statement or assigning it to "res". The compiler knows how to deal with temporary variables like these in an optimal way.

<comment><USER18> This and include conversational comments that explain in plain terms what problems you're solving and why.

</comment></comment><comment><USER19> Most of the responses focus on how you meet the current requirements. However, the most important thing to know is not actually about current requirements, but future ones.

Sure you can assume that all the requirements will change, but then you'll need to make a system so flexible it becomes a nightmare to do anything (just look at JIRA or other software like it, with 100 configuration options for every piece). These systems require vast resources to maintain because there is so much code to make it flexible.

You can also assume the requirements won't change at all, tightly following the spec and optimizing all the edge cases so you have a pristine black box no one can touch.

Finding the happy medium involves knowing which assumptions are likely to change, and which aren't. Usually, languages won't change often, so you can rely on most of those features. Certain well-maintained libraries and APIs won't change much, so those can usually be baked-in too. The business logic around things like pricing, users, analytics, data visualization, and data processing are likely to have changes. My favorite one for web apps with databases is search. The filters very often change and grow, so getting a highly flexible search working is usually a big win for not too much effort.

Note, I've never said always. If you can get knowledge about the business needs you're supporting, you'll have a much better idea of which things need flexibility, and which things don't. The longer the roadmap on a project, the more wins you can get when architecting systems too, as you can set yourself up for easier implementation of future features.

</comment><comment><USER20> Make it easy to delete conceptually

It should be removable in a way that does not break other systems and it should be easy to identify when "it" ends and when something else begins

</comment><comment><USER21> My strategy is make small functions that do one thing then combine this small functions to create larger ones. When a new requirement is added to change the large functions you probably have to change just one or a few of the small functions but many of the smaller functions are unchanged. Also when this new requirements are added you can reuse the smaller functions, most issues I had to fix is understanding code that evolved over time and ended up to be a giant function that does too many things , with many branches.

Also make the code easy to read and understand, have good naming convention for the small functions and variables, add comments if you have to do something unusual (like workarounds for weird quirks or bugs) so it makes sense 3 months later when you read the code again and you forgot most of it.

</comment><comment><USER22> Whole books have been written about this. I use the following rules from [1] myself. I like them because they definitely put some constraints on my coding which I like. It forces me to think beforehand and gives me (a junior developer) some guidance which I desperately need:

* Write functions/units that are <= 15 LoC.

* Create units with <4 branching points

* Write functions/units with <5 parameters

These guidelines force you to write maintainable code. Always open for discussion. Note that these lessons are lifted straight from [1].

[1] [https://www.softwareimprovementgroup.com/resources/ebook- bui...](https://www.softwareimprovementgroup.com/resources/ebook-building- maintainable-software/)

</comment><comment><USER23> I'd say write the least amount of code you can.

While you're adding a feature it's always tempting to go down the "what if" route and make some kind of crazy interface that is extensible and able to accept plugins and all that. The problem is you're likely making it extensible in ways that turn out to be useless down the road.

Just code the least amount you have to in order to achieve the current goal. That way down the road it's easy to delete what you did, or code up some changes to it. I personally think the worst thing you can do is write code that is all things to all possible future features.

<comment><USER24> This is probably the most valuable advice. Less code has less bugs, is easier to read, test and document.

</comment></comment><comment><USER25> This is how we do the API -

\- Database models should contain all the possible mechanisms/methods for data I/O

\- Data Transformation utilities/ helper functions that do one job well, that is - sort, filter, validation, whatever \-- -- If an API is using (more on API below), utils become immutable code

\- Finally the API level \-- -- treat the API code as immutable, once shipped \-- -- The code should look like a pipeline of functions \-- -- -- eg: serialize(...) validate(...) filter(...) db(...) \-- -- -- need not be chained \-- -- new API version, new router, new routing logic

\- Review API with an intent to extract out any possible util methods. final API methods should look like a series of data transformation functions

\- Overtime the utils would become extremely messy, but the APIs would be very clean

\</comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment>

The layer running business logic would be the most interacted with layer, if you can keep it clean, then you can keep frustration low in your fellow devs. A lot of people can work on the API level, irrespective of their experience.

Utils and Models should be managed by more experienced devs. Rate of change in Utils and Models is quite low as compared to the rate of change in the API levels.

\</comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment></comment><comment>

Not sure, I guess I am writing something very trivial and obvious.

</comment><comment><USER26> In codebases I've worked on, the biggest culprits that make maintenance and modification difficult are

\- functions that do several different things

\- tight coupling

\- implicit behavior

\- too much indirection

\- too many thin custom wrappers

Often several of these come together when an inexperienced developer factors out everything they can (over-eager DRY) but still tries to keep a few highly specific things "easy". One thing I see often is modules or classes that wrap a standard library, _adding_ code essentially _removing_ features in the interest of "ease-of-use".

I think you can write better code if you write code in multiple passes: only write what you need _right now_ , and use the code as-is between each pass. With that approach, you'll gain some real intuition about what is easy to read and modify, which is much more helpful than someone's list of tips.

That said, I've found that writing simple explicit functions that take arguments and return a result can get you pretty far. Same for class constructors and methods, API endpoints, etc. Try to avoid writing "convenience" functions or classes when just using the library directly with some arguments would suffice. In other words, boilerplate probably isn't as bad as you think, and the indirection/implicit behavior/tight coupling is often worse than the boilerplate.

</comment><comment><USER27> Here is my personal checklist:

* If in a loosely typed language go way out of your way to ensure conventions are in place to identify things by data type. TypeScript has completely changed how I look at JavaScript particularly its use of interfaces for defining objects and data structures.

* Limit your use of dependencies as much as possible. In my current personal project I am down to 1 dependency. Dependencies will weigh a project down and prevent nimble shifts of direction. This also includes frameworks and tools.

* Write good documentation and keep it up to date. Automate the authoring of documentation where you can so that it stays up to date with less manual intervention.

* Isolate concerns as much as possible so that a feature can be deleted and replaced with as little effort as possible.

* Keep things simple. This requires lots of extra effort both in planning and refactoring. When there are fewer pieces and everything is as uniform or consistent change requires far less effort and leaves far less dead code in its place.

* Don't abstract things for convenience or easiness. Abstractions are incredibly helpful when they result in simplicity (fewer pieces and fewer ways of doing things). Absolutely don't use abstractions as a means of being clever or for vanity reasons. Then you just have extra code and the larger a project gets the harder it is test and change.

* When other people want to impose their opinions on you push back until they come back with test automation and/or strong provable evidence of a better way of doing things. If they still try to impose their opinions on you, and this will happen, kindly tell them to go fuck themselves. So much of the stupidity in programming comes from baseless irrational subjectivity.

* Test automation. Its not about how you test, but about what you test. There is a lot of nonsense out there about how to test. In my current personal project I have automation in place for code validation, compile checks, command tests in the terminal, service tests. Soon, as I figure it out, I will be adding test automation for user interaction and user data storage. However you are able to execute all the kinds of tests you need just do it. The goal is to promise your software can deliver a feature and prove it with test automation and then add more tests later to cover for edge cases you did not consider.

</comment><comment><USER28> Keep a document of your design decisions. It's very tempting to hack away to get things done, but human memory is short and feeble: you will forget why stuff was coded the way it was faster then you think.

I usually keep a Google Docs page open where, as I write the code, I update the documentation. It keeps things consistent and flexible, and much easier to go back and refactor.

<comment><USER29> I think this is key when you are working with code you don't touch every day.

On code you touch every day one can easily make changes since everything is fresh in one's mind.

When you are working with a code base that you touch once a week or even for a few hours/minutes every day having notes about what you did, why and perceived next steps at the time is crucial and VERY useful.

Another strategy I found useful is to try and be consistent with your choices even if they are not fantastic.

For example: all your tables are named like tbl_entityNam. Even if prefixing every table with 'tbl' is a bad idea, the consistency in keeping it will be useful later when you need to work with that code.

</comment></comment><comment><USER30> Easy to change code is code you understand a year later.

This includes:

Easy to understand variable and function names. IDEs make autocompletion possible so don't fear long names. MyEasyToUnderstandFunction() is better than MyETUF().

Function names should describe what they do. CreateOrder() is better than NewOrder().

Make sure you don't use global/public state in any object or component. Public state is one of the biggest sources of failure and bugs. If you can, don't use it.

KISS: Keep It Simple Superstar!

But maybe the most important (for me): use separation of concern and context. This always helped me a lot. For example: if an email must be sent when a new order is created you can put the email code directly after the order creation code. This will ofcourse work and might even be valid code. But the component that creates the order should not be bothered with how emails must be sent. If you separate this, it will help you a lot to create maintainable code.

</comment><comment><USER31> Maybe a better question is this: how do you write code that does the most possible to prevent a maintainer from screwing it up?

It sounds like the same thing, but acknowledging that mistakes happen no matter what and trying to focus on preventing them is something much more tractable that trying to come up with the perfect thing that can be understood right away.

For instance, I used to be a fan of long variable names that say exactly what they do. I still am, but only in certain situations. In fact, I'd argue that using very descriptive variable names in the wrong situations can actually make the code less maintainable, not more.

This takes us naturally to a discussion about what works, why it works, and under which circumstances it might not work (or actually hurt), which is probably a much more productive conversation than something along the lines of "how do you guys think the best way to code is?"

<comment><USER32> > Maybe a better question is this: how do you write code that does the most > possible to prevent a maintainer from screwing it up?

By writing tests, that's the only way.. I remember recently writing the test two weeks after I added the feature, the feature was _already broken_!

The difficulty is that maintainers are very creative in their way to break your code so it's difficult to write 'thorough' tests.

<comment><USER31> Yeah. That would be my answer if I had to pick just one. Tests should give you immediate feedback if you're wrong. They might not tell you exactly what to do. I think there's a bit more to the story than just tests, or I wouldn't have been so elliptical in my comment.

</comment></comment></comment><comment><USER33> The first thing we did when we started building our ml platform was to go with a plugin architecture. All applications are simply plugins. Data connectors are plugins.

We do consulting work and have to build custom solutions for our clients. Once they were satisfied with the models, they'd ask for an application to use these models: user management, data uploads, etc.

We used to build a custom solution for each client. It was very hard to change these solutions when client's demands changed, and it was almost impossible to reuse that solution with another client.

We took advantage of a decrease in activity to build a platform where things would be plugins. The time series forecasting application is a plugin, with endpoints you can tap into with authorization tokens.

The recommender system is a plugin, the notebook application is a plugin, etc.

Now our notebooks are "Published" in one click, which generates an AppBook a business person can interact with by changing the parameters. The runs are tracked (params, metrics, and models) in case domain experts tweak parameters that result in a better model than we have. The models can be deployed to endpoints you can invoke with generated tokens.

The major benefit is that when a new member joined the team, they had to understand the whole code base to be able to contribute or add something. Now? They don't have to understand anything, only the application they're building. If they want to render it on the sidebar, they just have to add a `sidebar.html` with the proper icon and route. If they want to show it in our appstore, they just have to add a file with the proper icon, and our platform handles the rest. It will discover the application, load it, etc.

An administrator can even load an application as a zip file. The platform will consume it, install its dependencies, load it, and activate it.

We want the product to be easy to add to and modify its behavior with config, instead of changing the code and we work to do just that.

</comment><comment><USER34> Beyond having good testing, don't try to write it to be easy to change, write it to be good code.

You should try to express problems elegantly, and that will help make some changes easy. That's nice when that happens, and it does happen quite a bit. But many changes will still not be straightforward.

Generally, write the code to do what it's meant to do, and when it needs to change, rip it out and rewrite it.

It's shockingly easy to write something that's concrete and later realize "I need two of these" and then quickly factor out the common functionality.

Especially, don't kludge things. The problem with "easy to change" is it means "easy to kludge just one more feature on here." That won't remain easy to change. Refactor aggressively and your code still won't be easy to change, but it won't become a kludgey mess that's hard to change, either.

</comment><comment><USER35> Start with the absolute most simplistic structure, or no structure. Starting from "Hello world" is OK! (ie. starting in a new programming language)

Keep in mind you can always start over, especially if you componentize your work!

As you prototype, or just design by drawing on whiteboard, learn your domain and gain ideas what would improve your initial lack of design.

Iterate and refine when cost effective to do so, not sooner. If still on whiteboard, you could benefit from implementing rapid no-code solutions before diving into any code at all!

Resist committing to structure, unless your experience and insights into the domain require it and you see clear benefits from doing so. Deconstruct structure you find bring unnecessary complexity, as well as build on structure when doing so clearly brings leverage.

Care for your code.

</comment><comment><USER36> Writing code always involves starting with assumptions about how the code is going to be used. Extensible code is really just code that includes in its design assumptions that a part of it might need to be switched out or accommodate something more in the future.

Sometimes its easy to predict how your code may need to be extended if you give it a bit of thought. In those cases, it might make sense to allow for easy extensibility. This is pretty rare though. Most times, you can't really predict what will be required of the code in the future. In those cases I prefer to bake as few assumptions into the code as possible, so when someone else is extending it in the future, they spend as little time understanding your code.

</comment><comment><USER37> Simple things go a long way. An easy one is abstraction.

If you are writing an interface to another system of any kind (DB, API, etc.), abstract that interface one layer from other parts of your app. Then when that other thing changes you are less impacted.

An example: if your organization has multiple apps, it might sound easy to just let app #2 have direct DB access to app #1's DB. Take a little time and build a simple API in app #1 to get at the data, then when you change column names, etc. as long as your API layer doesn't change app #2 won't require changes. You don't have to build a fully RESTful API to all-the-things if it is just one table. Iterate.

</comment><comment><USER38> My usual go to is every time I write an interface, I think to myself: "How easy would it be to explain this module to another developer?"

For every additional change, I look at the module as a whole again, and keep thinking "If we got a new hire, how easy would be for the person to understand this in the bigger picture?"

Understanding is all about mindset. If part of the code starts to do too much, then other developers are likely to make incorrect assumptions of the logic behind that piece of work. The small mistakes slowly compounds over time, and if not taken care of, the whole project becomes un-maintainable.

</comment><comment><USER39> Write however you want to write, choose whatever best practices available, any design pattern, design principal. Just add lots of comments, as many comments as possible which talks about what each line is suppose to do. If you are using a pattern, write at the start that this is x pattern used for this scenario. if you are branching the code, which scenario each branch will take care of.

At the end, if you comments and logs are complete and self explanatory, any one can come in and change the code or debug the code.

</comment><comment><USER40> Keep code as simple as possible, shun abstractions until the refactor stage, adopt a language / toolchain that enforces a modular / functional discipline. EDIT: also, reading the comments here - absolutely shun DRY, be very explicit with code and don't try to couple anything until its absolutely clear that is the way to go. This in my opinion is the true mark of somebody experienced with codebases that grow unmanageable vs the less initiated -- the latter are always trying to reduce code by coupling things into abstractions, the former wait until it absolutely makes sense.

</comment><comment><USER41> The biggest bang for the buck for me has been using functional techniques where immutability is perhaps the most important thing. A good way to get started is to make a project with react/redux.

</comment><comment><USER42> Keep it short and succinct.

</comment><comment><USER43> Think of your tests as a consumer of the software you create. You will know it's easy to test if your component does not take much setup. If you have to create all kinds of different objects to get a test to pass, you've built a coupled component.

Said another way: Making an easy to understand interface to your software should be your top priority. Make the interfaces within your public interface as easy to understand, etc., all the way down.

Easy to test: Easy to understand. That makes it easy to change.

</comment><comment><USER44> Extensible doesn't mean the code itself gets changed often. It would help to read up on SOLID [1] design principles and books on software development. Actually implementing SOLID would come by reading good code, getting mentored and from experience.

[1]: [https://en.m.wikipedia.org/wiki/SOLID](https://en.m.wikipedia.org/wiki/SOLID)

</comment><comment><USER45> \- Don't write code until you need it. This results in less code, which is directly correlated with ease of change. \- If you write lots of separated classes but then use them directly inside other classes, you've defeated the point. When you depend on something, pass it in instead of directly referencing, if possible. \- keep methods less than 5 lines, classes less than 100 lines.

</comment><comment><USER46> Just one tip: Comment your Intent, not the code.

Anyone can read the code and see what it does.

No one can read your mind to figure out what you intended it to do.

</comment><comment><USER47> "Write code that is easy to delete"

[https://programmingisterrible.com/post/139222674273/write- co...](https://programmingisterrible.com/post/139222674273/write-code-that-is- easy-to-delete-not-easy-to)

</comment><comment><USER48> Here's a couple of mantras to write clean code:

\- Code is written once and read _at least_ once, have empathy for the readers...

\- If code cannot be understood, it cannot be changed safely...

\- Less dependencies on other code, makes code easy to understand...

\- The smaller the _context_ is, the easier it is to understand the code...

</comment><comment><USER49> Keep files small and use the file system to your advantage: it's much easier to organize information in a tree than in a string. Keep code for components together (e.g. no "controllers" folder). Write twice as much documentation as you think you need.

</comment><comment><USER50> Keep it simple and don't allow any technical debt to build up. I've worked in run down legacy systems and in clean ones. The run down ones are impossible to change without breaking. The clean ones are just as easy as a green fields project.

</comment><comment><USER51> If this were an easy answer, software devs would not be paid as much. Read some books about the topic, then write a lot of code, then change a lot of that code, and learn from your experiences regarding what was easier or harder to change.

</comment><comment><USER52> To add to the list - I just watched this great video on composition vs inheritance: [https://www.youtube.com/watch?v=wfMtDGfHWpA](https://www.youtube.com/watch?v=wfMtDGfHWpA)

</comment><comment><USER53> Separate interface from implementation. [1]

[1] [https://en.wikipedia.org/wiki/Interface_(computing)#Software...](https://en.wikipedia.org/wiki/Interface_\(computing\)#Software_interfaces)

</comment><comment><USER54> In a few words?....'Don't write the code in the first place'. Yes, follow best practices of modules etc, but in general write a lot less code. This is harder than it sounds, and often requires multiple rewrites.

</comment><comment><USER55> I would suggest reading Head first design pattern, apart from design patterns the book also explains how 'change' is inevitable in software development and how to design the software extensible and modular

</comment><comment><USER56> In very simple terms make small pieces of untangled code. Think in terms of small lego blocks that connect and can be replaced and modified independently instead of tangled webs of logic.

</comment><comment><USER57> Comments and empathy for others and your future self. That means minimalism and lots of comments to remind yourself what you were thinking when you wrote it, who calls it, why, etc.

</comment><comment><USER58> Your asking about modular code where modules can be changed or swapped.

The functional paradigm is the most modular style I've seen. Modularity is a side effect of immuteability.

</comment><comment><USER59> If you can, use state machines, they provide a level of effective encapsulation otherwise hard to beat.

This menas ability to change specific behaviours wih very limited side effects.

<comment><USER32> In theory yes, in practice I'm not so sure: I've seen state machine implementations which were ten times more code than the few if/else/for loop needed.

Sure you can draw a pretty state machine diagram, but is the code really easier to read and maintain? I'm not sure.

</comment></comment><comment><USER60> TDD is the key.

By using TDD methodology (structure your code to support it, not necessarily obey the principle head to toe), your code will be 80% of the way there.

</comment><comment><USER61> Write shallow code, code that is the simplest solution for the problem

If the word "architect" springs to mind then you are doing it wrong

</comment><comment><USER62> Make code easy to change by changing it often, thus forcing you to either structure it so that it's easy to change, or die

</comment><comment><USER63> Optimise code for Deletion.

If it's easy to delete, then it's easy to replace.

And if it is easy to delete then it should be naturally loosely coupled.

</comment><comment><USER64> try to anticipate where the code may have to change, and with what frequency. For example how likely is it that a modification to handle new file specification will be required, or how often would you have to integrate new authentication methods. how often would you need to give things a facelift to keep up with marketing trends.

</comment><comment><USER65> A lot of people say "You could write this X/Y block in one line" or "You can simplify this".

A lot of the times they don't mean simplify, they mean compact code.

I write verbose code, as explicit as possible. Sometimes it looks like it was written by someone just learning to program. And that's on purpose to make the code as easy to understand and change as possible.

TL:DR: Be skeptical about code "simplification" and don't fall on using fancy language features when if/else conditions do the job.

</comment><comment><USER66> Encapsulate the concept that varies.

</comment><comment><USER67> high test coverage and functional purity as much as possible.

don't get trapped by being "too DRY"

</comment><comment><USER68> Keep code Simple and Unified.

Keep data and logic separate, data-driven development.

Adhere to the "standardized data interface specification" and use pipeline- functions to manipulate data from the initial state to the final state.

Pipeline-functions conforming to standardized data interfaces are easy to change, replace, and insert extensions.

In the web model, It can be easily replaced as long as the components that conform to the http data specification. For example, Clojure web application model:

\- product standard (data interface): the req-map and resp-map of the ring

\- warehouse: the ring

\- workshop: the pipe functions on both sides of the C/S, and Raw materials (hash-map) are transferred to each other through warehouses through interactions.

[https://github.com/linpengcheng/PurefunctionPipelineDataflow](https://github.com/linpengcheng/PurefunctionPipelineDataflow)

</comment><comment><USER69> Don't repeat yourself.

There is an objective way to tell if design A is better than design B, and that is to measure how hard it is to make changes. You have to build that into your culture and not optimize for something else, or do things because somebody thinks that is the way to do it.

A big problem in current architectures is that what seems to be a small change (say, add a "cell phone" field next do a "home phone" and "office phone") field often requires a number of little changes in widely separated code:

* a database schema change * changes to database queries * changes to a back-end API * changes to a front-end Javascript app * changes to an iOS mobile app * changes to an Android mobile app

Conventional system design means that what looks like one change to management is actually at least six changes, which might affect that many source code repositories, etc.

An ideal design would let you create a feature by writing all of your code in one place. Of course this would require a big change in how applications are structured and built, but it could lead to a durable advantage. See

[https://en.wikipedia.org/wiki/Software_product_line](https://en.wikipedia.org/wiki/Software_product_line) [https://en.wikipedia.org/wiki/Feature- oriented_programming](https://en.wikipedia.org/wiki/Feature- oriented_programming) [https://en.wikipedia.org/wiki/Low- code_development_platform](https://en.wikipedia.org/wiki/Low- code_development_platform)

The biggest barrier to the above I think is that when you talk to a team they always have shiny objects that they can't live without. Maybe they think functional programming is great (yeah, you can handle errors with monads, but you can drop errors on the floor just as easily as you can with exceptions, return codes, etc.) or that immutability solves everything, JDK 13 is the best, whatever. So people are thinking about everything except the thing that management will care about which is long-term sustained productive development.

<comment><USER70> > Don't repeat yourself.

And also do repeat yourself. Consistency (patterns) are a factor in reducing errors.</comment></comment>


NYT Cascade visualization - <AUTHOR> http://WWW.nytlabs.com/projects/cascade.html

<comment><USER2> This could be a Very Big Deal in the Marketing/PR 'industry' where it is extremely difficult to quantify performance of PR departments and individuals. I can easily envision a "Cascade score" of a particular press release or press conference being a hard metric of influence & success.

If I was running a PR department or agency, I'd want this application as soon as possible, at any practical price.

<comment><USER3> Yes this tool could be very helpful to many. I could see it working very nicely with Klout. And taking it a step further sales departments could use this info to see who their 'target' is influenced, which could be very helpful as well.

</comment></comment><comment><USER4> They have this installed on the 28th floor by the elevator bank over 4 or so large screens. Its pretty damn awesome. You can access it via your iPhone on the network and control it. I wish I'd had a chance to play with it more.

</comment><comment><USER5> Jer Thorp is the guy who built the visualization tool. He also designed a tool to help layout the names on the 9/11 memorial.

He's got other interesting stuff at his blog, <http://blog.blprnt.com/>

<comment><USER4> He didn't do it alone, but he was a big part of it.

</comment></comment><comment><AUTHOR> via <http://processing.org/exhibition/></comment>