In our last article, we learned about two different camps of coding languages: specialized vs. general purpose programming languages. Today, we'll delve into another schism. See what I did there?
Compiled vs. Interpreted vs. Bytecode
This delineation revolves around how programs are executed.
In 1534, a Catholic monk translated the Christian Bible, including the old and new testaments, and a set of controversial books that didn’t quite make it into the official canon, called the apocrypha. Martin Luther translated the Bible from Latin, which was known only to clergy and well educated aristocrats, into the German vulgate; the language spoken by your average “We’re gonna party like its 1599” Germans. He single handedly took the Word of God away from being the purview of a small number of people, to the common family.
What does this have to do with coding languages?
There is an analogous process at play regardless of your personal religious convictions.
When Luther translated the Bible from Latin to German, he wrote one copy. Printers were able to take that one manuscript and reproduce it as a bound book. Once the translation had taken place, it never had to be undertaken again.
When you write code, you write it in text, and you don’t write it in the language understood by the computer. Computers “speak” binary code at their most basic level. Humans cannot write complex programs, operating systems, business applications, and video games using binary. The process is too slow and too error prone. This is why programming languages exist in the first place. To create languages we can use at a higher level of abstraction than creating long interminable lists of 1’s and 0’s.
But those languages must then be translated into a binary code that can be executed by a computer. Luther translated the Bible once. If he were a coder, we’d say he compiled it.
A compiler is a program that takes your textual source code and converts it into something useful by the computer. Compiled languages are generally fast, but they are also inflexible. Each time you make a change to the program, it must be recompiled and redistributed as a new version.
Interpreted languages are more like a conversation between two people who speak different languages. If I know French, even if begrudgingly, and you don’t, and you need to speak to someone who only speaks French, your only remedy is to have me translate for you. You say something in English, and if I’m feeling generous, I do my best to render that same phrase in French. The Frenchman responds and I translate back into English.
This is generally a slower process than dealing with a pre-translated piece of text. If you could write in French, you wouldn’t need a translator. However, a conversation unfolds slowly and organically over time. If any ambiguity arises between you and your French compatriot, you are able to ask questions and receive clarification, which is not possible in a fixed work of prose translated into any given language.
Interpreted languages read your code as it’s executing and translates each instruction just as it’s needed by the computer. This has a huge benefit of being able to run your interpreted code on any computing environment that supports your interpreter.
A compiled program doesn’t have to translate anything because it’s already been translated. The interpreted program interprets the same code over and over again each time the program is run, like having a new conversation each time.
A third category exists. It’s a kind of hybrid between the two. Some languages compile your code into something called intermediary or byte code. This byte code is then interpreted by a program called a run-time environment.
The neat thing here is that it is possible to run your “half compiled” program on a variety of operating systems without making any changes to the code. Your program will have performance comparable to a natively compiled program, but have the kind of flexibility you find in interpreted languages.
If you're picking a language, consider your requirements around where and how your software runs. Does it need to run on any operating system, or can you control that? Speed of execution is usually somewhat important, but do you need the speed of C running on the metal, or can you afford a runtime like you find in Java or .NET languages? Finally, consider productivity. I worked at a company that used Java to build their own framework using JBoss. Productivity was a problem because the compile time on our project was fairly long. It took several minutes to build your code, and restart your app server. This makes simple changes like pixel pushing absolutely maddening. Imagine moving a graphic over a few pixels using CSS. You make a one line change to the CSS file and build. Wait several minutes and check. Nope, we need a few more. Make another one line change to the CSS. Save. Build. Wait several minutes and check. This can go on for a while. Interpreted languages don't need to build, so your feedback is instantaneous making you more productive.
Procedural vs. Object Oriented Languages
I'm going to toss out one more way you can split language families, but I'm going to be a total tease about it. This last classification involves how you organize your code. I won’t get into this now, because in the near future, you’ll have a whole chapter on object oriented programming preceded by a thorough introduction to functions, which are the basis for procedural languages.
For now, just understand these are two different ways of thinking about how to structure your code.
Our next article will feature a discussion on general syntax considerations. You can sign up, free of charge, and be notified when the next article is published. I also have a YouTube channel that covers practical coding techniques, and as always, visit my web site: www.maddevskilz.com for training resources for devops and coders.