Hacker News new | past | comments | ask | show | jobs | submit login
The Case for ‘Developer Experience’ (a16z.com)
186 points by PretzelFisch on Sept 25, 2021 | hide | past | favorite | 73 comments



One downside I've observed from focusing on DX: We have too many single page apps / Jamstack sites, where the default is to send the entire application in Javascript bundles, and do little to no HTML over the wire. This is inherently bad for performance and especially bad for mobile. It's why the Jamstack mascot is the loading spinner.

The much better solution, SSR first with optional client hydration, takes more developer work and more cognitive overhead. It's much easier to write a React application and not worry about server side specific data fetching to do universal rendering, even though that's the strongest option for performance. Next.js is bringing us closer to the DX of enabling SSR first by default, but it's not there yet and many people use Next.js only for SPAs or static rendering, and miss the point that its main power is universal/SSR.

My main takeaway is that DX is important when it introduces the right abstractions that are also end user focused.


With webpack you can use module federation to share code and reduce bundle size for micro-frontend applications. There are other ways to make your application bundle smaller.

I spend a lot of time optimizing performance at work, both for UX and DX. It is common on HN to bash on large bundle sizes of SPAs, but in reality this not a problem unless users are on IE. At work, I often work tirelessly to reduce the amount of dependencies and bundle size, but I know that this would not make things faster, just more maintainable.

For UX perf killers are IMO:

  - rendering large number of deeply nested dom nodes and doing repaints and reflows.
  - large data fetches and storing huge number of objects in memory.
  - slow/flaky APIs, in many cases slow backend is main bottleneck, JS is plenty fast
  - silly animations, bad design that force clicking and multi stage workflows. 

For DX perf killers

  - micro-something. Micro services/frontend in organistions without deep pockets.    
  - special snowflakes internal abandoned framework that only two people in company know
  - lack of dedicated people for tooling and dev infrastructure
  - lava layer design pattern, multiple competing technologies used within same codebase/product.


> It is common on HN to bash on large bundle sizes of SPAs, but in reality this not a problem unless users are on IE.

This is dangerously wrong. Large bundle sizes are a huge problem on slow Android phones (and almost all Android phones in real-world use are slow).

Even in the US, if you walk into a cellular store and ask for an affordable phone, they're going to give you a device that will take 7-10s to download, parse, and execute a 3MB JS bundle, even over wifi. (The parsing alone will kill you!)

(And if you're in a developing economy? That "affordable" phone is the best phone you can reasonably buy with a month's wages. The median phone is even slower!)


In US 55% of people carry iphone. Depending on app, people with affordable phones are not your users (b2b).

Browsers would cache parsed javascript. More likly loading images will be slower.

There are use cases that general perfomance matter a lot but people are obsesing on js bundle size too much.


> Browsers would cache parsed javascript.

First load is important for any public facing site. A 7-10s delay on first load means you’ve lost the game no matter what happens on a second load, because there often won’t be one.

> more likely loading images will be slower

True, but images do not block interaction with your site. In most SPA situations JS will.


> First load is important for any public facing site. A 7-10s delay on first load means you’ve lost the game no matter what happens on a second load, because there often won’t be one.

I hear this said a lot, but have never quite understood it myself.

What industries have pages that are hit by new customers and need to be a big complicated SPA?

Any SaaS can have a landing page/login page which it can use to background load assets needed for the service itself. And if someone already knows of and wants to use your service they'll wait a few seconds.

Online shops maybe?


Yeah, online shops is a big one that comes to mind. But it’s more connected to this unnecessary proliferation of SPA sites that have no business being set up that way. Some news sites are like that, for example.


> - special snowflakes internal abandoned framework that only two people in company know

And remember that today’s darling framework all the internets are raving about is a special snowflake abandoned framework tomorrow that no one gives a damn about anymore.

The corollary to this is that the spice must flow, and the wheels must keep spinning, thus the hamsters^Wdevelopers must keep rewriting everything using the current darling languages, frameworks, and paradigms, restlessly contributing to the ever growing carbon footprint as CI/CD pipelines keep chugging away at each oneliner commit!


