When I look at a strand of spaghetti on my plate, I really cannot figure out where it started or where it ends. It can be unraveled, but with the sauce, cheese, and meatballs in my way it would be time consuming and, probably, an awful mess. While it may be tasty, it lacks structure. This lack of organization and structure is where spaghetti code derives its name. Badly formed code is usually discovered when there is some need to modify it: an upgrade of the code due to an operating system change, a new feature request, or troubleshooting a bug in the overall operation of the application.
To speak of spaghetti code on the factory floor is unusual as most process control systems work with configurations, not code. Occasionally, an end user may have need that calls for a large software development effort or a project may require a custom application to provide a complete solution.
When presented with such a need how do we make sure that code is well organized, easy to maintain, and that we can see all of the strands, from beginning to end? Here’s how:
It may go without saying, but it is hard to take a journey without knowing how you will get there. A well thought-out design that has customer input is less likely to experience last minute and ad hoc changes in the field or following the factory test. The code that generally results from this type of crunch is more likely to be the proverbial band-aid where the rush to make it work and get it running leads to poorly documented and badly formed code.
To help avoid this, start by generating a set of user requirements. It needs to capture the actions the software needs to take on a regular basis, the operations it must do occasionally, as well as error and exception handling that may never occur in the field.
Develop a design document (or design documents for larger projects) and start to incorporate the concepts of modularity here. The use of flowcharts to show how the modules will interact in your software architecture will make the design more readable for those who are not trained programmers.
Bringing your customer along for this journey is very important. Share with them your take on the Use Cases or user requirements to ensure a common understanding. Have them comment on the design document and review it with them in person, if possible. This will not entirely eliminate changes that must be made once the software is in place, but it will help ensure that everyone has a common understanding. More importantly, the changes made will be in the context of an organized application and can be made in such a way as to minimize overall impact.
Modularity in code can help with readability by organizing a program into smaller and more manageable pieces. Object oriented design leads to modules that can perform specific functions and that have their own scope and variable sets. By dividing the code in this way each component may developed, tested, and debugged separately.
A well-designed modular program is easier to maintain and update. New modules and features that are developed and incorporated into an existing program do not necessarily require a full test of the code. Instead, impact testing of the module may be performed in the spaces where the new module interacts with the program. Finally, troubleshooting time can be greatly reduced because the task of evaluating and prioritizing where to look in the code is easier. Whole sections of code may be eliminated as the source of the problem allowing the developer to quickly narrow in on the source of any problem.
Naming conventions and comments are integral to understanding how a particular piece of code fits with the rest of the program or the nuances of how the lines in a function interact with each other. Take the example below.
This code has structure, the variables have names, there are comments, and I can generally tell what the code is going to do given the results of the conditional if statements. Without any additional context, though, this code could be anything. While the comments are technically correct, they do not add to the understanding or readability of the function.
If, instead, the variable and object names were related to their actual purpose and the comments contained more details about the overall point of the lines of code then it might look something like this.
Readability is greatly improved in this example. If someone is maintaining this code and looking for a problem or researching a change related to the shipping light switches, they would know they are in the right place. If not, they could move on without too much examination.
Less is better but it takes more time and training to produce less code that does the same job. One of the early mistakes in the software industry was measuring productivity in lines of code written. Unfortunately, it made the erroneous assumption that all the lines were good and/or necessary. For example, which is easier to follow:
In this short example it is relatively easy to see how the code can be simplified. In more complex code a trained software developer will end up providing a program with a tighter structure than one with minimal or no training given the same set of functional requirements.
ACE will always recommend using off-the-shelf software when it is available from our vendor and manufacturer partners. Custom software can help fill the gaps that commercially available software may not handle. With planning, good organization, and a thoughtful implementation your custom application can be written so it is readable and more easily maintained.