30 rules to make your code unmaintainable

This is how jobs are created

Imagine developers wrote nice, simple and maintainable code. That would be terrible!
You should instead learn from the best, ensure that nobody after you will be capable of understanding any of your work, make sure that the simplest fix or modification will take a whole team of developers.
Your efforts won’t go unnoticed. Your colleagues will love you for making sure they have countless hours of guaranteed employment, and your employers will think you are the only genius capable of understanding the complexities of their awesome codebase.
In this article you will find the 30 best rules you can follow to spice up your code and make it interesting.

Unmaintainable code is the engine powering the economy! Unmaintainable code is glory for the brave! Unmaintainable code makes you the hero everybody loves! Hail unmaintainable code!


Disclaimer

This list has been shamelessly copied from its original source in:

http://mindprod.com/jgloss/unmain.html

I essentially took it and curated the list to the ones I have most frequently suffered for the last 15 years (the original list is massive and takes ages to go through). You will for sure identify some of your colleagues’ behaviour here, and even find out that you yourself do some of these (or don’t play much attention to them). Well done, you already are on the right track ¬_¬

Just to set you up in the right mood, remember this wise proverb by XKCD


1. Creative Miss-spelling

If you must use descriptive variable and function names, misspell them. By misspelling in some function and variable names, and spelling it correctly in others (such as SetPintleOpening and SetPintalClosing) we effectively negate the use of grep or IDE search techniques. It works amazingly well. Add an international flavor by spelling tory or tori in different theatres/theaters.

2. Be Abstract

In naming functions and variables, make heavy use of abstract words like it, everything, data, handle, stuff, do, routine, perform and the digits e.g. routineX48, PerformDataFunction, DoIt, HandleStuff and do_args_method.

3. A.C.R.O.N.Y.M.S.

Use acronyms to keep the code terse. Real men never define acronyms; they understand them genetically.

4. Thesaurus Surrogatisation

To break the boredom, use a thesaurus to look up as much alternate vocabulary as possible to refer to the same action, e.g. display, show, present. Vaguely hint there is some subtle difference, where none exists. However, if there are two similar functions that have a crucial difference, always use the same word in describing both functions (e.g. print to mean “write to a file”, “put ink on paper” and “display on the screen”). Under no circumstances, succumb to demands to write a glossary with the special purpose project vocabulary unambiguously defined. Doing so would be an unprofessional breach of the structured design principle of information hiding.

5. Code That Masquerades As Comments and Vice Versa

Include sections of code that are commented out but at first glance do not appear to be.

for(j=0; j<array_len; j+ =8)
{
    total += array[j+0 ];
    total += array[j+1 ];
    total += array[j+2 ]; /* Main body of
    total += array[j+3 ]; * loop is unrolled
    total += array[j+4 ]; * for greater speed.
    total += array[j+5 ]; */
    total += array[j+6 ];
    total += array[j+7 ];
}

Without the colour coding would you notice that three lines of code are commented out?

6. Lie in the comments

You don’t have to actively lie, just fail to keep comments as up to date with the code.

7. Document the obvious

Pepper the code with comments like /* add 1 to i */ however, never document wooly stuff like the overall purpose of the package or method.

8. Document How Not Why

Document only the details of what a program does, not what it is attempting to accomplish. That way, if there is a bug, the fixer will have no clue what the code should be doing.

9. On the Proper Use of Design Documents

When implementing a very complicated algorithm, use the classic software engineering principles of doing a sound design before beginning coding. Write an extremely detailed design document that describes each step in a very complicated algorithm. The more detailed this document is, the better. In fact, the design doc should break the algorithm down into a hierarchy of structured steps, described in a hierarchy of auto-numbered individual paragraphs in the document. Use headings at least 5 deep. Make sure that when you are done, you have broken the structure down so completely that there are over 500 such auto-numbered paragraphs. For example, one paragraph might be (this is a real example)

1.2.4.6.3.13 - Display all impacts for activity where selected mitigations can apply (short pseudocode omitted).

then… (and this is the kicker) when you write the code, for each of these paragraphs you write a corresponding global function named:

Act1_2_4_6_3_13()

Do not document these functions. After all, that’s what the design document is for!

Since the design doc is auto-numbered, it will be extremely difficult to keep it up to date with changes in the code (because the function names, of course, are static, not auto-numbered.) This isn’t a problem for you because you will not try to keep the document up to date. In fact, do everything you can to destroy all traces of the document.