> The much better solution, SSR first with optional client hydration, takes more developer work and more cognitive overhead.

I would argue it takes less developer work and cognitive overhead if you're doing traditional SSR.


And the newer HTML-over-WebSockets pattern takes this even further, IMO. In my (admittedly limited) experience, it's hard to beat the DX provided by Phoenix LiveView.


That DX can be futher improved with static type check (e.g. with typescript)


I agree with static typing, but disagree with TypeScript itself. It's a great tool to type existing JS code, but for greenfield projets I find it lacking. Structural typing means that you can't make the difference between an address and a name without resorting to branding, which sucks. Strict null checks are opt in. ADTs are a pain to use.


What is the alternative that doesn’t force you to use a completely different platform/ecosystem (a la Elm)?


There isn't any as easy to integrate as TypeScript. TypeScript isn't flawed because of bad decisions, I think the people behind did an impressive job with it. TypeScript's flaws stems from JS and its ecosystem. And I really can't blame people from trying to keep their legacy systems. JS isn't going anywhere, and of of TS's selling point is that you can easily go back from TS to JS (I'm not sure how true that is, we'll see in a few years).

ReScript (https://rescript-lang.org/) is trying to take another approach, which is being a different language, way simple and easier to use and in my opinion better than TS, but the price is that integration with JS is harder. The community is also small compared to TS. But you can leverage some work already done, as it can consume TS types. This may be what you asked for, as you can still use the ecosystem.


> We have too many single page apps / Jamstack sites, where the default is to send the entire application in Javascript bundles, and do little to no HTML over the wire.

This is a confusing statement. Pre-rendering is a core principle of "Jamstack". To quote the site[1]:

> With Jamstack, the entire front end is prebuilt into highly optimized static pages and assets during a build process.

That seems the complete opposite of what you're saying the default is.

[1]: https://jamstack.org/what-is-jamstack/


> It's why the Jamstack mascot is the loading spinner.

I know much of the HN crowd loves to hate on bloated SPA applications (and not for good reason, we all deserve better perf), but this comment makes no sense. You can have a fast website with no loading spinners, pre-rendering, static HTML and optional/client hydration running on Jamstack infra.

It's misleading to suggest Jamstack = complicated/slow/bloated and SSR = fast/simple/good ux. Please take time to understand your tools. You can build a brittle/slow/poor ux website with SSR if you don't know what you're doing and/or don't care.

I'd advise others to not worship one technique over another. Choose a stack that solves a problem for your users, demonstrate empathy, evaluate tradeoffs and things will be fine.


I don't really understand hydration. I want to render an HTML report on the server with Jinja but be able to use React code in it, like Bootstrap tooltips. Is that possible? I can make the HTML the child of a React component with `dangerouslySetInnerHTML`, but not sure how to make it a first-class citizen of the page.


You could use MDX [0], it integrates Markdown with React. Lots of MDX to HTML converters out there, I use it with NextJS which has a good MDX plugin.

[0] https://mdxjs.com/


Server Side Rendering means that your Javascript produces an HTML string that's sent over the wire, like "<div><button></div>". The browser can render this HTML very, very fast, which is why it's desirable for performance. However, the <button> that's sent to the client won't have any Javascript onClick interactivity. That's where "hydration" comes in, React (or whatever) re-runs over the HTML already in the browser, and wires up click handlers, etc. The HTML on the page won't change, but now it will be interactive. The benefit is the user gets to see the HTML much faster.

For some libraries that are very large, like Threejs or a charting library, or any tech that draws to a Canvas which probably can't be SSR'd, it's probably best to detect if you're on the server or the client in your React code (which is usually done by injecting some env variable into your bundle), and render an empty <div> on the server, and when the client hydrates, it will download the large library and create the chart.

For other data, the trick is to create an API that works on both the server and the client. So `getPosts()` on the server will call to your internal API, and when that same function is executed on the client, it calls out to GraphQL. Then you switch out your API client on the server vs client bundle. In this way, your app is "universal," you can do a blocking fetch of posts on the server and render server side HTML, and on the client you can still call `getPosts()` on button clicks or whatever to fetch new posts. And API calls are much faster on your server side because you're in the same VPC, they don't go out over the public internet, and you might not even need TLS for them.

For most SSR apps with hydration, the entire app is downloaded again on the front-end. What I want to see is selective hydration first. For example, you define your entire app in React, and things that don't change, like the header and the footer, are only rendered on the server, and the JS React code is never sent to the client. For things that need interactivity, like dropdowns, the React code is sent to the client only needed for the dropdown to make it interactive. I think selective/partial hydration should be the default behavior for webapps, only deviating if you have things like large JS libraries as mentioned above, or maybe applications that you always keep open in a single tab, like an email client.

These same principles apply to CSS rendering too. CSS should always be extracted to a static stylesheet and sent as a <style> tag. If you have to download JS, parse JS, run JS, and then get a stylesheet injected into the DOM, it's also a bad performance hit. Browsers will always be faster than us at showing vanilla CSS and HTML to users as fast as possible, which is what we want. The most important consideration of CSS libraries is whether or not they can produce static stylesheets. It's mystifying to me that none of the CSS-in-JS libraries mention if they can/can't do this as part of their landing pages. If users have to execute JS before CSS starts styling the page, you've lost the performance game.


With Svelte my static sites are automatically pre-rendered and shipped as pre-compiled HTML. Loads instantly and optionally hydrates with JS in place. No extra effort needed.


Blitz.js is worth a look as it supports both out of the box


I like Blitz, but it’s built on Next JS - isn’t that where it gets it’s SSR and static capabilities?


That seems to be correct, NextJS already has SSR and static capabilities like you say.


I don't think SSR is that big of a deal these days with faster phones and data plans. You get more returns focusing on bundle size, code splitting, and time to first paint.


There are websites and web apps. Two very different things.


They’re not ‘very different’, they exist along a continuum. Most somewhat complex projects will include parts that live at various points in that continuum.


I'm a big fan of TID: Trust in Developers.

That means building out an application and experience that has the following:

   * a substantial education component. You are an expert in X, so educate developers so they can get better at X
   * meets developers where they are (in terms of languages and tooling)
   * allows both high and low levels of abstraction (including a well documented and consistent API)
   * free to start (even though we all have to eat, developers want to kick tires with minimal effort)
   * encapsulated functionality that does a few things and a few things well. The RDBMS is a model here.
   * an open feedback loop, typically on GitHub or in public. (Slack is a bit of an anti-pattern here.)
I don't know how devs are going to use tools built for them, but the last thing I want is for them to be disempowered. The farthest end of the empowerment spectrum, of course, is open source, but there are business model problems with that. I've written on that before: https://www.mooreds.com/wordpress/archives/3438

For another smart, if different take, read this: https://redmonk.com/jgovernor/2020/11/26/addressing-the-deve...

The post talks about tooling and a cohesive structure as the next great opportunity.


I’ve advocated DX across my leadership career. However, I believe current development methodologies are at odds with significant DX improvement. Engineers didn’t start out making micro service architecture. It emerged as a consequence of large organizations running agile teams (Conway’s Law). Agile teams are solving their problems, which are a subset of the org’s problems at best or ironically opposed to them at worst. Anyone who’s had to fight another team to get something done knows what I’m talking about. That means DX will always cater to the lowest common denominator among them, much like third party tools will try to solve for breadth of user needs over depth.

If we really want a better DX paradigm, we need to figure out another way of working that isn’t agile, either with a big A or a little a. I don’t know what that is yet, but doing anything less will just be the equivalent of making a better Jira.


> we need to figure out another way of working that isn’t agile,

Isn't devops the next generation? (I mean devops as promulgated by Accelerate: https://www.amazon.com/Accelerate-Software-Performing-Techno... , not 'smoosh the devs and ops teams together, add Jenkins and hope for the best'.)


I'm not convinced it's materially different. At scale it looks similar to large agile organizations of today.


Tangential idea: I worked on Google's Web DevRel team for about 6 years. Another core conflict I saw a lot is the tension between developer experience and user experience. An improvement in developer experience sometimes resulted in a degraded user experience.


I guess it is a better developer experience to not need the software to work...


Can you give some examples?


One example is dropping support for older browsers. Dropping IE support is better DevX because debugging esoteric IE bugs is very time consuming. But if you have a lot of people using IE, dropping it is worse UX for them, especially if they are using IE6 from a very old OS and can’t get the latest browser.

So at that point, the balance becomes “ok, if less than 1% of requests come from this browser, we don’t explicitly support it.”


This is similar for Android developers.

How soon can we drop support for Android OS #? Because # doesn't have the easier to use animation API, or because we'll need to display an extra modal, or some such.


That can just as well be a business decision. We have X budget for this website, we currently have > X expenses so what can we cut. Then cutting the difficult browser is not a hard decision.


This is how it works and HN complains about it a lot, ie. when some service or program doesn't support Linux or Firefox.


Linux is very much understandable, but Firefox still has a considerable user base, between 3 and 5 pct depending on who's counting; Double that if you only target desktop. Considering the support burden of Firefox should be minimal, I can't really see those business justifications


Why should they prioritize support for a small browser that encourages you to block ads? Doesn't make business sense to me.


My guess is that the majority of web sites out there with any kind of custom dev work behind them are not relying on ads for revenue.

Eg Netflix doesn’t care about ads - they care about supporting their customers whereever they happen to be. Supporting (or not) Firefox is still a business decision of course, but it has nothing to do with ad-blocking.


A sports organization that I know seems to have bought a website that won't work with any browser, every User Agent that I have tried causes an error.

It still seems to download a fair bit of Javascript so I guess a developer had to write it at some point.


Have you tried faking user agents of different OSs?


Tried every combination of browser and OS.


Not the OP, but one came to mind quickly: developers like quick build times and easy to edit files, but end users need efficiently-packed, minimal builds - the more you do at build time to improve performance, the more time a developer has to wait for builds. This is especially true if E2E tests improve UX by reducing bugs but again devs have to wait. Finally, it’s convenient for devs if no API surfaces change but it’s convenient for users to have the newest features that will save them time. It takes work to make sure both UX and DevRel goals can align in the same solution… they’re different audiences, even if there is overlap.


That's why we have fast debug builds with logging, and slow, optimized, prod builds.


Electron?


This is a great example. Companies no longer wish to write performant desktop apps because it’s much easier to keep and hire cool young devs who think the syntax that you write your views in matters more than the experience as a whole.


I don't think that's why developers are writing electron apps. It's because it allows for more significant code reuse there's a much deeper hiring pool (IMO)

Disclaimer: I work for a company whose main product ships as an electron app, although I don't work on that part of the product specifically.


“Code reuse”. There’s your buzzword excuse for that project being a web view.

Edit: I also said it was easier to hire. Which IMO is an organizational anti pattern. Look at all the talks of Clojure shops, who despite having a small hiring pool, usually find passionate, practical developers who quickly pick up the language.

Electron allows you to hire devs who prefer code aesthetics over what the thing actually does to/on your computer.


It's not a buzzword, it's a very salient point. Code reuse, a consistent UI and a much greater development velocity across a much greater number of platforms (web, desktop, mobile).

It can be done poorly, and there are plenty of examples of that, but it's not a universal rule and the trade-off gives real benefits. At the end of the day you do need to ship and maintain _something_, and maintaining one thing is better than maintaining Web, MacOS Desktop, Windows Desktop, Linux Desktop, iPhone and Android.


While only slightly relevant to the content of the article, the author has an incredible tweet thread.

"Taylor Swift as classic programming textbooks, a thread."

https://twitter.com/jeanqasaur/status/1290883041418649600?s=...


I’ve had “engineers” at my company push leadership enough to force me to create a build/plug-in system for react components to render a map of the US. I made the same map in D3 at home over the weekend in vanilla JS.

The excuse was DX. How can we test it and use storybook if we don’t use react and generate a giant dingus of a bundle?

Edit: so don’t just trust “engineers”.


Great analysis. My only remark is that the focus is fully on the backend/infra.

On the frontend, observability and transparency are the main reasons why I still use Redux and its dev tool. It's like live logs on steroids. Not only do you see the chain of actions that led to a certain outcome, you see the state at each step. This makes the reasoning about the bugs much easier. There was a tool on Show HN a few days ago that does exactly this but on the browser level[0].

And DX in general? Well, this is how it's stacked in today's startups

https://pbs.twimg.com/media/FAIZRuaVQAEGwGU?format=jpg&name=...

[0] https://news.ycombinator.com/item?id=28539247


Nothing new here on the complexity. AOL had a similar service dependency graph around 2004 or earlier. Paypal had a considerably denser graph I made post-D3 in I don’t 2012? 1000 services by name (some segregation by QoS so maybe less code than that implies). The core graph or central service dependencies (removing all the services that just called other services and weren’t themselves called, repeatedly till nothing could be removed) was like a hundred, with many loops.


Having read the whole article, not sure what the point is. Focusing on the problem before the capabilities is good, but so much energy is spent working around missing capabilities, “this service won’t propagate the debug header and the team won’t fix it” that it is natural.

I will say design is useful - the AOL graph was mostly hub and spoke. App Routers -> domain specific orchestrators -> single coarse grained functional API. Paypal was more poi;t to point to point. AOL encouraged devs to take some time just mulling over a new problem or new servers until a sensible approach seemed feasible. Few weeks for a 3 month project, few months for a year long project.

and in the 90s good software had observability. Metrics and logs and tracing, all on the fly to enable or disable prospective msgs (you had to turn off a certain log msg on the fly when a dev accidentally left would should be a tracing level msg at like an always log level).


Since the article is talking about the great expansion I'm offering a counterpoint - the great collapse.

https://www.swyx.io/js-third-age/

> Collapsed Layers (One thing doing many things well instead of many things doing one thing well)


I think the author misses the mark about what the problem is with developer experience, although they get the analogy of a "rainforest" correct.

Developers are in a run-away-train kind of situation, where they think that more libraries, more frameworks, more tools, more languages, more abstractions, etc. is the key to a better developer experience. In reality, this is the exact thing that is making development and developers miserable. The whole `is_even` fiasco [0] should have been a wake up call.

The plain fact of software development is that there is going to be complexity, and there is going to be some point where adding features or fixing things is going to become a slog. The choice where do you want that to happen? With the never-ending reliance on libraries, frameworks, tools, etc. the difficulties has been shifted towards the latter half of development, "we'll worry about that later". Sure, the share holders and the angel investors are stoked when a team can get an app running in a few months. But guess what, down the road when it comes time to add more features, make it fast, to flesh out the app into its full potential...it will end up in a nightmare of trying to wrestle the code and the barely comprehensible infrastructure to get it to do what they want. Good luck trying to figure out what is making the app slow in that rainforest.

The best thing I ever did for my mental health when working on hobby projects was to keep it simple stupid. In the case of C++ and games, I do everything in my own code maybe using Sean Barret's header files or GLFW for Window and input. Use a .bat file to build the code, rather than some overly complicated build tool so that it can build in 2 seconds rather than 5 minutes giving me very fast iteration speed. The Vulkan rendering code, the math, system level stuff like memory and file IO is all my own. For web stuff, I wrote a production web app for an internal team in a single PHP file with only a templating library. Going this route has undoubtedly doubled my productivity. Static site generator? I'd rather write one in Python than try to figure out some complex dependency ridden mess of an open source tool that never does what I want it to do.

The pain of developer experience is self inflicted. In an effort to reduce friction in development, a system of increasingly worse friction has been introduced. Programmers need to stop being afraid of writing code, and, dare I say stop being lazy. Developers could be just as productive, if not more productive, if they would just write the code.

[0] https://qz.com/646467/how-one-programmer-broke-the-internet-...


I come to add my old timer agreement here. This does tend to lead to a lot of NIMBY ism - walled gardens of code that only I (or my team) know how to use. But then sometimes we grumpily admit that someone else's solution (either OSS or elsewhere in the org) is actually better and we use that. if we make that decision based on our experience of trying and failing to beat them. Repeat this and what you end up with is a shared core of libraries that have been agreed to be the best by informed electorate.

Surely the best outcome.


> This does tend to lead to a lot of NIMBY ism - walled gardens of code that only I (or my team) know how to use.

Just put code comments above everything and describe what happens below.


I got to "With developers spending less than a third of their time actually writing code," and thought "what?" then read the rest of it: "developer experience includes all the other stuff: maintaining code, testing, security issues, addressing incidents, and more." and then though "oh yeah... that's about right on a good day" lol!


> It’s certainly possible, for some problems, to automate the problem away. But other problems (for instance, finding and fixing bugs) cannot be fully abstracted, often requiring user input.

I think that's not the right way to look at it. It's just that a task that's automated no longer needs a dev. Thus we only work on things not (yet) automated.

As a corollary, easy-to-replace parts inevitably become replaced with hard-to-replace parts, because those are the ones that stay.


DX today exists at lots of different levels, from competitive code games, to hackathons, to well formatted docs & code samples - all IMO form a larger umbrella of DX.

I still see it as an emerging field with more work done to synthesize under a single umbrella of being able to communicate abstraction levels, concept understanding, adding explainability to decision models and of course tailored for the skill tree at where the target developer today is at.


> As every company continues to become a technology company inside — regardless of product or service — developers are getting more of a say.

I know this is Silicon Valley gospel but just because technology is a critical part of many if not most companies' operations today doesn't mean that those companies are "technology companies."


Nice article. Excellent point about software heterogeneity. Ecosystems and platforms should support potentially a wide range of different tools, engines, languages, hardware... Heterogeneity is necessary for 'natural selection' to take place and to ensure that the ecosystem/platform can evolve over time.


This is one of the main motivation for Oil: we have more and more languages and tools and they will never be consolidated. Software is being used in more and more areas so this is natural / inevitable.

Slogan: Shell is the Language of Heterogeneity and Diversity

https://www.oilshell.org/blog/2021/07/blog-backlog-1.html

To be concrete, a "monoglot" lives in a world where the language's package manager is responsible for integrating different pieces of software.

In contrast, a polyglot uses multiple languages, and the package managerS (plural) are just tools, not the world, and they're called from shell scripts! (Or something morally equivalent, like a Makefile or Dockerfile)

The future is more polyglot, e.g. your Rust or Zig code will coexist with a lot of C and C++ code. Sometimes they will be linked into the same process, but often they'll live in different processes and you'll use various forms of IPC.


>> The number of developers is currently larger than the population of Australia, growing faster than the population of Brazil, and set to exceed the population of Canada.

Does this count the 6 people I interviewed this year that couldn't fizzbuz?


>> Does this count the 6 people I interviewed this year that couldn't fizzbuz?

Yes. The bell curve for software developers is very wide. The 10x developers are real, they're way out there - maybe 2 standard deviations from average. The "can't fizzbuzz" crowd is large, probably only 1 standard deviation (or less) below average.


1 out of 6 programmers can't solve fizzbuzz? That seems way too harsh. 2 standard deviations would mean 2.5%, or 1 in 40 -- that seems more likely, at least in my DX


This is a well-known sampling bias. The number of interview candidates who can't solve fizzbuzz is very high, because those are the people who aren't in jobs and are therefore interviewing. Interview candidates are a skewed sample of the entire population.


"Started in 2006, and published twice a year, it provides the most comprehensive, current, detailed data on the state of the developer population. It includes information on the total number of developers in the world, as well as on the total number of developers involved in specific technology areas. This report combines EDC’s proprietary global developer population model with selected findings from EDC’s semi-annual Global Development Survey."[0]

Looks like it depends on how "EDC’s proprietary global developer population model" works.

[0]https://evansdata.com/reports/viewRelease.php?reportID=9


And more importantly, how does that number compare to the number of golf balls that can be fit into a 747?


You can fit far fewer than a million developers in a 747


> Does this count the 6 people I interviewed this year that couldn't fizzbuz?

No, but it does count the 1 guy who started a Shopify store and has made 6 figures selling "Do u even fizzbuzz bro?" t-shirts.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: