The target groups
We can identify three target groups with increasing priority:
- The Compiler
- Other developers
- The client
It is worthwhile to take a closer look at each of them. As different as they may be, there are sometimes interesting interactions or even no similarities at all.
Let’s start with the compiler. This piece of program ensures, quite simply put, that the code produced by the developer is converted into machine language and can ultimately be converted into actions by the computer. This process also ensures that the syntax of the program code is correct. In the hierarchy “syntactically correct code -> technically correct code -> technically correct code”, it thus secures the lowest layer.
(The compiler is not very satisfied with my configuration, but it can still work.)
Due to the briefly outlined layer model, the compiler cannot guarantee that only technically correct code has been produced. Communication with the application database serves as an example: if a connection to the database is established, in some cases the developer must ensure that it is closed again as quickly as possible, even in the event of an error. Hardly any compiler can guarantee that this will actually happen. Well equipped developers are supported by their tools (“the best tools money can buy”). But even highly developed IDEs are far from being able to detect all errors during development. Here, reviews in partnership between colleagues and experience are the means of choice to initiate corrective actions at an early stage.
The technical nature of the application is also far beyond the reach of the compiler. Thus, it does not care about incorrectly implemented use cases and is dutifully converted into machine code. Some programming languages support the embedding of technical logic to a certain degree in such a way that violations lead to compilation errors. However, these are not very common and the degree of this support is usually so low that it is not worthwhile to rely on a less supported platform.
In summary, the compiler only cares if the syntax, i.e. the grammar of the code, is correct.
Let’s get to the target group of developers. Their task is to implement customer requirements in such a way that the use cases of the client are fulfilled. Developers therefore have a kind of translator’s task: to convert requirements, prepared by requirements managers and formulated in human language, into the syntax of the chosen programming language, while fulfilling both the functional and technical requirements of the desired work. As a result, developers have to deal with two major subject areas: Professionalism and technology.
Developers make a number of demands on code that are usually invisible to the client after delivery. These include, above all, maintainability. In general terms, this means ensuring that the code base can be further developed over several versions and often years. A good maintainability can be achieved by various means:
(Tools like SonarQube can use code analysis to estimate how maintainable a code base is.)
First and foremost, automated tests should be mentioned. Here, special test code is produced, which checks the productive code for business or technical correctness. In the best case, a code base is obtained that can prove that it meets the requirements of a business or technical nature. However, following the principle “every line of code is guilty, unless proven otherwise”, one gets into a dilemma: Who proves that the test code is correct? Isn’t test code also code and isn’t less code synonymous with fewer errors?
Realistically, however, every line of test code is considered to be absolutely valuable. This can be well demonstrated with a simple example: If a developer is supposed to implement a requirement, it is not proven beyond doubt that the existing code base works perfectly. By means of automated tests, however, he can convince himself that the test cases described in tests are error-free. This allows him to make his changes and use the tests to determine whether there were any undesirable side effects. Finally, new tests are produced which check the changes for correctness and thus have a documentary character. This workflow describes only one of many added values that automated tests can deliver.
Another tool that can be used to produce maintainable code is a uniform architecture. As the name suggests, the comparison with the construction industry is obvious and highly appropriate. Not least because a house without a solid architecture will not survive the coming years, most developers will consider a solid architecture a must even with a code base.
Simply defining the term architecture in terms of code has failed as often as it has been tried. This is due to the fact that it is almost arbitrary in scope and can be applied to the most diverse domains. Thus, different architectural styles can be applied to different areas of a code base and be particularly efficient there, while at the same time ensuring at different levels of detail that code has been structured in consistent patterns. It is therefore generally accepted that the architecture of a software is the sum of all strategic decisions regarding the code structure. It is best if these decisions were made jointly by the development team or at least co-developed and accepted by the team.
If the software project is a customized solution, the third target group quickly appears on the scene: the client. This includes automating work steps or allowing systemic help for the first time in processes that previously had to be carried out completely manually. Other companies, on the other hand, have already collected data volumes that cannot yet be evaluated. This is where customized reporting solutions can help, providing insights into operational processes and uncovering potential. These two categories mean that they are not technical in nature and operate at a higher level than a single function can map from a business perspective. It is the long-term goal that the solution is intended to achieve, the vision.
However, the client does not only exist as a target group in the case of custom-made software, but also in product development, where there is a whole market of clients. Here it is much more difficult to define the concrete vision of the project. Rather, the vision of the product developers has to fit the needs of a rather unknown number of customers, who try to fulfill their own needs with the product.
Besides the vision there are a number of implicit requirements for the resulting software. For example, it should be able to complete its tasks in a reasonable time, be user-friendly and possibly run on mobile devices. At the very latest, security must be taken into account for applications that communicate with the open Internet. To make these requirements, if they are implicit, quantifiable and explicit, is an important task and should never be ignored.
Last but not least, a client has an implicit requirement for the software, which will probably never be included in the specifications: a function whose implementation costs X today should still cost X in a year’s time, or its costs should not differ greatly from this sum. This requirement creates a direct link to the requirements of other developers for maintainable code. Whole books, workshops and conference presentations deal with the topic that software that exists for a significant period of time is more costly to maintain and extend over time. This happens when the architecture chosen for a code base no longer meets its requirements or erodes due to poor maintenance. Even if software does not wear out with use like a car, it must be maintained in the long run, especially if many changes are made. This requirement creates a direct link to the requirements of other developers for maintainable code. Whole books, workshops and conference presentations deal with the topic that software that exists for a significant period of time is more costly to maintain and extend over time.
Is that all?
Of course not! As different as people, companies, customers and use cases are, so many requirements and target groups of code exist. Everyone has his own ideas about how software should work. Ultimately, however, all these ideas can be broken down to code that people have to formulate. And that this process works smoothly is not the task of a single programmer, service provider or client.
Project success can only be achieved if this triumvirate with each other works.