How to write unmaintainable code!

Started by Tonnica, January 08, 2006, 05:19:47 PM

Previous topic - Next topic

Mr. Analog

Incedentally, naming local scope variables isn't usually a big deal unless you do something like this:



/* Nest this a few more times and the single letter counter gets confusing */

for (int i = 0; i < blah.length(); i++)

{

for (int c = 0; c < blah[c].length(); c++)

{

//TODO: ADD CODE HERE

}

}




Which again, illustrates the point that good coding standards are nearly always discretionary.
By Grabthar's Hammer

Cova

Ya - besides gratuitous use of i, j, and k as index variables for looping, I also often use X and Temp as temp places to store garbage, and when using C usually also a 'char buffer[big]' for assembling strings in before sending them off to places.  If following standards is good for maintainability, and i is the standard indexing variable - well using i must be maintainable then.



The one thing I have started doing a lot of lately, thats greatly improved my ability to figure out my own code after I've forgotton some/most of it, is commenting my if/else code blocks (I normally don't comment a lot).  This helps the most when the code blocks start nesting 5+ levels deep, with else's way down below somewhere, and a page or more long when it gets hard to see what block/scope you're in.  I wish VB had a good way to graphically indicate the matching start/end of code blocks.  I usually start by blocking-out the sections, then fill in the code to deal with 'em later.  So I'll start with (vb-like psuedo-code ahead)



If File Opened Successfully Then 'Deal with contents of file

Else 'Deal with error opening file

End If 'End of dealing with the file



Which becomes something like..



If File Opened Successfully Then 'Deal with contents of file

 If File Is Empty Then 'Deal with empty file

 Else 'Process contents

 End If 'End of empty file check

Else 'Deal with error opening file

 Select Case on error.

 Case 1 'comment desc of error 1.

 ...

 End Select 'end list of error codes

End If 'End of dealing with the file





Eventually, when the app is near-complete, somewhere you end up with something like



         End If

       End If

     End If

   End If

 End If

End If



Or a series of closing curly-braces, language don't matter much.  Anyways, when you've realized there's a bug and need to add a bit of code to the end of a block, or add an else-block somewhere, it's much easier to figure out where to put it if you don't have to scroll up 10 pages trying to match indentation-levels.  And since I typically write all of the if/else/end-if statements first, even if I don't know what I'll need I include all the else's, I rarely ever have bugs due to un-closed code blocks, and I just comment-out empty blocks at the end if I didn't need 'em.

Tonnica

Wow! Some really fantastic posts here. I defenitely like the point of good coding standards being discretionary, it's really true. Sometimes you can have assy syntax but if your tabulation is good and your mistakes are as regular as a swiss watch there's a chance that whoever has to work on your code in the future can sort out what needs to be sorted out. If everything's akimbo and it's hard to distinguish where things start and stop, but things are put in you-know-it-works chunks like:

// begin area code chunk

// Copy and paste this chunk of code to extract the area code from the phone number!

if eval(isNumeric(right(strip(phNum,'/,(,),-,[,]'),3)), someVar) {sendAC(saveAC(someVar));} else {throwCodeError(451);}

// end area code chunk

Then I find that not so bad. It's a chunk, it's re-useable! ...Just as long as it's clear what the I/O of the chunk is.



Out of the whole list I liked this the best:

QuoteRigidly follow the guidelines about no goto, no early returns, and no labelled breaks especially when you can increase the if/else nesting depth by at least 5 levels.



This reminds me of what I call break-dancing. Can the break just go to some error handling or some kind of section of the code that's closer to the end? NO!!!!!! It MUST go to the TOP and the MIDDLE and EVERYWHERE freaking INBETWEEN making tracing the actual steps of a common execution almost impossible. Nothing gets me making the evil eye at people faster than something like (excuse the computerlish demi-syntax):

setVarbs: set variable1 = defaultValue1;

code...

code...

/*there's a secret break in this function that kicks out of the current function being executed! SNEAKY!*/

itsARecursiveStatement: someMysteryFunction(CONST_PIE);

code...

if (somestatement XOR 0) {

goto setVarbs;

}

else

{

goto itsARecursiveStatement;

}

onError goto setVarbs;


GRAGHGH! Hate so much. I consider break-dancing to be wiggity-wack. Or at least the hallmark of those who can't manage to cram their processes into a logical flow.

Thorin

Cova, you just provided an excellent example of where a bit of commenting makes code much easier to understand/edit.



As for VB6 code like you've got there, back when I wrote it I used to always move blocks of code into their own Subs as much as possible.  If a Sub or Procedure had more than two pages of code, it was too hard to read.  C# and VB.NET have the #region/#endregion directives that make it *way* easier to hide blocks of code that you don't normally look at.



