The best code has clearly defined variables, has been cleaned up by removing excessive debug statements and/or commented out unused code snippets, and the behavior of the code, as well as the “what”s and “why”s for coding decisions, is clearly documented. I know we have all heard these stressed numerous times throughout our coding education and experiences, but when these principles are not applied it can have extreme negative impacts on a sprint schedule and resource allocations.
This past week I had the opportunity to evaluate some test failures around a chemical solubility model and a solver type function using mixed composition waste as inputs, thermodynamic and reaction kinetics as internal methods of the requirement driven design specification, and a solver function that takes the information from those methods, along with the chemical compositions, and generates a convergent recipe of chemicals to add to the input tank to result in the desired end product. Normally this type of “meaty” test failure is something I love biting into and reworking. But this code, and the documentation with it was so cumbersome and filled with “dead” code and convoluted, and sometimes circular pathways that I wanted to scream and pull my hair out atleast twice every day. This blog started out as a end of the work day rant, but I am done “scream typing” and am ready to learn from these lessons and logically look at some examples below.
- Clearly Defined Variables
There are so many ways that people have for creating variable names. It is a limitless combination of letters and numbers and cases (camel, snake, etc). But each variable needs to mean something to the reader. I don’t mean the computer code that parses the information in program. But instead I mean a person doing code reviews or trying to debug and/or walk thru the code. In the code that I was working with this week there were variables named xMin, xMax, xCurrent, xLeft, xRight, xLast, xNext, xRoot1, xRoot2, xfnMin, xfkMin, xNextLast, etc. I think you can see the pattern that the person writing the code was using. If these variables were all part of a calculation for “x”, and if each were clearly defined on what they mean or how they were used, it might be ok to do this. But in this instance “x” means nothing. Left was not related to right. Next and Last were in two separate conditionals that never were related. And these values were all reused continuously through ~300 lines of code. Don’t do this. Make the variables relatable. Make the variable names mean something. Max and Min were the only two remotely close to being related and also used how one might expect. Decoding these variable names ended up taking 3 people and lots of white board time to break it down into pieces that were understandable.
- Clean Code
As the input to the solver function mentioned above, the calling methods copy the chemical composition of a single tank and manipulate that copy with reactions, temperature partitioning, and phase changes from liquid to solid, as an example – the settling of precipitates from the reactions. In this instance, the correlations used to do all of this have come through various temperature and composition dependent calculations based on the calculation used in the final tank end product. Over the 20+ years I have worked where I do there have been 18 different correlations. Each manipulating copied tank compositions, and sometimes making copies of copies. All 18 different ways were STILL in the code that I was working through this week. Some of them were even circular and called a correlation with a different input to get a different pathway through the muck. 95% of this was dead code. Only it wasn’t dead because a conditional was used to throw the dead code into one part of the conditional and the current correlation into the other part of the conditional. In the end we were able to cut these 18 different correlations into 4 with a very linear and clearly defined pathway. Clean up your old code. If something isn’t going to be used- get rid of it. Now days there is so much storage, backups and ways to go back and retrieve a bit of code if for some reason you couldn’t possibly recreate it better by writing it anew.
- Document With Comments
Comments – None of the code mentioned above had any comments. You might have expected a lot of unneeded commenting with all the circular references and legacy code. But there wasn’t. And back when most of these correlations were first drafted the requirements documentation was severely lacking. The hours spent at the white board trying to understand what the code was intended to do, what our client needed it to do, and what to cut out or leave in could have been used elsewhere. Use comments smartly, clearly, no big explanations- that is for requirements or user stories or any of the other tools to document these types of things. Give simple descriptions for the what: “Used to generate a lower limit for the ALOH3 target molarity”, “Pathway for ALOH4 dependent on sodium convergence of root1 and root2”. Maybe these are not the best descriptions for this class, but anyone looking at the chemistry of the tank will understand that ALOH3 is being adjusted to some target. That target depends on sodium. The end product will be ALOH4 at root1 or root2. Comments and documentation in general, matter.
So what were my big ‘lessons learned’ this week? I learned that each time I sit down to write code I should plan the layout of the program in a way that is clean of cluttered comments and junk code. I learned that even programs that may rarely ever get looked at again need to have clear variable names to understand how the input parameters and internal methods and structure work in the code. Without this, code tracing and debugging is spent wasting time that wouldn’t have otherwise been needed to identify bugs. And lastly, I learned that just because something is clear to me, that I think the coding task is trivial or intuitive, or that anyone with a similar background to mine will easily be able to follow along and understand… comments are the best way to explain a bit of code to the future developers. Always strive to comment and document the functionality, intent, reasoning, even if it is only one line with a requirement number of a bug ticket number… anything that can be used to identify it later are necessary in striving to follow good coding practices.