Cruft (job stuff)
On a more annoying note, earlier I was asking James why he was doing a certain stylistic thing, and he said "Well that's what Stroudstrup says to do." Rather than debating it on its merits. Which is fine, but then we got into a little chat about stylistic stuff, and then he started to bitch about how I need to comment my code more. Never mind that he doesn't comment his code at all, and he likes to make lots of indirection and just these hugely retarded call graphs which are impossible to trace, and moreso need to be traced backwards quite a bit to see what's supposed to happen where (to try to figure out why something isn't happening).
He clearly doesn't understand state machines, for example, but he gets offended when I try to do something in a clean way (he claims that I'm just upset because he was "touching my stuff" or that his way is just as good as mine). Ugh.
At this point I'm resigned to just let him do whatever crap he wants and just save the refactoring for the next game, when we actually have time to do it right (and when a lot of this will be moot since the next one will be in 3D anyway, which is a totally different beast on the DS).
Most of the duct tape he's added to my stuff has been because he doesn't understand the system or what I was getting at, not because my system was incomplete. One of the major changes he made today basically took a huge shit on the chest of a simple event-based API and turned it into a huge fucking tangled morass which makes it really fucking hard to just change the palette. Unless you happen to be doing stuff like changing the palettes and background images on both screens in the exact way that James happens to do everything.
I don't suppose he's ever understood the concept of "orthogonality." It's clear from his code that he doesn't.
(Also, the thing earlier that the long debate was about was the merits of using 0 vs. NULL for "a pointer which points to nothing." It's a semantic difference, but he insists that we should use 0 "because that's what Stroudstrup says," never mind that's not what ANSI says, and there's a huge semantic difference between 0 and NULL. (My argument: 0 is a number. Numbers are still things. NULL, although implemented as 0 on most systems, means "nothing." 0 is still something. His argument: "Stroudstrup says that 0 is more portable." QED, I guess.)
He also loves to harp on me for using post-increment instead of pre-increment on loops. Yes, I know that pre-increment is faster for overloaded operators, but there's no difference for fundamentals (I always use pre-increment for overloaded operators) and on C compilers set to strict ANSI mode, pre-increment has a different semantic meaning (it does the increment before the loop body). Never mind that the only real reason for avoiding pre-increment is a (very very slight) performance hit, while he sure loves himself a whole bunch of nasty shit which definitely hurts performance way more while also making the code less maintainable. HOORAY.
Ugh.
Honestly, I hope our little company grows so that we have separate dev teams in the future. I want to take on a more leadership/architectural/platform-specialist role and don't want to actually, you know, interact with James anymore.
Maybe next time around it'll be more like I'm in charge of the lower-level stuff and they get to build whatever morass of crap on top of it. Le sigh.
Comments
(or is the situation more complicated than that?)
Like, sure, you could use 1 and 0 instead of
trueorfalseon a bool, and it would be "more portable" to do so, but that doesn't mean it's a good idea.The thing which irritates me most about his justifications for doing things is that it's always an appeal to authority, and not based on any real experience on his part. "Stroudstrup says to do it this way because it's more portable." That's it, and no explanation on how it's more portable. When I challenge him on that, and point out that it's just Stroudstrup's opinion and it's actually not more portable (since every system has NULL defined, but not every system has NULL == 0 — the Motorola 6811, for example) he just says "But Stroudstrup invented the language!" which is only partially true. I mean, something that K&R said about the C language back in the 70s doesn't necessarily apply today, either. [edit: by this I didn't mean that NULL == 0 returns false on these systems, but that NULL is defined as something other than 0.]
Also, 0 is definitely not more portable; sure, it'll work on any C++ compiler on any platform where NULL == 0, but what about portability between languages? When converting code from C++ to, say, C#, Java, or even Managed C++, NULL translates to NULL, but 0 doesn't necessarily translate to 0!
Oh well. At this point I've decided that James needs to learn real-world software engineering practices on his own, since obviously he doesn't think my experience is valuable. I just wish he'd chosen a better time to assert his independence than two weeks before our game ships.
But it's low priority. If I was working with someone who wanted to insist on NULL, I'd just shrugs and use it.
The compiler has little to do with it. The platform is more important. GNU C is available for the 6811, but the RAM address space on the 6811 begins at 0x0, and it's perfectly valid to have a variable there. It's an extreme example and a pretty major stretch as an edge case goes, but it's still a valid example nontheless.
Portability-- some systems #define NULL 0, other systems #define NULL ((void *)0). (and these are the only two definitions allowed in ANSI C.) Switching betweeen these definitions can cause problems.
I don't know of any specific 6811 compiler which makes NULL != 0, but I was just saying that 0 is a valid address for a piece of data on the 6811. Actually, isn't it also valid user address space on the 6502? (The 6811 is basically an extended 6502 intended for low-power small-footprint embedded systems, FWIW.)
A compiler could conceivably define NULL as, say, some variable outside of the address space, and then have a special-case numerical compare between that special pointer and regular pointers. Or it could just require that no pointer ever points to 0. Or whatever.
But this is still largely tangential to my main point, in that 0 is a number, while NULL is a meaningful symbol. When you see code like
what does that tell you right away? You'd have to look at its type and see that it's of type FileHandle, but then what does that imply? That maybe FileHandle is an int typecast and this is the first handle in a series of files? But then if you look up the definition of FileHandle and see that it's a typecast of
const Filesystem::Handle*then you realize that oh, this is actually saying "this is a null file."If it were simply
then the first-glance response would be, "Hey, this file is being set to nothing," without needing to know anything extra about m_mainBGFile's type.
Looking at 0 vs. NULL in terms of the low-level implementation details is losing sight of the forest for the trees. Which, I think, sums up many programmers' problems nicely.
Oh, and the typeless vs. (void *) portability issue is largely a red herring, because you're only supposed to use NULL for pointer types anyway - if you're setting an int/float/whatever to NULL then you're falling into the exact opposite problem of using a symbol for something which it doesn't mean. The (void *) version of NULL was added later specifically to make NULL typesafe with pointer types and type-incompatible with fundamentals.
*waves*
Yeah, but this is incomplete use of Hungarian. Call it m_pfhMainBGFile and that problem goes away (at least for some sadistic definition of "problem goes away"
Interestingly enough, what Stroustrup actually says is that if you use NULL you should define it with
>amen<
Actually I switched from using NULL to 0 in my C++ code for two reasons: First because I agreed with Stroustrup (I don't like excessive MACRO use for replacement of immediate values like that... ) and figuring that NULL= 0 was part of "the standard" now, I could safely drop it. (also, rightly or wrongly, my style is to do if(!x) over if(x==0) which is more readable to me so I'm depending on NULL pointers being 0) Secondly I had been in a situation, long ago, where I was using two different C libraries, one that defined NULL to 0 and one that defined it to -1 (the latter probably being coded for another platform as Fluffy points out). Not a real problem, but there was a situation where both include headers for the libraries got into the same file and much hilarity ensued..
I think they both wash in pros/cons in normal use. I *like* my style and its legal but if I was coding for maximum platform compatibility I'd probably go back to using the NULL (and severely curtailing my C++ feature use...)
But they do not mean the same thing, even if the compiler thinks they do!
That's kinda dumb, IMO. It should be done as
because, again, the whole point to having a pointer called NULL is that it's a pointer. Treating ints as interchangeable with void* kills type safety in a big way.
Right - if you've turned off pointer vs. integer typechecking, then you may get bitten by something stupid like the difference between
*(x[72]) = 123;
and
x[72] = 123;
Don't ask me why you'd ever have an int ** that isn't an array at both levels, though.
int **could be a C-style reference to anint *which the function needs to be able to reallocate or similar. James always uses C-style references in that case because he doesn't seem to be able to wrap his head around typing something as afoo *&.Yeah, I was kind of scratching my head over that as well. Turns out ANSI C++ actually prohibits using a void * for NULL. I think the reason is the difference in typing-- a void* will not automatically convert itself into the needed pointer type like it does in C. So if you define NULL as a void * you have to cast it every time you use it.