Are we there yet? The road to production (Part 1)
So you had an idea, built a prototype, people started using it, now you decided to build something of substance. There are many shortcuts one can take during the development of a project but if it ever reaches the dreaded ‘Production’ than your needs go way beyond the usual I’ll just package it up and run it on my MacBook as a service. This book provides a comprehensive list of concerns and subconscious decisions that need to be made when building an internet facing production system and a product/company alongside it. We’re off! So hold on tight it’s going to be a wild wild ride.
The language and ecosystem
Choosing a programming language can be as simple as picking what you know best. That said as your company grows certain decisions will make your life a lot happier down the line. As you may know, some languages and ecosystems are a great fit, while other even if they might work, they would be a tight fit. An example even if you can run Node.js on an embedded system, doesn’t mean that might be the most sensible thing to do.
Things that need to be considered can be broken down into categories:
- The language
- The ecosystem
The programming language
Static typing or dynamic typing
Before we dive into the little research that is out there, let’s start with the basic premise. What static typing means that type checking happens at compile time, whilst in dynamically typed languages this only happens during runtime. In practice, this means that in some languages you explicitly have to declare types everywhere, or almost everywhere (different languages have different levels of type inference ). Okay, so what do we get for this in exchange? You get compile time guarantee for things like :
- Can we call this function with a parameter of this type?
- Does this method actually exists in this class?
- Can we assign the result of a computation to that variable?
- …
I hope you see the general pattern it’s about verifying for the programmer that things actually line up. Some developers go as far as to say “If the types line up it’s guaranteed to run!"
- The research done in this area mostly provided inconclusive results, there were issues with the gathering of subjects, biases in the selected projects, issues with the analyzed results, but even this way there wasn’t any real conclusive evidence. So in this regard, my suggestions would be to go with whatever your team’s preference is.
As a personal insight from a sample size of 1, in the enterprise/fintech space having worked on a large project that used with Java, Scala, Javascript, and Groovy. The stronger the type system the better and as much type inference as possible is a blessing.
The drawback is the compiler speed but from what I’ve seen for large enough dynamic projects the startup speed and extra tests because the lack of types the net result is mostly the same. In refactoring, the static languages, gave me such a significant help, as if I was almost pairing up with another developer.
Strong or Weak Typing
The debate for strong versus weak typing is sort of similar, just the context is different. In a weakly typed language when you write
$someVarible = "abcd"; // $someVarible is a string
$someVarible = 123; // $someVarible is now an integer
The other thing that happens in weakly typed langues is type coercion, where because of context the type of a variable is changed to a match it’s context. See the following example in Javascript:
[0,1,2].indexOf(0)
returns => 0
[0,1,2].indexOf(0) == false
returns => true
This happens because in the context of == sign the 0 should be a boolean value, so it’s coerced into false. You can find many examples of type coercion in javascript in the “Wat” video by Gary Bernhardt here.
In a strongly typed language if you give a variable a type it usually ‘binds’until the end of its lifecycle. Note the above type coercion is not to be confused with implicit conversion, in which the compiler basically knows the rules in which one custom type can be converted to the other in a meaningful way. In some languages like Scala, you can even define you’re own implicit conversions and then import them as needed. A few examples below:
// In Java
String token = "abcd";
String newToken = token + 123;
=> newToken now is "abcd123"
//In scala
implicit def bool2int(b:Boolean) = if (b) 1 else 0
scala> val b=true
//b: Boolean = true
scala> 2*b+1
//res2: Int = 3
The learning curve
Many people say learning a programming language takes only a few days since it’s just syntax. Whilst it’s somewhat true, and there are sites like learnxinyminutes It’s still not an easy task if you want to have a team write production ready, idiomatic, maintainable and scalable code. Every programming language comes with its own implementation of one or many paradigms, patterns, conventions. Even though some of them are related and the transition is easier ( think Java to C#) it might still cause headaches in terms of libraries, language features, runtime.
Changing paradigms can be even more challenging, taking a team of Perl programmers and having them working on an async/callback full Javascript project might be challenging. Or switching from a pure OO Java project to functional Scala one that freely uses things like scalaz will have an impact on the maintainability and long-term survival of the project.
Again the advice is to try to stick close or in the range of the team’s expertise while leveraging the opportunities new languages give. As an example, slow addition of Typescript to a Javascript project might give positive benefits and only a slight learning curve. The same goes for Kotlin or “Java-esque” Scala for a team of Java developers.
This is Part 1 in a series of blog articles “Are we there yet? The road to production.” In the next article, we will explore the importance of the chosen languages ecosystem, libraries, runtime, tooling, monitoring, APM and etc.