Ask Slashdot: When Do You Include 'Unnecessary' Code? (sas.com)
"For more than 20 years I've been putting semicolons at the end of programming statements in SAS, C/C++, and Java/Javascript," writes Rick Wicklin, a researcher in computational statistics at SAS. "But lately I've been working in a computer language that does not require semicolons. Nevertheless... I catch myself typing unnecessary semicolons out of habit," he writes, while at other times "I include optional statements in my programs for clarity, readability, or to practice defensive programming." While Wicklin's post is geared towards SAS programming, Slashdot reader theodp writes that the question is a language-agnostic one:
...when to include technically-unnecessary code -- e.g., variable declarations, superfluous punctuation, block constructs for single statements, values for optional parameters that are the defaults, debugging/validation statements, non-critical error handling, explicitly destroying objects that would otherwise be deleted on exit, labeled NEXT statements, full qualification of objects/methods, unneeded code from templates...
He's wondering if other Slashdot readers have trouble tolerating their co-workers' unnecessary codes choices (which he demonstrates with a video clip from Silicon Valley). So leave your answers in the comments. When do you do include 'unnecessary' code in your programs -- and why?
He's wondering if other Slashdot readers have trouble tolerating their co-workers' unnecessary codes choices (which he demonstrates with a video clip from Silicon Valley). So leave your answers in the comments. When do you do include 'unnecessary' code in your programs -- and why?
All of my code is unnecessary, you insensitive clod!
I'll add extra intermediate variables, break up lines to make them as short as possible, and use extra verbose variable names along with explanatory comments of the logic of each object/function. The goal is to make it so that anyone reading the class for the first time with no prior experience can understand its purpose and basic function without having to spend 5 minutes deobfuscating the code. Yes you generally can golf most any class into a single line, but it's unmaintainable even to its original creator after a couple weeks.
That said, for personal consumption code, I don't generally bother going to that much effort to make my code clean/clear.
.
There are some programmers who like to complain about other people's code (it seems to make them think they are a better coder), so why not give them something intended for them to complain about?
In effect most punctuation, indented blocks etc is superfluous to a computer. Is your code more or less readable with whatever construct you include? What if you add more code between eg your declaration and your use, would it still be obvious?
That's why languages without those construct are a pain to work with, you add a bunch of code and suddenly you've lost whether you're 4 or 5 tabs deep when the tabulation decreases. I like to add comments to the end brackets of regular code myself and add brackets to all if statements. It's superfluous but it's harder to rewrite a conditional one liner into a multiline code after the fact.
Custom electronics and digital signage for your business: www.evcircuits.com
When Do You Include 'Unnecessary' Code?
Here is how I make the determination: if it reduces my cognitive burden now, later when I return to the same code, or other programmers who will have to maintain it, then I include it
These days, a programmers time is nearly always far and away the most expensive commodity employed in any project. Why should I spend time asking myself about minutiae rather than focusing on architecture and algorithms?
I never use variable names of more than one character unless all possible single character names have already been used, which rarely happens. I never indent blocks; extra white space is only superfluous. I never do in six lines of code what can be done in one long convoluted line. If the person that needs to maintain my code can't make sense of it, too bad. They're probably just a sloppy programmer.
09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
I used to make firmware that goes into aircraft instruments. The FAA has some guidelines on this.
Unnecessary code is generated machine code, and the rule is that you can have none of it. Source code doesn't matter, if it's ifdef'd out it's the same as commentary.
The theory is that if execution takes an unexpected jump, it can't land in anything that isn't specific to the purpose of the device. Some people take this to extremes, writing new versions of printf() that omit the floating point and pointer output formats when they're not used in the system.
However, if a buffer overflow causes the program to jump, it can't land in the middle of the pointer formatting section and send a pointer to the airspeed computer instead of the decimal altitude.
What the OP is talking about is unnecessary source, which is a different matter.
IBM did studies of bug frequency, and concluded that the number of bugs in a program depends on the number of source lines a programmer can see at any one moment. Big screens allow the programmer to view more lines of code at once, little screens require reading the code through a soda-straw.
Their studies showed that simple code-tightening techniques reduced the number of bugs. Placing the brace on the if-statement, for example, allows one more line to be viewed in the window. Omitting braces altogether for single-statement "if" saves another line. Using 120-char width lines instead of 80 allows fewer wrapped lines, and so on.
There is a competing goal of readability, so tightening can't be taken too far. The complex perl-style or APL-style "everything on a single line" construct goes the opposite direction - too much info and it becomes hard to understand at a glance.
Typical C-like syntax with line-tightening techniques is easy to read, and presents probably an optimal view of code to the engineer.
Braces on their own act like vertical whitespace. Requiring one-and-only-one exit from a subroutine leads to convoluted and chevron code (where the code looks like a big sideways "V" and the hints of indenting is lost). Requiring all definitions at the top of the module requires the reader to flip back-and-forth, and requiring Hungarian notation makes the code look like gobbledy-gook.
Dump it all.
Name your variables clearly, using nouns for objects and verbs for actions. Name your subroutines after their functions. Tighten your code to make it terse, but keep it readable.
A function should read like a good short story. Set the scene, develop the characters, advance to the climax, then there's the denumont/ epilog (sp?) where loose ends get resolved. Add comments if the story is hard to follow, don't if it's not. If the story is too long, create some helper functions.
A dash of humor here and there helps keep things entertaining, but go easy on it.
Remember, some software archaeologist may have to go back in 5 or 10 years and figure out what the heck the code does to fix a problem -- and that guy may very well be you.
I'm completely serious. This is what I do, and I actually enjoy going back through my 10 year old code (I've got a nice stable job)
I add "unnecessary" parentheses to complex expressions in order to avoid the mental burden of thinking of operator precedence. I instruct my team to do the same.
Obviously if I can name a sub expression reasonably I just extract it, this is often enough not a reasonable solution.
Usually I prefer terse code, but the above is a fairly common exception.
Since I make a ton of money, and my boss is itching to fire me and replace me with a Syrian refugee who will work for cafeteria scraps, I make heavy use of 6-level deep macros and the C downto operator: while (i --> 0)
Intron: the portion of DNA which expresses nothing useful.
Caveat: I am retired. Programming was a major part of my career between 1995 and 2005 but I mostly do HTML/CSS these days, with only enough PHP to glue others' existing scripts together.
What I determined back in the day is that efficient coding is unnecessary for performance when the wetware BKAC would always be the primary limiter on speed. Since virtually all of my work was repurposing documents from old versions of Word, Excel, WordPerfect, Lotus1-2-3, and other outdated apps to newer standards (mostly early HTML), I did not have to worry about shaving off microseconds. The typing speed of the person selecting the raw data had more impact on performance than the programming. So I was much more concerned with whether I would be able to rewrite a handler for a Windows3.11 app to work on a Windows98 version, if that need arose.
So I worked mostly in Perl using the Tk graphic interface and Javascript front ends, which made rapid development and easy revisions to meet new criteria possible. I used explicit declarations, human-readable naming conventions, extra punctuation, and the long way around the barn whenever the shorter routes looked like they might cause head-scratching later on.
If I had been working in an environment where microseconds counted, I would have used a compiled language and a different approach.
My old-timer's advice to you young'uns: Look at the environment you are coding in and match your coding style to fit its shape. Eschew becoming the cleverest code monkey in the cube farm and focus instead on becoming wiser than all the others.
I code for thousands of mostly-unique commercial software products a year, using 8 languages (mostly C#), for many dozens of major customers, and lots of smaller ones.
Because of this, I have a huge chain of demands I keep track of, and methods of automation in order to collectively manage a constant flow of data requirements, and of course tracking issues both shared and common between these scenarios.
When I'm coding, I've got to code in a way that communicates these details to myself, consistent between all the languages I might have to touch for coding, scripting, database, reporting, and specialized languages a client may suddenly require.
Because of that, my code has to be a loose framework, a late-binding train station of logic, where demands may switch at any moment, and limitations imposed from other teams may similarly pop up.
My code is littered with multi-paragraph discussions of a technology I once had to interact with (customers often switch back), large sections of functions commented out rather than deleted, and other 'bad' practices just to give me landmarks and a 'flavor' of what a customer is occasionally interested in, amidst a never-ending avalanche of context switching between products and customers.
I've redesigned these several systems from the ground floor once (they used to only handle a small fraction of the work, using an antiquated language), and am working with a team to do a better design... but it's been very difficult for a team of perfectionists to understand how to react to an unlimited flow of changing requirements. Fortunately, the code itself has been quite usable, and they're using the same languages, but no system can really handle these demands truly consistently - I'd call it NP ridiculous. It's basically the "mythical man month" writ live, where I've got to do my work, and train a team whose work process may never really be able to do what I can do - definitely healthier long term, but can't help but result in some amazing process failures.
I actually would have made most of these design changes myself, but at the time, I was forbidden by management from making those choices, since I was doing my work directly at the production level - so it's actually a bit of a relief to see someone at least allowed to make some of the better choices.
In short (and yes, for this scenario, this is short), because I'm doing alone, for years, what a team of almost any size would struggle to approximate, as many of us seem to be doing, I've got no choice but to code how I need to in order to have a system that I can sanely maintain in an insane set of requirements. There's not really a choice in the matter, if your put in a position where "oh, we suddenly need this" exists as a live production task in a growing industry.
Ryan Fenton
Speaking of readability, here's an entertaining one I've been seeing more of in C:
if (result == SUCCESS)
versus
if (SUCCESS == result)
The rationale behind the second is that you don't end up accidentally assigning SUCCESS to result (eg, if (result = SUCCESS)). But I know that I find it weird to look at it the other way around. I want to know if the result was successful, not if successful was the result. Maybe it's an english thing.
I know that Xcode has been putting up warnings/errors for code that does assignments in if-statements and saying that if you really want to do that, wrap it in an extra layer of parentheses (eg, if ((booleanResult = Do_Something()))). I'm not sure this is somehow more clear that you're doing the assignment...
Maybe because you are a douche?
If you believe that code will help someone with understanding (yourself included) then it is necessary. It is needed to help with clarity. It may not be strictly required for the correctness of your program, but your goal should not be to express the correct solution as succinctly as possible. That approach leads to many other problems.
Occasionally I include solutions for problems which have not yet been uncovered. Those methods may not be called (dead code) and any kind of static analysis would report them as "unnecessary." If I make the decision that such code will help me, or help someone else, later then I believe it is totally necessary, and good to include. Worse-case is that it will be a good starting point for someone later, and they will throw it away and replace it with something better.
Never include unnecessary code. If there are incorrect implementations that you are replacing, remove the incorrect ones! Don't leave traps lying around for people to get caught in. Unexecuted code, or not succinct code, is not unnecessary. I constantly include semicolons, and brackets around one-line conditionals - those are defensive practices which are designed to prevent future problems, and aid in clarity.
This is why people are hiring you - to apply human intelligence and judgement to a problem. There are situations where doing not strictly necessary things is appropriate, and situations when doing not strictly necessary things is a waste of time. It's up to you to decide. Different actions are necessary for different metrics. One thing may be necessary for a correct solution, and another thing may be necessary to help someone else understand your correct solution. Everything should be useful (necessary?) under some kind of metric.
Any c++ programmer with more than 1 years experience will see this immediately and slap some braces around it. Thanks to modern IDEs and standard indentation (which the IDE will auto-correct) it's extremely unlikely anyone will make this mistake, or it will go unseen for very long.
I'd group this sort of 'error prevention' in the same category as putting the constant first in every if statement e.g.
if (1 == YouShouldHaveDoneThisTheOtherWay)
{
Whatever();
}
The people who make the mistakes that this shit prevents have no place working on code.
All those moments will be lost in time, like tears in rain.
/*
That's
fine
,
good
code
should
be
well
commented
*/
--- Most topics have many sides worth arguing, allow me to take one opposite you.