Those who come after you should only be able to find one or two contradictory, early drafts of the design document hidden on some dusty shelving in the back room near the dead 286 computers.

10. Avoid Encapsulation

In the interests of efficiency, avoid encapsulation. Callers of a method need all the external clues they can get to remind them how the method works inside.

11. Clone & Modify

In the name of efficiency, use cut/paste/clone/modify. This works much faster than using many small reusable modules. This is especially useful in shops that measure your progress by the number of lines of code you’ve written.

12. Dummy Interfaces

Write an empty interface called something like WrittenByMe, and make all of your classes implement it. Then, write wrapper classes for any of Java’s built-in classes that you use. The idea is to make sure that every single object in your program implements this interface. Finally, write all methods so that both their arguments and return types are WrittenByMe. This makes it nearly impossible to figure out what some methods do, and introduces all sorts of entertaining casting requirements. For a further extension, have each team member have his/her own personal interface (e.g., WrittenByJoe); any class worked on by a programmer gets to implement his/her interface. You can then arbitrarily refer to objects by any one of a large number of meaningless interfaces!

13. Mix and Match

Use both accessor methods and public variables. That way, you can change an object’s variable without the overhead of calling the accessor, but still claim that the class is a “Java Bean”. This has the additional advantage of frustrating the maintenance programmer who adds a logging function to try to figure out who is changing the value.

14. Modify Mom’s Fields

In Java, all primitives passed as parameters are effectively read-only because they are passed by value. The callee can modify the parameters, but that has no effect on the caller’s variables. In contrast all objects passed are read-write. The reference is passed by value, which means the object itself is effectively passed by reference. The callee can do whatever it wants to the fields in your object. Never document whether a method actually modifies the fields in each of the passed parameters. Name your methods to suggest they only look at the fields when they actually change them.

15. Local Variables

Never use local variables. Whenever you feel the temptation to use one, make it into an instance or static variable instead to unselfishly share it with all the other methods of the class. This will save you work later when other methods need similar declarations. C++ programmers can go a step further by making all variables global.

16. Subclass With Abandon

Object oriented programming is a godsend for writing unmaintainable code. If you have a class with 10 properties (member/method) in it, consider a base class with only one property and subclassing it 9 levels deep so that each descendant adds one property. By the time you get to the last descendant class, you’ll have all 10 properties. If possible, put each class declaration in a separate file. This has the added effect of bloating your INCLUDE or USES statements, and forces the maintainer to open that many more files in his or her editor. Make sure you create at least one instance of each subclass.

17. Casting

Pass all data as a void * and then typecast to the appropriate structure. Using byte offsets into the data instead of structure casting is fun too.

18. Numeric Literals

If you have an array with 100 elements in it, hard code the literal 100 in as many places in the program as possible. Never use a static final named constant for the 100, or refer to it as myArray.length. To make changing this constant even more difficult, use the literal 50 instead of 1002, or 99 instead of 100-1. You can further disguise the 100 by checking for a == 101 instead of a > 100, or a > 99 instead of a >= 100. Consider things like page sizes, where the lines consisting of x header, y body, and z footer lines, you can apply the obfuscations independently to each of these and to their partial or total sums.

These time-honoured techniques are especially effective in a program with two unrelated arrays that just accidentally happen to both have 100 elements. If the maintenance programmer has to change the length of one of them, he will have to decipher every use of the literal 100 in the program to determine which array it applies to. He is almost sure to make at least one error, hopefully one that won’t show up for years later.

There are even more fiendish variants. To lull the maintenance programmer into a false sense of security, dutifully create the named constant, but very occasionally “accidentally” use the literal 100 value instead of the named constant. Most fiendish of all, in place of the literal 100 or the correct named constant, sporadically use some other unrelated named constant that just accidentally happens to have the value 100, for now. It almost goes without saying that you should avoid any consistent naming scheme that would associate an array name with its size constant.

19. Exceptions

I am going to let you in on a little-known coding secret. Exceptions are a pain in the behind. Properly-written code never fails, so exceptions are actually unnecessary. Don’t waste time on them. Subclassing exceptions is for incompetents who know their code will fail. You can greatly simplify your program by having only a single try/catch in the entire application (in main) that calls System.exit(). Just stick a perfectly standard set of throws on every method header whether they could actually throw any exceptions or not.

20. Use threads With Abandon

title says it all.

21. Never Beautify

