HTCondor Project List Archives



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Condor-devel] changes to condor_submit



On Thu, Aug 05, 2010 at 08:45:27PM -0400, Matthew Farrellee wrote:
> >On Thu, Aug 05, 2010 at 04:58:06PM -0700, Rob wrote:
> >>The ZERO return on SUCCESS I did not realized in the past
> >>and occasionally wrote buggy code....
> 
> "obscure knowledge maintainer" =?= "You think you know something about 
> POSIX, well I bet I can trick you."

Yup. That's exactly what it means. :) I bet if you did an informal poll
and asked a bunch of developers (who shoudn't be given a chance to look
it up) what access() does, I bet a tiny majority of them would even
know about the real uid check vs the effective uid check of stat(),
and most will think access() uses the effective uid cause that's what
damn near most other file system unix api calls do.

Also, the majority of the Unix API functions which return integers return
0 on success and -1 (or <0) on failure. It is part of the orthogonolity of
the Unix API. Couple this with the serious desire to not use relational
operators in C conditional expressions (utilizing anything which is
nonzero is true), and you end up with things like what was found with
!access(...) <= 0 during brain farts for what a boolean is in the language
vs the semantic action of what you want to do.

C programmers read ! as NOT, which inverts a truth value, but they also
read it as ISN'T, like "If the value isn't present in the object" -> if
(!present(obj, value))

As you start to leave the lower level representations of the hardware
values, where NOT is the dominate point of view, you end up using the
semantic ISN'T form more often and code your APIs that way opposite of
how Unix thinks about it, taking the above example:

#define TRUE 1
#define FALSE 0
int present(Object *obj, int value)
{
	if (lookup(obj, value)) {
		do_something();
		return TRUE;
	}

	return FALSE;
}

Oops, see that suddenly I exchanged the meaning of true and false from
the SUCCESS and FAILURE point of view of most Unix functions, I should
have returned 0 in the TRUE case and 1 in the FALSE case to mimic the
Unix point of view. When you start building large codebases like this,
! by itself becomes a funny concept and very hard to use across the layers
of Unix and the application code. This is why I advocate always checking
the return value against a real entity instead of assuming the boolean
system of C is the one actually used in the API: cause often it isn't.

So, I'd write:
"if the value isn't present in the object" -> if (present(obj, val) == FALSE)

Because this way I, and the reader, guarantee that I understood what
was going on.

This behavior of using a nonzero return value for true comes down to
failing to learn from the Unix masters that one should only enter an
if conditional if something went wrong and not as a matter of habit
if it went right. If you program like the masters, only entering a
conditional on a unix call when something went wrong, instead of when
something went right, then the control flow always stays to the left of
the screen.  You minimize large jumps of common path control flow over
if/else chains, among other sundry pieces of confusing crap that spew
from people's fingers.

Meh, enough ranting.

-pete