If your infrastructure is Docker based, you’ve already created an environment that isn’t dependent on a single language. Step 2 is realizing why the words “standardize on language y” no longer make sense.
A while back, I wrote a piece on how Heroku streamlines a lot of the pain points of microservice architecture. One of the big wins I talked about was the ability to deploy code in multiple languages rather than investing in a lot of deployment process around a single primary language. When your infrastructure runs on Docker, you’ve already built almost all of the same wins. You’ve invested in a process that abstracts development, testing, and deployment consistently…totally independent of language choices. However, not everyone is prepared to embrace that freedom just because they’ve removed infrastructure investments from the equation.
So let’s take a look at the other concerns brought on by the polyglot potential of Docker.
Concern 1: Nobody here knows language x
This is often the single loudest opposition to introducing a new language in a company. Is existing knowledge a valid concern when introducing something new? If so, in what context? Has anyone polled other developers or are we working from a broad assumption?
Already knowing language x is a valid concern if you’re trying to assemble a team to build something new. You’re looking at potential learning curve for multiple people to develop something from scratch, learn workflow and process, and learn to work with each other. Naturally, it’s going to make more sense in many cases to use something the team already knows in that situation.
The flip side is when you have developers who do already know language x and want to use it to solve a problem. In this situation, there is no training time or learning curve…those developers simply get to develop the solution among already known workflows and processes. If the language provides a compelling solution to the problem at hand, it makes sense to proceed. Until we get to…
Concern 2: What happens if you leave?
Right alongside “nobody knows language x” is “who will maintain it once you’re gone?” It’s a valid concern…until we consider how developers learn languages. If your replacement is asked to learn a new language and then build something in that language from scratch to deploy to production, that’s going to take a while. They’ll have to try to work through all of the ins and outs, tooling and best practices.
If they’re asked to learn enough of a new language to track down an error in an existing codebase, where they have all of the other code as a reference point, project workflow defined, and tooling already chosen, it’s a tremendously simpler task that just about any competent programmer should be able to do. It’s a difference of a few days versus a few weeks in terms of potential ramp-up time.
Concern 3: We can reuse code written in language y
The ability to reuse library code written in a primary language at a company is an extremely good point…in theory. In practice, this is much more difficult than it seems.
Developers will clearly reuse their own code or their own libraries, because they inherently know that code, where it is, what it does, where its limitations are, and how to modify it. But at a certain size, this type of knowledge exchange for internal libraries simply doesn’t happen.
One of the perks of internal development is that your standard of completion is “good enough for your needs,” while open-source libraries that we’re used to browsing and reusing are “good enough for the problem, well described enough that I can find them, well documented enough that I can figure it out, well tested enough that other people use them, and consistently available enough that I always know just where to look for them.” That’s a harsh reality for internally shared code in a lot of different companies.
Do you need a function that calculates a particular formula for a project…or do you need to write a reusable and well-documented library to calculate that formula on any project that you’ll advertise internally in a consistently searched location and likely end up maintaining if somebody else does need to use it?
If I run over to Google and search for “library that does…” it’s not searching my company’s private code bases. If you’re looking for a solution to a problem that you expect is a common one, a quick Google will turn it up. Internally, you’re not going to expect every common problem to be solved so you’ll tend not to look unless you’re actively told about those solutions. That creates additional overhead to properly communicate (and recommunicate to new hires).
If there is an internal library that makes sense to use over an external replacement, does it need to be included in my code or is it a consumable microservice? How many different places does this code need to live? How often is the reuse really happening right now?
The Benefits of a Polyglot Philosophy
Once we get past the concerns of a polyglot programming approach in a company, we get to realize a lot of the benefits.
Foster a creative environment
Developers are nothing if not creative. Our entire lives are based around solving both business and technical problems. Opening the door to more potential solutions is good for everybody.
Fostering a creative environment empowers your developers to explore more solutions with the confidence that those solutions will be openly received and fairly evaluated, which further encourages them to look for those great solutions. It’s a rewarding cycle that feeds itself via motivation and continuous self-education.
Language decisions are all based around tradeoffs given constraints. Solving the same technical problem at two different companies could mean two entirely different languages based on the constraints of those individual companies. There’s no silver bullet, but every language has a weaknesses.
Languages all make tradeoffs around development time, environment access/limitations, performance, verbosity or readability, flexibility, concurrency, portability, ram usage, reliability, fragility, calculation, libraries, and ecosystems just off the cuff.
When you chain your company to a single language, you’re essentially forcing yourself to live with the pain points…which forces your developers to live with those pain points…which can create a morale problem, especially if a potential solution is discouraged from consideration.
How Does Docker Address All of These Concerns?
Docker isn’t a silver bullet either, but a company with a Docker-based infrastructure for delivery through the pipeline has already abstracted away most of the language-specific parts of its infrastructure.
When Docker is used to deploy code to production, you deploy your code inside of a container. You don’t have to configure an entire set of servers. You simply deploy the container to a cluster with multiple other containers.
As usage grows, you might need to dedicate resources, but as far as your deployment process is concerned, you’re just dropping the container and running it. It’s already configured to whatever language you’re using. Your infrastructure doesn’t have to worry about mapping a lot of language-specific functionality to fit the model.
By using Docker for testing, you see similar benefits for your continuous integration system (like Codeship). It just needs to know where to get the container and how to run the tests…there’s no language-specific setup or maintenance involved. Just run the tests and report on those results.
This one is still the trickiest. Docker in development has gotten tremendously better over the years with the additions of the likes of Docker for Mac, Docker for Windows, and Ubuntu on Windows, but depending on your development workflow, using Docker for development may still have some stumbling blocks.
If you’re mostly developing within a text editor or Vim/Emacs, these probably won’t be as big of an issue. The more robust environments that take the time to index the entire codebase, including dependencies so that you can jump around in the reference points of code, can have some difficulties accessing those dependencies installed within a container. Other factors, like automatic test suites that pipe output to your machine’s notification system on file saves or IDE-based debugger tools, could also take some additional work to get working. These quirks still aren’t perfect in development environments, although they are seemingly getting better everyday.
Nonetheless, native setup for development is a much more reasonable assumption, even in a polyglot environment. Although your company may use many languages, each individual developer is not likely to do the same. Configuring a local development environment for the language that you’re going to be working on for a while isn’t likely to be a tall order if using Docker for development proves tricky.
In so many cases, development environments utilize additional packages that aren’t deployed up the chain, so a lot of the ideal of “mirroring production” isn’t always happening. You can always run your tests locally within the container.
If you’re using Docker across your testing and deployment processes, you’ve already taken the steps necessary to enable a polyglot environment in your company. Take advantage of your new-found superpowers and see what fruit it can bear.