Never use an automated source code tidier (beautifier) to keep your code aligned. Lobby to have them banned them from your company on the grounds they create false deltas in PVCS/CVS (version control tracking) or that every programmer should have his own indenting style held forever sacrosanct for any module he wrote. Insist that other programmers observe those idiosyncratic conventions in “his ” modules. Banning beautifiers is quite easy, even though they save the millions of keystrokes doing manual alignment and days wasted misinterpreting poorly aligned code. Just insist that everyone use the same tidied format, not just for storing in the common repository, but also while they are editing. This starts an RWAR and the boss, to keep the peace, will ban automated tidying. Without automated tidying, you are now free to accidentally misalign the code to give the optical illusion that bodies of loops and ifs are longer or shorter than they really are, or that else clauses match a different if than they really do. e.g.

if(a)
  if(b) x=y;
else x=z;

22. Hide Error Recovery Code

Use nesting to put the error recovery for a function call as far as possible away from the call. This simple example can be elaborated to 10 or 12 levels of nest:

if ( function_A() == OK )
    {
    if ( function_B() == OK )
        {
        /* Normal completion stuff */
        }
    else
        {
        /* some error recovery for Function_B */
        }
    }
    else
        {
        /* some error recovery for Function_A */
        }

23. Your Boss Knows Best

If your boss thinks that his or her 20 year old FORTRAN experience is an excellent guide to contemporary programming, rigidly follow all his or her recommendations. As a result, the boss will trust you. That may help you in your career. You will learn many new methods to obfuscate program code.

24. Book Of The Month Club

Join a computer book of the month club. Select authors who appear to be too busy writing books to have had any time to actually write any code themselves. Browse the local bookstore for titles with lots of cloud diagrams in them and no coding examples. Skim these books to learn obscure pedantic words you can use to intimidate the whippersnappers that come after you. Your code should impress. If people can’t understand your vocabulary, they must assume that you are very intelligent and that your algorithms are very deep. Avoid any sort of homely analogies in your algorithm explanations.

25. Compiler Warnings

Be sure to leave in some compiler warnings. Use the handy “-” prefix in make to suppress the failure of the make due to any and all compiler errors. This way, if a maintenance programmer carelessly inserts an error into your source code, the make tool will nonetheless try to rebuild the entire package; it might even succeed! And any programmer who compiles your code by hand will think that they have broken some existing code or header when all that has really happened is that they have stumbled across your harmless warnings. They will again be grateful to you for the enjoyment of the process that they will have to follow to find out that the error was there all along. Extra bonus points make sure that your program cannot possibly compile with any of the compiler error checking diagnostics enabled. Sure, the compiler may be able to do subscripts bounds checking, but real programmers don’t use this feature, and neither should you. Why let the compiler check for errors when you can use your own lucrative and rewarding time to find these subtle bugs?

26. Combine Bug Fixes With Upgrades

Never put out a “bug fix only” release. Be sure to combine bug fixes with database format changes, complex user interface changes, and complete rewrites of the administration interfaces. That way, it will be so hard to upgrade that people will get used to the bugs and start calling them features. And the people that really want these “features” to work differently will have an incentive to upgrade to the new versions. This will save you maintenance work in the long run, and get you more revenue from your customers.

27. Compensate For Bugs

Don’t worry about finding the root cause of bugs in the code. Simply put in compensating code in the higher-level routines. This is a great intellectual exercise, akin to 3D chess, and will keep future code maintainers entertained for hours as they try to figure out whether the problem is in the low-level routines that generate the data or in the high-level routines that change various cases all around. This technique is great for compilers, which are inherently multi-pass programs. You can completely avoid fixing problems in the early passes by simply making the later passes more complicated. With luck, you will never have to speak to the little snot who supposedly maintains the front-end of the compiler. Extra bonus points make sure the back-end breaks if the front-end ever generates the correct data.

28. Sprinkle sync code liberally

Sprinkle some system synchronization primitives in places where they are not needed. I came across one critical section in a section of code where there was no possibility of a second thread. I challenged the original developer and he indicated that it helped document that the code was, well, “critical!”

29. Code Names Must Not Match Screen Names

Choose your variable names to have absolutely no relation to the labels used when such variables are displayed on the screen. E.g. on the screen label the field “Postal Code” but in the code call the associated variable zip.

30. Pose as an Idiot

A clever C programmer chafed at the company policy of insisting on the use of named constants instead of using embedded numerical literals. He followed the letter of the law, but avoided its spirit by defining 100 symbolic constants.

 #define ONE 1
 #define TWO 2
 #define THREE 3
 …
© 2017 Akaita development