And Mr. A., you make an excellent point.  You don't necessarily make code more maintainable by following strict de rigueur rules; case in point - Hungarian Notation.  It's all about making it as understandable as possible.
Prayin' for a 20!

gcc thorin.c -pedantic -o Thorin
compile successful

Cova

Well, when I talk about VB, I don't distinguish really whether it's .NET, VB6, etc.  I've been using VB since version 3 (it was 16-bit back then, I remember VB4 added 32-bit) and the syntax really hasn't changed since then - they've just added more keywords and extra functionality.  The snippets I posted above could just as easily be .NET as VB3, you'd just have system.io.file objects to the the file stuff in .NET, and OPEN and PRINT statements in VB3.  I don't really use the #region statements in .NET much - I think I've done it once since .NET 1.0 was originally released.  I prefer to make my code readable without depending on a specific IDE.  I do use visual studio to code, intellisense is the best thing ever for lazy coders like me, but I also very commonly have a few notepads open with various code files from other projects / samples - I don't like to open any file in visual studio that isn't part of the current project/solution, and loading multiple instances of visual studio eats RAM in a serious way (though I do do it sometimes)



Hmm..., maybe I see things differently because I'm mostly a VB programmer now.  Especially my own code, due to a few standards I tend to follow (not NAIT's standards), tends to look very englishy.  My variable naming for instance - I usually prefix most variables with an a (sometimes an an) if its an instance of an object - so I end up with aDatabaseConnection, aCommand, aResult, etc.  sometimes shrunk down for easy typing of commonly used ones (aDBCon is common).  Throw in some other VB code which is already more english-looking than most languages, and you get stuff that even non-coders can probably read, even without comments.  'If aDatabaseConnection.Open = True Then aCommand.Execute()' is a perfectly valid piece of code, assuming those 2 variables exist.



As for logical flow of code - I think it might be a thing of the past.  Way-back in the early days, code was spaghetti - goto's everywhere.  Then came functions, procedural programming, etc. - and code flowed very obviously from main() to whever it ran out of lines to execute.  Then we went object-oriented, and code-flow started to get a little confusing again - you might have multiple-inheritance, overloaded functions, etc., you have to be careful and know what you're calling, where it is, make sure you aren't calling an inherited version of it (or that you are getting the inherited one if you're dealing with the base object), etc.  Code still flows, but it's harder to follow.  Windows added messaging and event queues and such to that - windows programs respond to mouse-click events, raise-exceptions, and do all kinds of things that can really result in execution jumping all over the place in a program.  Event-based programs don't flow anymore from start to finish - they process messages and every time they need to check to make sure the pre-req's for that message have been met (eg. print message is useless if no doc is open yet).  And finally, we are just on the verge of something new again - multi-threaded programming.  Yes, there have been multi-threaded programs around for a long time, but with multi-core cpu's, hyperthreading, all next-gen consoles going multi-core, etc. the average programmer is now starting to need to learn about parallel threads of execution - multiple flows of code potentially modifying the same memory, and all responding to events with execution jumping all over.  A single copy of an object that's been inherited 10 times being accessed by 20 threads at once - modern code needs to be concerned with doing its own part of the whole properly and error-free, and not so much anymore with flow.

Darren Dirt

Quote from: "Tonnica"I wouldn't be surprised if some of you have already seen this but I found it again while searching for some ASM hacking tools and got a good chuckle.



How To Write Unmaintainable Code



Apologies to anyone non-coding inclined who decided to cick on the link and need to take an asprin after trying to scan it over. Double apologies for those who are coding inclined and get the Scanners Effect from considering what kind of code these guidelines would produce (WOO! BOOM!). Triple apologies to those who have coded in Java. Ever. I feel your pain! ;)





"To foil the maintenance programmer, you have to..." And thus my interest is re-piqued (being, technically, the "maintenance programmer" for RTW when I started here 21 months ago) -- I am totally re-reading this at home, it's been prolly 2 years since I last found this list. :D



PS: agreed re. Java.





PPS: "Quidquid latine dictum sit, altum sonatur."

- Whatever is said in Latin sounds profound.



^ I had this as my BBS sig in the pre-Internet days, no joking :o
_____________________

Strive for progress. Not perfection.
_____________________

Darren Dirt

"This essay has been like rock candy, seed the string with sugar, soak in sugar water, soon it grew out of control"

-- the original author (!)



http://mindprod.com/jgloss/unmain.html <-- (essay is split into sections)
_____________________

Strive for progress. Not perfection.
_____________________