If you're a software engineer, I can imagine that you've heard the term "compiler" a lot whenever you're in the process of coding something. Especially when you're getting an error. 😁
The compiler can be a friend or an enemy, depending on what you're doing.
This article will show you the advantages and disadvantages of a compiler.
The book "Five Lines of Code" explains it brilliantly, so I'm going to refer to that in this article. The code snippets are in Typescript.
DISCLOSURE: This article contains affiliate links to external products. This means that I will earn a commission at no additional cost to you if you decide to make a purchase. Thank you!
Now let's dive in.
What is a compiler?
A compiler is a program that turns a high-level language into low-level code that the processor can digest.
This is the primary goal of a compiler.
But nowadays, compilers do more than that.
They check if some errors can happen during runtime, and in this article, we're going to concentrate on this aspect.
What are the advantages of a compiler?
1. Advantage: Reachability ensures that methods return
The compiler ensures that a method has a return statement. The compiler will let us know when a method should return something, and if we miss the return statement.
2. Advantage: Definite assignment prevents accessing uninitialized variables
Compilers are helpful with checking whether a variable has something assigned to it before we use them.
The compiler won't let the programmer get away with not declaring a variable.
3. Advantage: Access control helps encapsulate data
The compiler does an excellent job of managing access control.
If we make a member private, we know that it will not slip away easily.
4. Advantage: Type checking proves properties
The compiler helps us check whether members and variables exist and are associated with compatible types.
We've seen the advantages of the compiler.
Now let's examine the disadvantages of a compiler.
What are the disadvantages of a compiler?
1. Disadvantage: The halting problem limits compile-time knowledge
What is the "halting problem"?
Wikipedia defines the halting problem like this:
"In computability theory, the halting problem is the problem of determining, from a description of an arbitrary computer program and an input, whether the program will finish running, or continue to run forever."
In simpler words, the definition says that we don't know what's going to happen until we run a program.
In the screenshot above, what's inside the IF statement won't run, and regardless the program will fail because there is no definition for the method foo().
This is a weakness because the compiler will allow a program to behave unexpectedly in some cases. In other cases, the compiler will perform conservative analyses, which means it will refuse to run the program if it is unsafe.
6. Disadvantage: Dereferencing null crashes our application
Have you ever got a
Unfortunately, the compiler doesn't help with this.
The compiler will allow a program to run but then throw a NullPointerException at runtime.
In some cases, the compiler will tell you something such as "XYZ may not have been initialized". But not all the time the compiler will help you prevent a NullPointerException.
An excellent way to prevent a NullPointerException is to ensure that all objects have been initialized before we use them.
7. Disadvantage: Arithmetic errors cause overflows or crashes
The compiler doesn't help with this as well. It doesn't even tell us whether a number is divisible by zero (in that case, we'll have to trust our maths skills).
8. Disadvantage: Out-of-bounds errors crash our application
Have you ever seen an
ArrayOutOfBoundsException? I certainly have.
It happens when you try to access an element outside the data structure.
In this case, the compiler will not help us.
A great way to overcome this exception is to go through the data structure using a loop. Alternatively, we can check that an element exists before we access it.
9. Disadvantage: Infinite loops stall our application
The compiler doesn't help us when we stare at the screen while there is a never-ending loop running in the background.
I encountered this problem in the past when using a while loop.
Indeed, it's better to use a for loop instead of a while loop to prevent this problem.
10. Disadvantage: Deadlocks and race conditions cause unintended behavior
The compiler doesn't help us with multithreading. And multithreading is an advanced topic.
Many problems (such as race conditions, deadlocks, and starvation) can occur with multithreading.
When does a race condition occur?
"A race condition occurs when a software program depends on the timing of one or more processes to function correctly."[TechTerms.com]
When does a deadlock occur?
"Both threads are locked, waiting for each other to unlock before continuing."
A deadlock can be solved using a lock, which checks whether a thread is free before moving on.
When does starvation occur?
The author of the book uses an excellent metaphor:
"The metaphor for it is a one-lane bridge where one side has to wait, but the stream of cars from the other side never stops".
A bit of curiosity: what's the difference between a compile-time and a runtime error?
Compile-time errors happen because of mistakes in the syntax or semantics. The programmer can quickly fix the error during compile-time.
Runtime errors happen during program execution. Fixing runtime errors is challenging because the compiler doesn't highlight runtime errors.
In this article, we went through the advantages and disadvantages of the compiler, and the difference between compile-time error and runtime error.
If you enjoy my content, consider subscribing to my newsletter.
Thank you for reading this article.
Until next time! 👋🏾