In this three-part series, you’ll learn the process of selecting a tech stack for a project.
Blog two of a series.
For a programming language, maturity is a double-edged sword. If it is too young, businesses don’t take it seriously – in part due to its instability and in part due to its lack of a track record or critical mass.
Conversely, if it is considered too old, it may start to atrophy due to a lack of new features and developer support.
Language Maturity
All languages have a lifecycle, and considerations of that lifecycle are made for any project.
We always consider Java and C# for their apparent ubiquity. We consider Node.js and Ruby as well for ease of development and availability of tools and expertise.
I, personally, always consider Google’s Go because it has the perfect blend of speed, concurrent capabilities, ease of use, operations versatility, commercial viability and available libraries – if I was starting a company, all of its applications would be in Go. But ultimately, it doesn’t pass the programmer availability test – yet.
Some languages, like /perl/ and /awk/, have historic significance and are still in play , but they enjoy more of a niche role as a utility play. And some languages that started off in one primary role, have evolved into a new primary role. To me, Python is a good example of that – moving from a language of the web to a language of data analytics.
Almost always, the languages we consider for a project are all on the upper right corner of the chart below, indicating the amount of popularity they enjoy in two of the largest online developer communities. That’s also reflected in aggregated job listings over the last several years.
Now, of course, we also get called for more specialized assignments like mobile where our decisions are constrained by the platforms (Swift or Objective-C for iOS, Java for Android, Xamarin for cross-platform). Those discussions are easier because they are relatively closed-ended.
All of the “orange boxed” languages are the typical candidates for most projects. They have strengths and weaknesses, but for the most part could do any job. But different tools are made to solve different problems.
Each of the languages we typically consider are classified as “general purpose” meaning that they fit well in a variety of situations – but each has their “sweet spot.”
Primary considerations are usually given to the languages below [Language, Version, Primary Backers]. First, the two obvious candidates:
- Java 8: 1995 (Sun/Oracle)
- C# 6.0: 2000 (Microsoft)
These platforms continue to be two of the most popular choices for software development in the business today. Both products enjoy mature ecospheres, available third-party resources, a large pool of developers, and a high demand for those developers.
They are also considered “enterprise strength” which means that, conceivably, they can solve any development problem an enterprise may have. The issue with being “enterprise” is that it comes with a lot functionality and capability that is not needed for a lot of development projects so it can be cumbersome to iterate quickly and deploy easily.
One reason we usually would not select C# or Java is because of the sheer weight of those technologies both from a “coming-up-to-speed” perspective, as well as building, deploying and operating those environments. Because our standard system architecture requires at least a partially distributed system, the ability to deploy, destroy, and deploy components again is a critical process in an active environment.
Since there may be functions that are being configured on the fly and running with several instances simultaneously, the need to be able to build, ramp up/down these components becomes a normal part of the DevOps process. The solution needs to have a very small footprint and be able to modify the functionality on the fly as well as stand-up new instances on a seconds’ notice to be a valuable asset.
C# and Java can be unwieldy, just in the setting up of environments, much less their automation.
Add to that the potential licensing considerations of Windows, a distributed environment could add complexity in areas it is not wanted. In the specific case of C#, being part of a Microsoft platform does not lend itself to being containerized easily, which adversely impacts our goals in the distributed design, deployment, and execution of the project.
Now, that said, if the client already has a heavy investment in those areas and is adamant about about keeping that direction intact, we will typically change the architecture to suit their desires and to accentuate the positives of those platforms.
A stack that has worked very well for us on many projects has been one based on Node.js and Javascript:
- JavaScript ECMAScript 2016: 1995 (Mozilla Foundation, 501c(3); Ecma International Standards Organization, founded 1961)
- Node.js 7.20: 2009 (Joyent/Samsung) — asynchronous runtime environment, web server for Javascript
- V8 5.5: 2008 (The Chromium Project, Google) — JIT compiler used for front-end performance on Google Chrome & Opera and for back-end performance on Node.js, Couchbase, MongoDB.
The Node.js stack has been powerful for us in part because it allows the team to avoid “mind shifting” when moving from the front-end to the back-end since we use JavaScript throughout. Although JavaScript developers are hard to find, they are easier to make than it is for many other established languages. If you add to that the ease of deployment, availability of reference resources, vendor support, and size of community – JavaScript/Node.js is always a solid contender.
Other languages that we like to consider, but are usually dismissed for various reasons:
- Go 1.7: 2009 (Google) — very capable, very well supported, harder to find resources (no critical mass, but rising)
- Ruby 2.3.3: 1995 (Yukihiro Matsumoto, Heroku) — large developer base, first-class citizen of the Internet, high development productivity, some performance concerns but can be mitigated. Would be recommended after JavaScript/Node.js.
- Erlang 19.1: 1986 (Ericsson) — one of the fastest solutions, highly fault-tolerant, and industry tested (used for phone switches), more esoteric, quick development once functional programming learning curve overcome. Rising programmer resource availability.
Because of my role in the company, I’m able to do a lot of pilots, proofs-of-concept, and one-off prototypes. Because those usually don’t come with a lot of long-term baggage regarding supportability, availability of resources and other non-technical concerns, I have chosen Go over the last three years for those situations because of its flexibility, speed (both execution and development) and ease of use.
But I also use it as an opportunity to try new things, so this year I’ll be selecting a new personal stack. But even when I’m a development team of one, I have to worry about availability of external libraries to help me complete my goal.