Author: José Carlos
Date: 00:39:02 03/05/04
Go up one level in this thread
On March 05, 2004 at 01:01:45, Russell Reagan wrote:
>On March 04, 2004 at 21:26:18, Omid David Tabibi wrote:
>
>>But on the other hand, Hungarian Notation can make the code much clearer.
>
>That's purely a matter of taste. Code written using HN is not going to be 'much
>clearer' (or clear at all) to someone who doesn't know it. I had a heck of a
>time reading Gerbil the first time through.
I think it's a tradeoff. HN (or any other notation you like) is not easier to
read unless you're well used to it. Actually, as you said, it can be hard to
read, but it's much better for the developer, once you know how to take advance
of it. When you're reading a line and want to make a change there, it's a pain
having to go to the start of the function or to the class declaration to see
what time this or that variable is. For me, in C++ it's even worse since you can
declare variables anywhere (not that I do it, but can happen when reading
someone else code).
In a chess program, where we write some code at very low level, and use a lot
of bitwise operations, it's specially important not to make a mistake with
types. For example in Anubis (bitboard based) I have large arrays of unsigned
chars that I must and / or with bitmaps. I don't have my code here but let's
suppose I have a line:
Attacked = ((UINT64)File[n] << 16) & WhiteAll
or instead of that:
u64Attacked = ((UINT64)u8File[n] << 16) & u64WhiteAll
When next year I come back to this line to make some change, I hope to find
second verion rather than first.
>You would be better off just using descriptive variable names and abstracting
>the handling of the data so that someone reading your code doesn't need to know
>that you use an unsigned int (or whatever).
>
>
>>What do you think about Hungarian Notation?
>
>IMO, Hungarian Notation is antiquated. It served its purpose in its day, but all
>it does today is make your code more rigid and difficult to change.
I'm antiquated also :)
HN prevents me to make type changes happily forgeting about side effects. A
type change is a very serious change, so it's IMO a very good practice to have
all the lines where the variable appears revisited.
>Just the other day you said you wanted to change from int to unsigned int (or
>something like that), but that you keep putting it off because it is going to be
>a lot of work. If you had planned for change, you would be able to modify half a
>dozen lines of code and recompile and be done with it. I think you agreed that
>it would have been better to use typedefs and macros/functions/classes to make
>that a 60 second change. If you do that, then you do not care about the types.
>You actually want to *hide* the types, not brand them into the variable name.
>Just imagine how much *more* work you would have to do to make that simple
>int->unsigned int change if you used Hungarian Notation. That's a lot of
>variable prefixes to change...
You want to hide types if you're doing only high level operations. If you do
bitwise operations you'd better know very well what type you're using.
>Here is an example of how I would do things. I would use a class, but I think
>you use C right? So I'll do C. If I wanted to represent a move in C, I would do
>something like this (I think C has inline functions now, if not use macros, you
>get the idea).
>
>
>///////////////////////////////////////////////////////////////////////////////
>typedef unsigned int MOVE;
>
>inline MOVE new_move (SQUARE from, SQUARE to, unsigned type) {
> return from | (to << 6) | (type << 12);
>}
>inline SQUARE from_square (MOVE move) { return move & 63; }
>inline SQUARE to_square (MOVE move) { return (move >> 6) & 63; }
>inline SQUARE move_type (MOVE move) { return (move >> 12) & 15; }
>///////////////////////////////////////////////////////////////////////////////
>
>
>Now what if I decided that it would be better to use a struct of bytes instead?
>No problem.
>
>
>///////////////////////////////////////////////////////////////////////////////
>typedef struct { unsigned char from, to, type; } MOVE;
>
>inline MOVE new_move (SQUARE from, SQUARE to, unsigned type) {
> MOVE move;
> move.from = from;
> move.to = to;
> move.type = type;
> return MOVE;
>}
>inline SQUARE from_square (MOVE move) { return move.from; }
>inline SQUARE to_square (MOVE move) { return move.to; }
>inline SQUARE move_type (MOVE move) { return move.type; }
>///////////////////////////////////////////////////////////////////////////////
>
>
>Recompile, and all of your code should still work perfectly. When you use the
>code, you need not have any idea what the underlying type is, and that is
> a good thing.
In a small code piece it's fantastic to hide types. But remember in a chess
program you have low level interactions everywhere. You have a move array, you
have a hash table with moves, you have a position structure with (possibly) some
moves there, you have a book with many moves there... you have lots of
interactions. I you simply forget about them and change types hiding them behind
a macro or typedef, you might get into big trouble.
> It makes your code flexible and easier to change. Hungarian Notation
>makes your code rigid and easier to break. There is a reason we don't do
>everything in assembly anymore. C lets you do some abstraction like I did above.
>C++ lets you do even more abstraction without losing any runtime efficiency.
Abstraction is fine... for applications where abstraction is fine :) (which
are most BTW, I like type hiding a lot when I can afford it).
José C.
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.