If you've worked in this business for a long time, you've definitely encountered that mid-size company where every team has their own favorite language. And while this might work for awhile, it's a long-term disaster waiting to happen within your company. Eventually, every company that grows to a certain size and survives realizes that you need to clamp down and have at most four computer languages allowed inside your build process.
Four languages is the minimum every company needs, because every company needs the following:
- A shell language for builds and runbooks
- A script language for rapid development cycles and low-performance
- A compiled language for performance and long-term deployment
- A front-end language for user interfaces.
You need to decide up front which of these you're going to use, and stick with them. The reason is simple: if you limit the languages that are in use in your company's software projects, no project will be a mystery to anyone else. No one will have to deal with "Microservice X is failing, but only three people know how to fix it" problem. By restricting the list of languages your company uses, you guarantee portability of skills across the enterprise, and you provide a safety margin in case one of your core developers gets hit by a bus.
Here are the four programming languages you should be using (with alternates, in some cases). These languages have been chosen for a combination of power, tooling, reliability, and popularity. That last is important: it makes hiring for that language that much easier.
A Shell Language
Shell languages are the ones that you use to glue lots of existing tasks together. Shell scripts are use for building programs, streamlining complicated processes, and encapsulating the hard-won lessons of runbooks.
Bash should be your shell language. Not zsh, not csh, not the original sh, Bash. It's universal, it's powerful, and everyone knows it.
If you're an all-Windows house you might be able to get away with Powershell for a while, but everything in the cloud is running on Docker, Kubernetes, and Linux these days, and those are places where Bash rules.
A Scripting Language
Scripting languages are useful for tasks that require the complexity of a full-blown programming language (which shell scripts are not), but they tend to be slow, inefficient, and use a lot of memory. As a way of getting something to market fast, however, nothing beats an accomplished team of script developers.
Python is the most popular scripting language, and it's the one you should be using. It's a language that is both fragile and battle-hardened, and it's so widely known that you can usually find a Python developer looking for work fairly easily. Python 3 provides some powerful new concurrency features and it comes with an extensive library of machine learning kits.
Alternatives to Python are Ruby and Node. Node is a good choice if you're a web-heavy business, as it allows for something call isomorphic deployment: the same code that encapsulates the business logic you use to validate and protect your back-end can be bundled as libraries and used as your front-end. Node has an awkward concurrency story, but experienced Node developers know how to work with that.
Ruby has its place in older web deployments that use Rails, but its popularity has waned quite a bit in recent years.
And if you find yourself in a place that still uses Perl, well, you're on your own. It's a powerful language, but it's also notoriously easy to write code that's difficult to read, and code is meant to be read by your peers long before it's deployed to customers.
A Compiled Language
The point of a compiled language is often said to be "performance," but it's more than that. It's about security and cost. In the cloud, a scripting language often comes with a lot of baggage; containers for a Python, Ruby or Node program contain whole subsets of the Linux operating system, providing any attacker who gets past the front door an entire toolkit with which to dig further.
Picking a compiled language is always a contentious issue, because the intersection of performance, learning curve, popularity and so forth is broadest here. But for start-ups, there's only one choice: Go.
Google Go is an open-source programming language that is absurdly easy to read, and if you're a Python programmer, the standard library should make you feel right at home. Google has thrown a lot of money at Go, and it shows in the tooling and development cycles. Go is a very simple language deliberately designed to make developers productive while providing guard rails to help developers not make mistakes. And it's simplicity makes reading, reviewing, and discussing the internals of every project straightforward. As an enterprise teams language, Go is unmatched. Go's compiled product is cheap to run in the enterprise and quick to start; a Go program typically uses half the memory of a similar Python program and less than half the CPU, so enterprises with large swarms of microservices can run on smaller persistent instances, and can spin up on-demand instances much more quickly for responsive user experiences.
If you're an all-Microsoft shop, however, C# with .NET 5.0 is an extremely attractive option. The newest version of .NET can compile a microservice-oriented "solution" into a single binary object that can be containerized with ease, providing all the security and ease of deployment that Go does. .NET programs typically require more CPU and a lot more memory than an equivalent Go program, but the .NET libraries are among the most extensive in the world.
Java is still the most popular programming language in the enterprise, but I discourage its use for startups. Yes, it's big and yes, there are libraries for Java that do just about anything. But it's owned by Oracle, which is famously litigious about extracting money from its users, and it's a highly ceremonial language that requires a different way of thinking about programming from most of the others. You can't just open up a file and start programming, and the sheer amount of boilerplate makes bringing new developers into your project difficult.
And finally, Rust is your desperation language when you absolutely, unquestionably need to extract every last erg of power out of a programming language. Rust is what you grab when you need to process images and text in real-time, when you'll be doing it a lot, and when your processing costs are significantly greater than your development costs. This space used to be ruled by C and C++, but Rust has grown recently into a language both Microsoft and Google admire for it place. But you're going to use Rust, go all-in: write everything at the compiled layer in Rust. Rust developers are hard to find and hard to train, but once you've got them, use them.
Your Front-End Language
Your front-end people are going to be in their own world; Webpack, Closure, HTML, JSX, React, Vue, CSS, Sass. They'll have their own language. But you should discourage them from using more than one, and they should come up with their own internal standards, and they should have their own templates for bringing new developers into the project. CSS or Sass, Webpack or Closure, React or Angular, REST or GraphQL; allowing more than one of each means that you have compatibility and portability issues across internal teams.
There are exceptions. There are always exceptions. Even with a highly skilled Typescript team, using NodeJS for your back-end isn't going to be a big win because server-side development is a different skill from front-end, but that doesn't mean there can't be a NodeJS microservice on your server-side; a front-end with a lot of validation logic can have that same validation pass "as a service" on the back-end by having a dedicated NodeJS process that takes your inbound data and runs the validators against it, then returns a verdict.
Likewise, if your back-end is ridiculously data-complex, using either a data-oriented language like Clojure (which runs on the Java virtual machine) or an algorithm-powered language like Haskell (which compiles to machine code) might make sense, especially if you have the world's best developers in those languages.
If this happens you should require your developers to make their case. To explain why they should be allowed to deviate from your company's policy and use languages outside The Four, whatever "four" you've chosen.
I mentioned "five languages" in my title, and nd there's simply no getting around the fact that you're going to need a fifth language: SQL. There is only one relational data language, and that's SQL. But if you're going to be an SQL-heavy shop, have rules about using it: indentation, capitalization, commenting should all be part of your SQL, and to whatever extent possible your SQL should be independent of the programs that use it. Treat SQL like a real programming language.
Above all else, avoid shiny new toys. As of 2021, it's wise to just let the kids play with ReScript, Crystal, Kotlin, or Dart. These languages don't have the traction, tooling, libraries, or communities necessary to make them good startup choices. You'll find yourself reinventing the wheel a lot, and that's not a good place to be. You'll want to avoid these languages unless there's some overriding, utterly compelling reason to do so.
For the same reason, stay away from languages that are in decline. Obviously, no one is going to be writing microservices in Fortran or Cobol these days, but Perl is still around it still has its adherents. There are still ObjectiveC programmers who believe it's the most productive programming language, but if you base your business around ObjectiveC you're going to have a hard time hiring new developers.
My plea is simple: if you want your business to go from $1 billion to $5 billion in non-GAAP annual revenue, you're going to have to pin your development teams to a collection of four well-known, industrially-supported, and generally mature programming languages. You should also lock down the frameworks and, if you're using them, the transpilers that are also permitted. This enables portability, gives every programmer permission to perform a code review on anyone else's code, and reduces the risk that if that one guy gets hit by a bus your company is doomed.