A Programmer's Biggest Mistake and How To Avoid It
A programmer must face many challenges throughout his/her career, however, there is one mistake that will almost guarantee failure. A mistake can be your best ally if you can control it. Care to know?
124
13
I Had No Clue
In all my years writing code and studying computer science, no one every told me that there was a difference between a programmer and a person that can write code. But most importantly, no one ever told me that if I knew the difference, and became a programmer, I would be spared hours of work. The good news is that you can, too, be spared hours of work.
Not knowing the difference between a programmer and one that can write code can be fatal, in fact, it is the most important ingredient in the preparation of a failed project. The difference is not is how the code is written, however. A person that writes code and is not a programmer will not necessarily write worse code than a programmer. Not everyone that can write code can be called a programmer. So, what is the difference between a person that can write code and a programmer?
Programmer versus One Who Writes Code
In almost any dictionary, a programmer is defined as a person that writes computer programs, but I do not fully agree with this definition.
Writing Code
It is important to note that in this article, a person that can write code is defined as one that produces well-written code. A programmer can too, produce well-written code. Well-written code is easy to read and understand, it performs the intended tasks, it is free of syntax errors, and it follows the fundamental principles of programming.
Here is an example (simplified) of code that could be better written:
int findIt(int arr[], int size, int n) { for (int i = 0; i < size; i++) if (arr[i] == n) return i; return -1; } int main() { int arr[] = {4, 9, 1, -14, 2, -20}; int size = 6; int res = findIt(arr, size, -1); res == -1 ? printf("Not found\n") : printf("Found at index %d\n", res); return 0; }
Here is the same program, but now better written:
#define NOT_FOUND -1 /* ====================================== = Finds and returns the index of the = = element n if found in array arr, = = otherwise, returns NOT_FOUND. = ====================================== */ int findIt(int arr[], int size, int n) { int index; bool found = false; for (int i = 0; i < size && !found; i++) { if (arr[i] == n) { found = true; index = i; } } if (!found) index = NOT_FOUND; return index; } int main() { int size = 6, arr[] = {4, 9, 1, -14, 2, -20}, result; // Store result of the findIt function result = findIt(arr, size, -1); if (result == NOT_FOUND) printf("Not found\n"); else printf("Found at index %d\n", result); return 0; }
What makes the second code better? For one, it is documented. Its intent is clear. All operations are easy to read. The variables state their purpose by using proper names or by clarification. It is a structured program instead of the spaghetti code in the first example. It makes use of constants to increase readability and reusability. The line width does not exceed a number of character that would make it less readable. Yes, the code is longer, but what is important is that is well-written.
Other than the ability to produce well-written code, a programmer must possess two skills that can almost be simplified into one.
Solve That Problem
A programmer does not only write code that works, rather code that solves a general problem. There is an important distinction between a problem and a problem instance. When a problem is solved, you have an answer for every answerable case, however, when a problem instance is solved, not all possible cases that can arise are addressed. This also means that a programmer produces code is free of logical errors–to the extent that is humanly possible.
Quality Code
A programmer writes quality code. Quality code possesses all the attributes of well-written code, but it is also optimized, without compromising readability. It is important that code be written in an optimal way, and that means that sometimes you will be required to find the time and space complexity of your algorithm and compare it to the best conceivable runtime (BCR). The BCR is the best runtime (time complexity) that can be conceived for a solution. However, it is important to note that the BCR is not always achievable.
Here is a 'isPrime' function that could use some improvement:
bool isPrime(int x) { bool prime = true; for (int i = 2; i < x && prime; i++) if (x % i == 0) prime = false; return prime; }
Now here is an improved version of the 'isPrime' function:
bool isPrime(int x) { bool prime = true; if (x <= 1) prime = false; else if (x % 2 != 0) { for (int i = 3; i * i <= x && prime; i += 2) if (x % i == 0) prime = false; } return prime; }
If you pay close attention to both code snippets, it is noticeable why the second segment is an improvement over the first one. For instance, the first snippet returns the wrong answer when the input is 1 or less. This is an example of a problem instance solution. Aside from that, the first snippet is testing cases that are not necessary; for instance, it should not test i if i > sqrt(x) because in that case i multiplied by any other number greater than or equal i is > x. Additionally, there is no need to test values of i that are even and greater than 2. If x is even and greater than 2, then it is divisible by 2, and thus is not prime, so we test for i = 2n + 1 (odd). The fist code snippet has a time complexity of O(x), however, the second one have a time complexity of O(sqrt(x)). If we had not simplified the runtime, it would be O(sqrt(x) / 2), which is even better.
The Extra Informational Edge (EIE)
Okay, I will admit that not every programmer possesses this attribute, but if you do, you are not just any programmer, but a great one. The EIE has to do with how well the programmer understands his/her environment; hardware and software. A programmer with EIE knows which function calls are more beneficial in certain scenarios, perhaps because of hardware and/or software implementation. The way the hardware is implemented can change every single decision a programmer with EIE makes, and the way that functions are written (software) can have a similar effect.
A programmer with EIE also understand that less is not always faster. A solution with a lower runtime does not always mean faster code. Sometimes, a tradeoff is made to ensure that the code is optimal beyond first instinct. A programmer with EIE works in context. To work in context means to know what your environment requires, and make tradeoffs accordingly. For instance, if you environment requires a large amount of memory, perhaps it is better to split your problem into multiple parts, regardless of it running a slower.
The Mistake
Now that the distinction between a programmer and a person that can write code is (hopefully) established, we can discuss what the the biggest mistake a programmer can make is. It's simple; in this article we've established how a programmer must be a problem solver, and the worst mistake a programmer can make is to prematurely write code.
Hands First versus Brain First
We are programmers, and we love and live to write code. That attribute is great because it keeps us motivated and moving forward, however, that love and raw passion that can work against us. When we are given a problem and immediate start writing code, we are using the hands-first approach. The hands-first approach may not seem like a huge mistake at first, but when the problem is large and complex enough and you have to rewrite your code, almost entirely and many times over, the perspective changes. I realize that the are many problems that do not require much thinking, but it's all about habit. There are also the small but tricky problems that we encounter all the time; those problems that seem very simple, and at first glance it seems like we have the solution, but we then realize that we've only solved an instance of the problem.
The brain-first approach is to first solve the problem. At this point we are not writing any code yet, rather, we are modeling the problem, and coming up with an algorithm to solve it. Note that in some cases you may get away with solving a problem instance because there are cases that seldom occur, however, it is always good practice to solve the entire problem. The problems that we solve we are likely to face again in different projects. Many times the problems are disguised, but if you use the brain-first approach, you can quickly recognize the similarity. The simple fact that you only write your algorithm once and that you solved a problem that you are likely to encounter again is almost a guarantee that you will save valuable time in your future projects.
Becoming A Programmer
Perhaps an even more important point is now, how do we become programmers? Well, with hard work, of course. There are tools that will help you in getting there, however. A book that I always recommend for those that want to become programmers is The Algorithm Design Manual by Steven S. Skiena. It teaches the fundamentals of designing an algorithm, from how to model a problem, to finding a solution, to expressing it in code. It also teaches about optimization.
Another book that is a great idea to have in your library is Cracking the Coding Interview by Gayle Laakmann McDowell. This is an essential book that talks about everything you need to succeed in a coding interview (and thus become a programmer). It discusses concepts such as Big-O, Technical Questions, Data Structures, among others.
Thank you for reading this article. If you think it would be beneficial for others, please share it on your different social media accounts. Also, I'd love to read what you think, so please leave a comment below.
124
13