It’s common to talk about the way we build software in terms of the individual tools we compose together, like command-line utilities and deployment pipelines and containers and services, and most obviously, programming languages. Programming languages seem to get the highest level of scrutiny out of everything that comprises the way we write software. And in the last decade, I think we’ve seen a healthy rejuvenation of innovation in programming languages, driven by languages like Rust, Go, OCaml, Zig, and Swift that bring new ideas to the industrial programming world in practical packages.
But while programming languages are academically interesting, I think we more desperately need innovation in programming environments.
The programming environment isn’t a single component of our workflow, but the total sum enabled by the tools working together harmoniously. The environment contains the programming language, but also includes the debugging experience, dependency management, how we communicate with other developers (both within source code and without), how we trace and observe code in production, and everything else in the process of designing APIs to recovering from failure.
The story of programming language evolution is also a story of rising ideas in what capabilities good programming environments should grant developers. Many languages came to popularity not necessarily based on their merits as great languages, but because they were paired with some new and powerful capability to understand software and write better implementations of it.
C brought practical portability to (what was at the time) high level programs. C literally elevated the programming environment out of processor-specific assembly code into a common vernacular. The legacy is so strong that most languages we use in production today are either direct descendants of C, or inherit much of their syntax, like curly brace-delineated blocks and structures, semicolon statement-terminators, and parenthesized function calls.
One of Go’s claims to fame and primary design goals is compilation speed. Compared to its predecessor C++, Go compiles fast. And when you make something fast, people start to use it differently.
Erlang, with its advanced, concurrent, message-passing runtime, offers a better way to build high availability, highly reliable systems. It was born in the telecom industry, but has found home in many other critical services industries.
Thoughtfully crafted programming environments are the hidden treasures of the software industry. When we choose a language because of the “tooling” or because of the “IDE experience” or because of “the workflow,” what we are really doing is making a judgement about the programming environment we want to live in and grow around our work.
Between investments being made into new languages and the community’s willingness to experiment, there’s a lot of creative energy being poured into inventing better languages. I think it would serve us well if we invested just as deeply into rethinking the context in which we write those programs. We should be asking questions like:
- While professional photo editors and video games can run in the browser, why are we still using a repl that prints lines in the terminal?
- Does the compile-time / run-time distinction make sense to have? Can we give better control to developers about when their code is executed during the software development and deployment process?
- What does an operating system kernel designed for debugging experience look like?
- What does a memory model or memory allocator designed for debugging experience look like?
- Are the tools we have today good enough foundations for massive open-source communities like NPM? How can we improve the programming environment and our tools to make the most of package repositories with hundreds of millions of libraries and billions of lines of code?
There are some people trying to create better programming environments. Repl.it brings general purpose development to the browser. Experiments like Light Table more closely integrate source code with its output. Jupyter notebooks are a unique way of writing and sharing code that focus on the process of iteration.
But these are also workflows and tools built around languages that were never designed for such interactive experiences. I think if we build a culture of thinking about programming environments as a place ripe for creative innovation, we’ll see a new class of software development tools emerge that make the most of today’s machines and networks and allow us to write new kinds of software we couldn’t before.
If you enjoyed this piece, you might also enjoy my next post, On leading change in the tech industry.
I share new posts like this on my newsletter. If you liked this post, you should consider joining the list.
Have a comment or response? You can email me.