views:

456

answers:

10

I am a bit stunned by lots of reactions on questions that point out that developers care more about the resulting compiled bytes than about the meaning of their code. I tend to nit-pick about postfix/prefix increment, as I tend to nit-pick about using a boolean for an enumerated type with two values, and about proper function naming, and...

So the question is more a rethorical poll: when is one allowed to disregard the semantics of what one writes? Where's the border line?

  • operator++ (postfix/prefix)
  • string.empty() vs. string == ""
  • vector.empty() vs. vector.size() == 0
  • enumerate { on, off} vs. boolean on=true; off=false
  • ...

Name it.

EDIT -

I didn't mean to question about the need for (micro)-optimizations. Rather, I want opinions on how well you should be aware of what you're writing, and on statements like "but it compiles to a dword, anyway, so why should I make it an enum?" (that's an extreme case...).

+1  A: 

The border line is side-effects.

If an encapsulated function does everything you want with 0 unexpected side-effects, AND the code is readable, that's all that matters. If you're predictable to an outside user and any "bizarre" functionality is held internally, that's all that matters.

It changes slightly if you add in optimization, but since you should never prematurely optimize, that's where it ends.

+9  A: 

Define "ok". Is it okay if it works on the initial delivery date, but every time you need to make a change it takes an extra three weeks to figure out the old code?

There's your answer: as long as you can understand the code and it doesn't hurt your ability to maintain it.

Joel Coehoorn
+1  A: 

I think these days most people agree that, assuming it works correctly, readability is the most important consideration. There are exceptions, of course - some apps have to run as fast as possible, and some apps can never be allowed to crash, but generally speaking it's readability.

gkrogers
+2  A: 

The border is when you are dealing with write-once, read-never code. Only then does it ultimately not matter what you are doing (in that instance) because you will never use it again. Unfortunately, this does not address the indirect feedback of practicing things that you would rather not repeat.

MSN
+3  A: 

When you start worrying about esoteric stuff that have no effect on the bottomline, I think that's going too far. Discussions like whether to use the ternary operator or write explicit if statements are good for those days when you have nothing to do but sit back, put your feet up, sip beer/wine/soda and discuss matters of "great consequence" :)

But creating an enumeration for boolean is just plain wrong.

Tundey
enum {on, off}... and than... enter 'standby'...
xtofl
It's not wrong if the two values don't convert to discrete notions of "on" and "off", nor is it wrong if an additional value could conceivably be added in the future (which is more likely if the first condition also holds).
Rob
+3  A: 

Depends on your cost function

Here a couple dimensions people love to argue about, and often conflate. Really, the answer is it depends. What is it that you truly value?

  • Character count
  • Number of ops created
  • Run-time
  • Portability
  • Maintainability
  • Clarity
  • Cleverness
  • Stability (free of bugs?)
  • Extendability

I always aim for the higher order stuff first, like clarity. Loss of clarity is paid for in human cycles, of which there's always a shortage of. People rarely care about raw clock time, and people who say they do are almost always optimizing prematurely.

If it helps you any, I like to think we're making progress by going up the stack, caring more about semantics and work getting done rather than being slaves to bits and numbers. However, this is not an excuse to forget the fundamentals and remember how certain semantic bits are implemented. You don't want to get caught with your pants down during those rare opportunities where speed starts to matter and convention goes out the window.

Mark Canlas
+3  A: 

"when is one allowed to disregard the semantics of what one writes? Where's the border line?"

I think a reasonable question is: "when should one disregard the semantics of what one writes?"

Since I view programming as a human activity, I'd say the only time one should disregard the semantics of a statement is when the system itself forces you - when some incomprehensible statement is the only way to do something. Such statements are good to document.

Joe Soul-bringer
That's a valuable twist!
xtofl
+1  A: 

Micro optimizations are pointless 99% of the time. For example, if your compiler interns all "" to a single instance anyways, you are not increasing performance in any way by using String.Empty. Not having any measurable effect is typically the best you can hope for too, I have seen "optimizations" decrease performance, due to the compiler doing a better job, and the optimization interfering with it.

Most code does not need to be optimized. Identifying where that needs to happen can only be done with diagnostics after the code is running, and even then most of the time it is done through algorithmic optimization, not micro optimization.

Matt Briggs
I'm not even talking about optimizations. It's more like: don't pay for it if you don't use it, and even more like: express what you mean, not what you think might help the compiler.
xtofl
Thats what I'm talking about though, these things are done in the name of optimization, even though it is a pretty pointless exercise nearly all the time. Maintainability is the overriding concern in the vast majority of code being written.
Matt Briggs
+1  A: 

Observing the examples that you have provided -- The following:

operator++ (postfix/prefix)

string.empty() vs. string == ""

Don't seem to be good examples, as they compare operations that are different in functionality. Hence, one better not disregard their semantic distinctions.

In contrast, the following examples:

vector.empty() vs. vector.size() == 0

enumerate { on, off} vs. boolean on=true; off=false

Are perfectly reasonable.

vector.empty() is preferable if the context of its use is only to determine if the vector is empty. At the risk sounding condescending (which I do not intend to be): this boils down to common sense. Why ask for the vector's size if you only want to know if it's empty? That's like asking someone how much money they have in their wallet when you simply wish to know if they have enough cash to by a Coke.

As for enumerate { on, off} vs. boolean on=true; off=false, ask yourself this: how likely is it that you may add another value to the enumeration, in the future? It seems reasonable that one might want enumerate{on, off, indeterminate}` (or some variation), so the answer may be yes. Otherwise, a simple boolean would suffice.

This leads me to the crux of your question: which seems to be if there is some deterministic/algorithmic approach to deciding one way or another on questions such as these, or their relevance? My answer is that until the day that Turing Machines are able to pass the Turing Test, I would say No. This is the reason why humans are required to engineer software.

Ryan Delucchi
I provided these examples because those are the source of debate in some questions at SO, and the answers often say: "Who cares... as long as the result is ok?".
xtofl
And indeed: there is no deterministic algorithm to decide upon whether or not to nit-pick.
xtofl
+3  A: 

I've written a lot of code in my career. Certainly not as much as many folks here, but a lot of code nonetheless. During that time, I've learned one thing that's proved true time and time again: When you get sloppy, when you ignore the details, defects creep in.

Defects cost time and money to repair. You can either spend the time to write the code cleanly and clearly up front, when it's cheap to do so, or you can spend lots of time and money later chasing down a defect in code that you likely don't remember all that well because you slapped it together in a hurry or because it doesn't conform to the coding standard. The end result is, you're wasting time and money. Further, you're wasting time and money you didn't have to waste to begin with, because it could have been prevented by a little upfront investment.

I have never regretted being meticulous about the way I write code. It has never come back to haunt me. Being sloppy has always come back to haunt me.

Mike Hofer
Man Do I Like You! (Your answer, that is... :))
xtofl