Re: Circlemud design issues 12:05:03 +0100"

From: James Turner (turnerjh@XTN.NET)
Date: 04/21/98

Luis Pedro Passos Carvalho <lpcarvalho@SONAE.PT> writes:

> This thread has been going on like this:
> James Turner: Macros Bad! Inline Functions Good!
> yada! yada! yada!
> Sorry about the bluntness but let's think clearly now!

I think perhaps the discussion got side-tracked into inline
functions.  I did not intend, nor do I believe I ever stated, that
macros were bad or evil; if thatis how I seemed, then I misrepresented
my stance.  Macros do have their use.  However, circle uses them as
shortcuts around writing actual functions.  That is where I find
fault.  If the macros were achieving something that couldn't be done
by use of functions, then it would not be as much of an issue.

Inline functions aren't the center of my argument -- normal functions
are.  However, inlines are a counterargument to the issue of speed.

> Macros:
> + increase the readability of the code (in 90% of the cases they do James)
> + are portable
> + hide simple parts of code thoroughly repeated
> + enable you to use them on the left side of an attribution

Functions are portable.  They also look the same as macros (ie,
GET_NAME could be a function or macro, it doesn't really matter except
when it is used as an lvalue).  The lvalue argument is the only one
that is really valid; however, assignments in some cases can be very
bad if the value is invalid.  Functions would allow us to make sure
these cirtical assignments don't have problems.

> Inline functions:
> + increase the readability of the code
> + hide simple parts of code thoroughly repeated but can be used with larger
> ones as well
> + make type checking
> + can safely receive active parameters
> - may not be portable
> - Imply a cost with changing to them

Normal functions are portable.  Inlining can be made portable by using
#define's and #ifdef's.  Yes, there is a cost to changing to
them... however, that cost is not so large as to be prohibitive, and
it will save us work down the road.  It will allow expandability,
contribute to robustness, and give us better compile time error
checking (we well as runtime error reporting... a mud, or any program,
shouldn't crash unless it is in an unrecoverable situation).

> I've been coding with Circle for 3 years now, and my opinion is that the
> macros are
> being well used. They make reading the code easier and allow you very simple
> manipulation
> of the rather complex data structures of the MUD.

The readability argument isn't valid, since functions are every bit as
readable -- we could go as far as to use the same function names if
need be.  Functions would allow very simple manipulation as well.

setTitle(ch, s);

Is just as readable as

GET_TITLE(ch) = s;

While allowing for checks to be made, such as s being too long, or
null, or invalid, etc.  We should only do those checks once -- not
every time we try to set the title.  Likewise,

setRealStrength(ch, 18);

Is just as readable as

GET_STRENGTH(ch) = 18;

Yet we can make certain checks as to whether 18 is a valid value for
the strength of a character etc.

Range checking and pointer/string validity checking are very useful
things.  Circle could definitely use the redundancy.

> Granted, they have limitations but they are not supposed to be used for
> everything (which they're not,
> mind you). If you encounter a situation where a macro is unsuitable, by all
> means, use a function. But
> remember that they too have limitations. For example, I love the CREATE
> macro. And you can't implement
> it in any function with the simplicity it has been made with.

struct char_data *ch;
funcCreate((void) &ch, 1, sizeof(*ch));

That would accomplish the same thing without using the return value,
though it is no prettier than the CREATE macro. Using calloc directly
would be a better way of allocating memory IMO.

> Now, please. Let that discussion drop. It's becoming a religious thing.
> *shiver*

This will be my last post on the matter, unless something new must be
said :)

> I'm against patching to your heart's content, but i beleive that we should
> make Circle a little bit more
> modular. For example, by hiding the data structures a bit more. Has an
> example, we shouldn't know that
> The world is in an array, that there are prototypes or even how the
> caracters in a room are maintained.

Very much one of my points.  Abstracting the data behind functions
would be very nice.  I hope such things move into Circle stock.

> That would be cleaning up code and making the stock code much more solid
> than it is now. Not deciding wether GET_BLAH should be a function or a
> macro. In most cases it would be just cosmetic.

Not true... it isn't always cosmetic.  Macros have major shortcoming
when it comes to changing underlying data.  By this, I do not mean
simply moving an entry in a structure to a substructure or whatnot.  I
mean something like drastically redoing the way structures are laid
out.  Suppose the decision was made that an array of rooms isn't the
best way to go.  Right now, all the code that does

for (tch = world[ch->in_room].pepople; tch; tch = tch->next_in_room)

Would need overhauling.  But if it had been done originally like:

CharList *l;
for (l = chars_in_room(ch); l; l = l->next) {
Or another way,

Iterator i;

for (i = chars_in_room_iterator(ch); i; i = next(i)) {
  tch = iter_to_ch(i);

Data is hidden.  We don't directly poke into the world array.  We
don't repeat code.  It's nicer, more elegant, and easier to read,
though the second adds a very slight kludge.  We could define macros
to make this easier, though normal functions will do just fine.

> Well just my thougts.

Very much appreciated.  Discussion like this is why I made the
original thread -- not to argue and argue and argue the same thing
over and over, or to start holy wars.


James Turner     

     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     | |

This archive was generated by hypermail 2b30 : 12/15/00 PST