[HN Gopher] Tao of Node - Design, Architecture and Best Practices
       ___________________________________________________________________
        
       Tao of Node - Design, Architecture and Best Practices
        
       Author : kiyanwang
       Score  : 100 points
       Date   : 2022-03-27 09:24 UTC (13 hours ago)
        
 (HTM) web link (alexkondov.com)
 (TXT) w3m dump (alexkondov.com)
        
       | Morzaram wrote:
       | Wow this is so well written. I've been struggling with finding a
       | method of organizing code and things. Coming from a rails
       | environment I struggled finding a layout that wouldn't easily
       | turn to spaghetti.
       | 
       | Thank you for taking the time and writing this!
        
       | jackblemming wrote:
       | This is good stuff, but very little of it is specific to node.
       | It's more of Tao of Web APIs that happens to use node as the
       | example language.
        
         | yangcheng wrote:
         | Agree, I find most of the content applies to my golang services
        
       | lelandfe wrote:
       | I'm going to need to read through this a few times to give my
       | thoughts on the opinions but I have to say:
       | 
       | Thank you for providing code examples of both what not and what
       | _to_ do. So many of these architectural principle articles just
       | stay floaty and academic instead of having practical examples.
        
       | dyeje wrote:
       | This reminds me of that Python / Django (can't recall)
       | architecture guide posted a while back. Most of it is just
       | generally good advice for web service architecture, regardless of
       | language or framework. The tooling section here gets more into
       | preference territory though.
        
         | stochastastic wrote:
         | This guide?
         | 
         | https://alexkrupp.typepad.com/sensemaking/2021/06/django-for...
        
       | sagarjs wrote:
       | This is a great resource. I have come to the same conclusions
       | after years of coding web apis and it's very helpful to have it
       | written down.
        
       | ErikAugust wrote:
       | "To this day, it's hard to find two Node applications that are
       | structured similarly."
       | 
       | I've seen a few Express applications that were mostly the same.
        
         | BiteCode_dev wrote:
         | With auth, perms, db setup, templating, validation and
         | migrations ?
        
       | ivailop wrote:
       | Great work, Alex!
        
       | yes_but_no wrote:
       | Great article. I also suggest watching Casey M. recent video[0]
       | about Conways Law. How organization in your company determines
       | what you can/will do and how organization of your code follows
       | the same principles.
       | 
       | Starting with just the handlers and introducing layers as you
       | make sure its time is great way.
       | 
       | [0]https://www.youtube.com/watch?v=5IUj1EZwpJY
        
       | fatbird wrote:
       | This is a digression, but the book starts by saying that it's a
       | benefit to the developer to have one language front and backend.
       | I've been working on node/JS web apps for several years now, so
       | this is my lived reality, but I _don 't_ like that it's the same
       | language front and backend. Just as a web page with HTML,
       | JavaScript and CSS lets me mentally separate the different
       | aspects of the front end and context switch more easily between
       | them (I'm never confused about what I'm addressing), I've found
       | having JS both front and back end (separated by a GraphQL API) to
       | require being more conscious of my environment. There are subtle
       | differences between Node and the browser VM; there are different
       | concerns with resource usage and concurrent operations.
       | 
       | When doing React I refused to follow Facebook's lead and relocate
       | styles into the code. In my mind it just crowded the JavaScript
       | and made for more code where multiple concerns where colocated.
       | Am I the only one who felt this way?
        
         | cies wrote:
         | > the book starts by saying that it's a benefit to the
         | developer to have one language front and backend
         | 
         | I also cringed at that premise. JS sucks a lot, having it on
         | both sides would make things worse. Yes TS can help here, but
         | only so much. You cannot make up for a languages design
         | mistakes by bolting on a type system. Also: making a SPA-like
         | browser app makes thing think about the state of the
         | application twice! This comes at huge cost. Simple page-to-page
         | applications with SSR are waaaay easier to build an maintain.
         | 
         | When I do browser apps I prefer a strong-typed API spec from
         | which I generate (1) client libs and (2) server stubs. This
         | gives me some safety guarantees over the API barrier.
         | 
         | Using a language like Elm with an "elm-graphql" generated
         | client lib is a bliss. Compile gQL queries in a type safe
         | manner: if it compiles it runs. I feel there is soo much more
         | "tao" (simplicity, peace of mind, zen, less moving parts) in
         | this approach than in the JS-article I just read.
        
       | Madeindjs wrote:
       | This is a really great resource. All of theses tips are
       | implemented in Nest.js framework. I can't recommend enough to
       | give it a try, it'll force you yo have best practices.
        
       | qxqdtqutwtv wrote:
       | This was really great and closely matches how we do it as well.
       | 
       | For people who generally follow this approach, what's your take
       | on structured logging transaction traces, or more generally,
       | propagating request-contextual information through the call
       | stack? TFA seems to prefer a res.locals approach, but it's
       | coupled to the framework in a way that the article avoids
       | elsewhere, and needs manual propagation beyond the express
       | handoff. I've seen these alternatives:
       | 
       | One team in my organization uses explicit context objets that get
       | passed to every function call as the first argument, in a style
       | very similar to what is idiomatic in Golang. I find this to be
       | viral and not to compose well with third-party code that ends up
       | calling your own code, which is rare with npm modules but
       | somewhat common with company-internal libraries.
       | 
       | Another team was an early adopter of node async hooks to create
       | the equivalent of a continuation local storage, with cls-hooked
       | at around the time of node 8. They reported several problems that
       | were implementation related, but seemed to prefer the developer
       | experience of the approach, and context was preserved through
       | third party code just fine. E: (Apparently this now ships
       | standard in node with AsyncLocalStorage)
        
       | mrloba wrote:
       | Very nice, I found myself nodding along with almost everything in
       | this post. One thing I do a bit differently is that I usually put
       | the API handlers in their own module (they're usually just a
       | couple lines of code each), along with domain-to-api model
       | transformers. This is because I often have various worker entry
       | points as well, and it's nice to keep the domain logic separate
       | from all the different entry points. I also like to keep all
       | routes in a single file. I don't like to hunt down the full route
       | path across a bunch of different files, and I like to be able to
       | get a full overview of the API in one place. Just different
       | tradeoffs I guess
        
       | zelphirkalt wrote:
       | > It grew from a questionable technology to one used for critical
       | infrastructure in many large enterprises. It performs incredibly
       | well for high-volume IO operations with a much lower code
       | complexity than languages that rely on multi-threading.
       | 
       | Well, that is not where one usually uses multi-threading (OS
       | level threads), as the threads would possibly be bottle-necked by
       | IO and there would be no use of having the overhead of multiple
       | threads. IO does not become magically faster by using multiple
       | threads.
       | 
       | Which languages "rely" on doing that? Many popular languages have
       | green threads and many have asynchronous concepts. I would
       | assume, that programming language designers are aware and do not
       | prescribe using multiple threads for IO of multiple concurrent
       | "execution units".
       | 
       | Note: Little typo in the TOC: "Cetralize error handling".
        
         | morelisp wrote:
         | The complete failure of early Java iterations of green threads
         | and fall back to 1:1 OS threads, along with terrible async
         | ergonomics in Java, meant a lot of backend software was based
         | on real OS thread e.g. per connection. The story was similar in
         | C/C++ for different reasons - the details of select and its
         | various extensions were some of the least portable parts of
         | otherwise POSIX interfaces. And on the lower end e.g. Python
         | also relied on OS threads unless you built your entire
         | application around one of the early async reactors.
         | 
         | The real success story behind node is libuv. It's a shame it
         | was married to such a mediocre language, but that language did
         | have some of the least-bad async ergonomics at the time (nearly
         | by accident - client-side JS _had to_ yield to the browser
         | frequently, and the language was mostly designed to run small
         | code blocks instead of application lifecycles).
        
         | erikpukinskis wrote:
         | The author is saying "green threads" and "asynchronous
         | concepts" are more complex than "everything is synchronous".
        
       | is0tope wrote:
       | This was a great read! I've been using node on and off for
       | personal projects for some time, and also always hated the fact
       | that it was very unclear how you should structure a project. At
       | least with django, it was clear. This provided a really nice set
       | of techniques that I will be sure to put to use. Thanks!
        
       | deltaonefour wrote:
       | The tao of node?
       | 
       | It reminds me of this story about a secretive master kung fu
       | artist who perfected his technique but taught his style to no
       | one. Yet the master still wanted to document his style in a kung
       | fu manual. So he did, but as a security measure, he wrote
       | everything backwards so that anyone reading it would get the
       | wrong set of instructions. If a move involved a user blocking a
       | hit with his arm he would write down that the hit should be
       | blocked with his foot. Every move was a complete reversal of what
       | should be done.
       | 
       | One day a thief stole the kung fu manual with the goal of reading
       | it and becoming a great kung fu master. The thief read the manual
       | day and knight and practiced just as much. And guess what? the
       | thief became an incredible master surpassing the original author
       | himself. Nobody could figure out his hilarious style, when you
       | tried to punch him in his face his foot would immediately come up
       | to deflect the punch. Everyone was WTF? How does this shit work?
       | The thief ended up founding a kung fu school and taught everyone
       | this style... proliferating the backwards art all across China,
       | much like the same way Node has proliferated across the world.
       | 
       | I made the last part up because I thought it would be a more apt
       | analogy. What actually happened is the thief went crazy because
       | the the backward moves caused his chi to spin in the opposite
       | direction... driving him insane. Anyway, this is what the Tao of
       | Node reminds me of. I should also say so does the Tao of CSS and
       | HTML and maybe the Tao of the entire web reminds me of this
       | story.
       | 
       | Do these things really need to be associated with Tao as if it's
       | some great art or philosophy? Feels a bit pretentious, but that's
       | just me.
        
       | lmeyerov wrote:
       | We have generally followed that for years, this is great! A few
       | big missing areas:
       | 
       | - node is also often the best for - 'backend for your frontend' (
       | batching/caching, ...) which adds a bit more complexity
       | 
       | - structured logging should really be tracing given the heavy
       | async + services nowadays
       | 
       | - This architecture is normally done as part of some scalable m:n
       | mapping, which is alluded to, but can be a full article to itself
       | (tools, patterns, manual/auto operations, ..)
       | 
       | We have been moving Graphistry's regular stateless web backends
       | to python as it converges with node on async but is easier to do
       | our GPU + AI data services (and other reasons).. but been
       | generally keeping our 'backend for the frontend' parts here. This
       | could have been part of a primer in our internal docs, so bravo!
        
       ___________________________________________________________________
       (page generated 2022-03-27 23:01 UTC)