Added on 27/01/2017
"Why should I care about how my code is written, as long as it works?" I have met with this attitude many times, especially around academics, but also among software developers. We are often faced with deadlines that demand the results of our simulation or software. The code behind the applications remains forever hidden, it is not formally assessed, and therefore might seem unimportant. However, I will argue here that well-structured and well-written code not only saves time on a project, it also helps you to invest your time in a way that is meaningful for your future work.
Design vs coding
The first important topic is that of design versus coding. By "design" I mean the time before we start programming, during which we think about how data will be stored and retrieved, what classes (in object-oriented programming) or modules (in functional programming) will be used and how they will relate to each other, what kind of actions will the user need to perform to get from A to B, etc. This kind of design is usually performed by a coder with the help of diagrams, such as flowcharts, statecharts, class diagrams, etc. (see the image below). When done correctly, it provides an overview of how an application or a simulation will work and how it will be built. More importantly, functionality can easily be redesigned and discussed among programmers, as well as with people who know nothing about coding.
Code implementation takes much longer than the design stage. For example, it is much faster to draw two boxes for "Text file" and "Simulation engine" and an arrow between them to signify that the simulation engine writes data into a text file, than actually implementing this in a programming language. This is why as much time as possible should be spent on the design stage. Furthermore, designing code this way can help you to keep an eye on "the bigger picture", without being distracted by particular implementation details. If the design stage is rushed through, or even worse, if it never happens at all, it is almost guaranteed that time will be lost for creating bad code that will need to be scrapped or rewritten later. For example, imagine that when implementing another part of the simulation, we realise that we actually need to store our data in a database. All the time spent writing code for text file storage will be lost.
Good coding practises
The second important point to consider is coding practises. It is possible that even if we take good care when designing our software, something will need to change or be extended along the line. Therefore, program code should always be written as clearly as possible and be well-organised. For example, the following can help:
- Well-structured coding project: Related classes and modules should be kept together in a meaningful way in packages, namespaces, etc. For instance, classes or modules that are responsible for data storage should be clearly distinguished from those that provide user interface.
- Naming conventions: There are no universal naming conventions that need to be followed, but we need to be consistent in a single project. Naming variables sensibly and with lower-case letters, starting class names with upper-case letters, starting pointer names with a 'p', or capitalising names of constants are just a few examples of conventions that can be maintained.
- Good documentation: There are two types of documentation that are equally important. Commenting code is crucial to help others and yourself to understand the code that has been written. This could include a text block on top of your class, module or function to explain what it does, comments next to variable definitions, or comments inside functions that explain specific lines of code. The second type of documentation is more 'high-level' and ties back to the design stage. If you have created a class diagram, make sure to include it with the project and update it when something in the code changes. If there is a complicated way of gathering or displaying data, make sure to document it in a text file somewhere. In other words, write down or draw anything that could be unclear later on.
Good coding practises can save an incredible amount of time and stress when it comes to altering, reusing and extending code. There are few things more annoying or stressful for a developer than having to work with code that cannot be understood even after being read five times. Some coders seem to be under the impression that spending the extra time to properly document or structure code is not as crucial when working alone or with a small group of people, where any questions can be simply answered by the person who wrote a particular piece of the software. I would like to challenge this attitude in three ways:
- 1. You never know when the person who wrote the code will not be available anymore to answer questions. If there is no written record of how their code works, who will you turn to?
- 2. You never know whether the size of your team will grow later on. Writing documentation at a later stage of the project, so that a larger team can manage and understand the software, can quickly become a nightmare that takes away precious resources.
- 3. You might want to use your code in one, five, or N years after you have written it. You simply cannot be certain that this will never happen. This applies when working in a team or when working alone. If you don't help yourself understand your code now, it will be very difficult to understand it later.
I have found it a good idea, when working in a team, to designate a person who can keep an eye on common code. For example, the person could check every week or every month if the agreed conventions are being applied, if documentation makes sense, etc., and ask relevant people to put more work in if this is not the case.
In my opinion, the following is a good way of thinking about code, be it for a scientific simulation, for a commercial software project, or even for a small script that does something useful: Take care of how you write and document. Think of your code as an investment for the future. You are inventing a unique piece of functionality right now, so make sure that you can always use it when you need it later. In other words, code not just for today, but also for tomorrow.