Today I would like to write about a topic that many developers tend to overlook, not because their lack of analytical skills but rather their overenthusiastic approach to coding or sometimes even deadline pressure from the top. However, we will learn how to cope with these problems and develop a fail-proof way of getting your planning (to 97%) right.
We all know that feeling: We have an idea for a project and are burning all motivated like kids on Christmas day to write the first lines of code. Test after test, error after error and coffee cup after coffee cup the moment arrives when we have a first working version. The big relief is: We don't know why it works but it works. The big problem is: We don't know why it works but it works!
We keep working on our app and just building feature after feature and testing carefully that everything works together like if we were building a toothpick tower...
...Uuuuuntil it collapses. Suddenly, the div we just added breaks our beautiful grid (of course, we did not check out yet how it looks on Internet Explorer but we don't want have nightmares) and we get "undefined" all the time in the console. Worse yet, while trying to fix it, we get so many red error messages that our console makes the Red Sea look small.
We have no idea how to debug it and the fact that most difficult functionalities were patched together thanks to code from Stack Overflow makes it really to figure out what the hell is going on. Even your cat and debugger duck try to hide from the horrendous code smell and you have no more allies on your team to help.
Here there are only two options: Rebuild your app from scratch or go checking piece by piece what could be wrong. The second option is only recommended if your app is big enough.
In any case, the most common outcome is that, don't matter how you'll handle the situation, you will think that it was your bad "coding skills" and not the planning skills and will suffer impostor syndrome.
Of course, there is the other typical scenario where you are given the task to expand or improve an existing app. Let's say: Someone has a script that encrypts, moves and decrypts files from one directory to another. Your task is to expand it to two target directories instead of only one. The second directory is for odd ID's and the first one for even ID's.
We accept this task and are over-optimistic that we'll get it done in twenty minutes including testing. In the end it seems so straight-forward and easy: Instead of one directory I put two and make and if-else to determine to which directory every file should go. Yeah...Easy until you try to make it...
You don't get why the second directory gets flooded with all files while the first directory has gotten no files at all! It is possible that in the if-else you've written, the "if" always yields false because you are checking for a string instead of a number. Yeah, that must be it...So you correct it, and it still goes wrong. Your colleague comes to help you. A fresh view of things is always good. And he finds out what is going wrong:
You put the condition at the very top, before even the ID's of the files are even set. Of course, then all files get moved to the second directory!
Your colleague steps in and corrects it for you. You feel sad and incompetent. You think to yourself "How in the world can I be so bad at programming? Why is everyone better than me?". You shouldn't answer these questions however, since they will dig you deeper into the hole of hopelessness. What you should be asking instead is "why did this happen and how could I have avoided it?". Additionally, as an extra, we should figure out a general approach to similar situations. Every situation will be different but if we approach them in the beginning the same way, it is very possible after a short time that we'll see a pattern of similarities.
So, basically, the solution to both of these presented problems lies in the initial approach and it should be the following:
For the first scenario, figuring out how we want the layout to be and designing the algorithms first to not repeat/misuse logic chunks would have been ideal. Additionally, ignoring to understand "why" something worked did not help at all. This approach of "blind coding" should be avoided at all costs, especially if we are dealing with critical code.
For the second scenario, a better algorithm design of the condition and what it really does was crucial. However, for expanding code that already exists the most important thing is to check first where we should add our code. For that, we need to do an entire analysis of the code at hand, or at least of the functionality we are expanding.
Developing software requires a high level of abstraction. However and thankfully for us, most of us humans have a high level of creativity that we can use to help ourselves. So we don't need to be mathematical geniuses or chess masters, who can think their algorithms through in their heads with 0's and 1's. We can take analogies from real-life examples where we know what the outcome would be. Let's take for example building software like building in real life:
If you build a basic landing page (or script), you might not need any algorithm or thinking at all. You pull out the HTML and CSS and it's done. Just like a cottage. For a small cottage, it is very possible that making the plans takes longer than building the cottage.
On the other hand, most of the time you'll be building big, complex pieces of software where just "start coding" would be like a death sentence. Respectively, how would it feel if people plan to build an apartment complex and you say "Ok! Come on! Let's begin!" and start laying bricks without thinking about the state of ground (is it sandy? Is it solid?), how many floors it'll have, how many rooms will each apartment have, direction of the sun etc.
Especially for visual learners, the approach of imagining these abstract concepts with real-life examples can save your code from many bugs. And beyond code, everything you'll build/create from not working the way you want it.
Of course, you might be wondering: "How can I then handle with tight deadlines and angry managers that want it now and don't care about my code?"
Well, first of all, my opinion on that kind of managers is that they don't deserve any employee they have. So they should lose them all to realize that there is something wrong with them.
Of course, while on a project that is not always easy to say, but what you should just remind yourself every moment of what your tasks are as a developer: Design a way to solve a problem and solve it with the help of a computer. If a manager complains about you being slow, just remind him you did not plan the budge. Also, remind yourself that if you fulfilled your tasks, you should not worry about your worth as a developer. If you are a freelancer and you promised something too early, of course, you'll be held responsible. But again, if the project fails, analyze why and do not start thinking you are a horrible coder. Maybe your code was bad, but most of the time freelancers do not understand what the customer wants or promise too much in little time. Then you should work on communication and budget planning skills instead of blaming your ineptitude as a coder.
An additional resource I would like to present to you is a small resource that is very useful to me when designing an algorithm, especially if it takes input. I call it "The input handling table". It might be simple, but at least for me it proved itself very useful!:
With this, we put on the left column the possible input we expect and on the right column how it will be handled. A real vaccine against "uncaught exceptions":
|Possible input||How it'll be handled|
|Nothing||Prompt user to fill|