Just recently the SANS institute and MITRE published a Top 25 list of most dangerous programming errors that lead to cyber crime and other problems with websites. Experts from more than 30 organisations – including software companies, universities and the US government – collaborated in creating the list. One of the findings is that just a small number of errors cause the bulk of problems around nothing less than 1.5 million websites. Problems vary between sites simply ‘going down’ to theft of personal and financial information and complete computers being taken over from remote locations.
The list is well worth to read – it’s written in an unexpected, humorous style – and it is mandatory, educational stuff to software engineers and cyber criminals the like. However, the list notoriously misses the biggest cause for critical errors in software: simply too much software is still being coded. It shows that IT yet is a painfully immature profession. The practitioners stubbornly persist in creating their own problems and then – with great aplomb – come up with lists, articles, methodologies and books to solve them. It’s like turning all the taps on in the house and then proudly pulling out the newest, moist-absorbing mop. With more software being hand-coded, the risk of errors increases. And although many programmers may share a nostalgic sentiment on producing their code line by line, it does not serve efficiency or security.
The best way to avoid dangerous coding errors is to code less. Here are 7 ways to achieve that:
1. Reuse. More and more basis functionality is covered in frameworks and other reusable components, services and libraries. This material may have been developed within the organisation or by an external source. Because we are dealing with code that is approved for reuse, we may assume that the software has been thoroughly tried and tested, in any case well above average. The software only needs to be used, so no need to understand its inner working. This reduces complexity and – with that – the sensitivity to errors. Yet, many developers believe that even the most elementary services should be created by themselves. A harmful case of inflated ego, with a high price to pay for. Incidentally, explicit reuse leads to a shift in testing activities: the correct functioning and the reliability of external software gets the highest priority.
2. Generation. Better tools become available to generate code from design models and specifications, possibly even articulated in a semi-natural language. The most popular and standardised approach seems to be Model Driven Architecture (MDA) but keep an eye on Microsoft’s Domain Specific Languages (DSL’s) as well. Pioneers like software guru and former space tourist Charles Simonyi even work on concepts in which specification in various ‘business languages’ (for example a language to describe life insurance calculation rules) are continuously synchronised with programming code. Specifications on a higher level of abstraction are easier to understand and offer more expressive power. And from them, error-free and efficient code can be generated, obviously with the help of an exhaustively tested and optimised code generator. Biggest pitfall: developing the generator yourself, a dangerous hobby horse for bored programmers, looking for new challenges.
3. Standard packages. More and more organisations find that their existing, bespoke systems have turned into an impenetrable swamp. Maintaining them demands a disproportional amount of time. And the risk of errors only increases further with the original developers gradually disappearing or retiring, the documentation getting less up-to-date and the code starting to show obese features. Rebuilding the entire system on a modern platform is an option, but this will often turn into big, monolithic designs, massive programmes and – you get it by now – a higher risk of errors. In this context, standard packages and ERP now quickly become the unavoidable default, even in do-it-yourself bastions such as government and financial services. Let Waldorf deal with the bugs, that is roughly the way of reasoning. Of course, standard software must be carefully tested – just as bespoke solutions- and there is a catch: extensive customisation of a standard package is really the same as building solutions from scratch. Only more laborious and with bigger risks.
4. Get rid of own middleware. Back then, it seemed to make such good sense. Developing your own middleware and at one go deal with all these recurring, infrastructural software functions. But the years have gone by and the software industry has developed solutions that handle the same plumbing, only based on open standards and probably a lot more robust and effective. Here you are, with the Dialectics of Progress working on your stomach, saddled with complex and hyper-sensitive code that has lost its added value already a long time ago. It might a painful migration toward industry-strength solutions – possibly from Open Source – but eventually it will lead to relief and a more secure feeling. So let the alarm bells ring whenever developers are working on their own Enterprise Service Bus, transaction monitor, application server, database, portal, GUI handler or object-to-relational mapper.
5. Isolate process logic and business rules. With a whole new generation of Business Process Management (BPM) and Business Rule Engine (BRE) platforms emerging, developers must seriously ask themselves why they are still hard-coding process logic and business rules into their software. Defining logic and rules together with the actual business users – applying a language that is easily understood at the business side – not only saves on the volume of code but also bridges the gap between business and technology: an area where most of the misunderstanding still starts. And for that matter, the same principle applies to business intelligence solutions: reports, scorecards and dashboards nowadays are clicked together with specialised tools, without any programming. And of course, externally defined business rules and process logic can also contain errors, but the sensitivity to ‘real’ bugs and threats from outside clearly decreases.
6. Avoid complex constructions. Useless complexity in IT, sooner or later we will have riots in the streets because of it. Developers swarm like flies around complex constructions as dynamic polymorphism, multiple inheritance en xml-to-object-to-relational mapping (and vice versa). It’s not that they actually need these constructions. It’s more about being attracted by the wrong category of heroic, juicy challenges; just because they can. Why would you store your information straightforward in a simple, relational database, maybe accompanied by some SQL triggers, if you can do the same in that shiny new, perfectly incompatible object-oriented system? Including all the monstrueus mappings, morphing, translations and conversions that needs to be built, it provides a much more satisfactory experience. Professionally speaking, that is. And on the rebound, many programming languages evolve in the same direction. Java – with all its additional features has become top-heavy and even the childishly simple Basic language is overfed with confusing capabilities. Achieving simplicity is the single most important challenge to every software engineer. With less distracting constructions to oversee, the mind stays cool and calm. Eventually that leads to less code and less incomprehensible errors.
7. Simple programming tools. Speaking of programming languages: if we take the other 6 measures seriously, sooner or later we might notice that there is not that much programming left to do. Maybe we want to stick to orchestrating services and gluing components. Our users may be clicking their own solutions together, in true mash-up style. Who knows, we might be adjusting process logic ‘on the fly’ by configuring graphical process models or semi-natural language definitions. A good time to reconsider. Do we really need difficult, error-prone programming languages as Java and C# anymore? Honestly? With simplified, yet highly expressive tools – without all the seductive side-roads and unnecessary whistles and bells – we achieve maximised results with a minimum of code.
If you don’t write code, you cannot produce errors. It is as simple as that. The Top 25 list of most dangerous programming errors is and stays relevant. But our dependency on it can be decreased, just by staying out of the wrong neighborhoods. Nothing less than a cultural landslide to a profession that from way back likes to look for trouble.