The Short Guide How To Write Bad Software


By Stan Bleszynski (aka Heretic)                              15-June-2006



Even though there is no shortage of good examples of bad software, I decided to present and systematize some of the most productive techniques helpful in producing and maintaing bad software, with short explanations and comments.


#1.  Use message-passing schemes for inter-task communication (as oposed to function or function table based systems).


This is in my humble opinion the most effective method, widely used with tremendious succeses in the most popular operating systems,  ensuring that the excution speed will scale as 2^N where N is the measure of algorithmic complexity, and that the flow of message passing will be almost impossible to comprehend at the source level due to an inherent lack of hierarchy, be virtually untraceable at run time and exhibiting a pseudo-random behavior.


#2.  Use interrupts for everything.


 A traditional justification of using interrupts (sparringly) only for those externally driven asynchronous events that cannot be handled efficiently in any other way, gave way to the widespread practice pioneered with the advent of a certain popular disk operating system and perfected with the introduction of multitasking operating systems.  Using interrupts as opposed to polling ensures that the response speed not only slows down due to overheads in most CPU’s with large register base, but also unpredictable.  Additional “benefits” are the loss of hierrarchy and structure due to the hardware-enforced  flat structure of interrupt handing vector tables, lower transparency at the source level, reduced source portability and more difficult debugging.


#3.  Use C++.


C++ offers programmers many “benefits” and obfuscation opportunities unmatched in other programming languages.  The reliance on multiple header files not only make the source code harder to follow but allows disposing with the idea of code reusability through binary libraries.  In addition, this language has also protected us to a large extent, from code sharing at the source level through a non-immediately apparent but a subtle and brilliantly implemented class trap.


#4. Use data-oriented programming style (as opposed to function-oriented).


Data oriented style allows for a much greater code obfuscation, through creation of multilevel data structures or objects that require browsing back and forth between definitions and instantiations, and makes it much harder to decouple the source code into modules.  This also permits and in fact enforces construction of functions that take such structures or pointers as arguments ensuring that changes to such parameters are hard to track or at least hard to understand at the source level.  It also makes the source code much more resistant  against attempts to upgrade or modify ensuring scrap-and-rewrite as the only option.


#5.  Allocate memory dynamically as often as possible.


Not only it presents us with the exciting possibility of creating invisible memory leakage schemes but also aids in planting uninitialized pointers or related bugs. 


#6.  Avoid exception handling using jumps with ‘goto’ instruction.


The dreaded instruction ‘goto’ has gone out of fashion so long ago that many programmers might not have heard of it.  It used to be blamed fo all sorts of programming  evil.  Instead of risking being blamed for using obsolete programming style why not just use some multilevel nested logic and multiple flags?  The added “benefit” is that the source code becomes nicely convoluted and incomprehensible.


#7. Use general purpose project planning methods.


Usage of project planning in software development, such as Gantt charting of individual modules, critical path analysis etc. has been generally neglected in software but in recent years many of the large software companies have been adopting them. With great results.  However certain modifications to standard techniques were found to be necessary, for example replacement of weekly time scale with years.


Always consider individual software tasks as unitary pieces of work that should not in theory be any different  from, for example carving a specified amount of rock from a quarry.  Assuming that every task must have a beginning and an end will help achieving the title objective.


#8.  Separate management tasks from software coding tasks.


This will ensure that no individual programmer will be distracted with a “big picture” or other information not related to his/her specific task.  The issue of work motivation should be handled by human resource department using “employee of the month” awards, corporate picnics etc.


#9. Maximize the output of your best software team by reassigning them to a new project development as soon as an old one is launched, handing over the maintanance and follow up to other ad-hoc assigned people, not previously involved.


This is obvious, since the cash flow is determined largely by the new releases it is not prudent to allocate precious resources to something that has already been sold.


#10.  Assume that rules have no exceptions.