[crossfire] 2.0 object-type refactoring
Mark Wedel
mwedel at sonic.net
Sun Oct 29 23:35:12 CST 2006
Few questions:
Use form of server/types/foo.c or server/types/foo/bar.c depending on if the
object type requires multiple C files to be clean.
With the fact that the SVN repository is called server, it is unclear exactly
what server refers to.
If we include the repository name, is it:
server/server/types
server/common (example of existing directory)
Or
server/types
common/ (being the exististing directory)
IMO, I'd prefer the second form - put the types directory at the top level,
relative to the server directory. This is how the socket code is, doesn't have
any real disadvantage, but could have some advantages (better for unit tests?
Better for stand alone program that does simulations, etc?)
Function pointers:
It's not specifically mentioned on how the callbacks are registed. I see one of
two ways:
register_apply_callback(type, funcpointer);
or
register_callback(type, funcpointer, callback_type)
Both have pros and cons. The first case has the advantage that the compiler
can do actual type checking on funcpointer. The second has the advantage you
don't need as many callback functions, and it makes it easier to add new
callbacks (add the new callback_type #define, update the number of callback
types, and recompile. One could even do things like:
callbacks[ob->type][CALLBACK_TYPE](....)
It's also not really mentioned on how the callbacks themselves are registered
(that code has to be someplace). And rather than having a single function that
registers all the callbacks for all the object types, I'd suggest that each type
file has something like init_callbacks_weapons (or something). Then in some
other place, you have that function that calls all the init_callbacks - having a
function of MAX_TYPES lines longer is much better than one of MAX_TYPES *
MAX_CALLBACK_METHODS lines long.
The other advantage of this is that the individual types files themselves can
then declare all the functions except the init function static, so that it can't
be called by other functions.
I suppose that one could use various system function calls to try and look up
the function names and call them (presuming a standard naming scheme, like
init_callbacks_46, where 46 is the type number for that object), but that may be
overly complicating things.
Other thoughts:
It may be better working on getting all of this infrastructure/callback methods
in place, and implementing one type of object using them instead of focusing on
the specific callback method (the web page mentioned doing all the apply stuff).
Why? That way, if someone does write code for a new object type, all the
pieces are in place so they can use the new method. If only the apply callback
is implemented, they can use that logic, but are left using old coding method
for the other areas, that then needs to be converted down the road.
Also, by doing all the different callback methods, it provides better coverage
of the callback logic, eg, if there are issues with any of the methods, they
will be found sooner vs later.
Second, if we're going to be writing all new functions, we should use some other
'best practices'. In particular, for anything that would return a string value,
they should be modified so that a string pointer (and length of that pointer) is
passed in, instead of using static return buffers. This will assist if we ever
thread the server, but it will also help prevent a few bugs (related to this,
sprintf, strcat, and strcpy should never be used, but rather snprintf, strncat,
and strncpy instead)
More information about the crossfire
mailing list