I'm in the process of building an application which needs extensive logging of points in time at which certain events happen. For example when it renders a sequence of different shapes to the screen then we need a logfile with info like 'shape A rendered to surface at time X, shape B rendered to surface at time Y, surface flipped at time C' etc. in response to comments These names (A,B) should be meaningful and will either be user-defined (e.g. 'MyGroupOfRectangles') or automatically generated (like shape type + number, e.g. 'Rectangle1' or for bitmaps/avis/... use the filename). Main reason for this is that most of the time the logfile is going to be interpreted simply by the user reading it and quickly checking out if the sequence is doing what he/she wants to.
In order to make this happen it's clear that at the moment the log function is invoked it needs to know the name of the shape it's going to log about. One could just give any type of object which is going to be logged about a string member. However thinking about that there are some implementation- and design-wise questions which make me doubt that approach. But other approaches in turn have other problems.
The major question being (almost philosophical - I'm probably overthinking this): should an object know it's own name? After all it's merely an implementation detail here, used solely for logging - if I wouldn't want to log Shapes by their name they wouldn't need to be named at all.
So does it make sense to stuff the name in there as well, or would it be a better practice to keep a map somewhere which links object instances to a name? Something like
Map< Shape, string > shapeNames;
string NameForShape( Shape s )
{
return shapeNames.Contains( s ) ? shapeNames[ s ] : "<unnamed>";
}
This is very much unintrusive but does introduces some other potential problems in keeping the map up to date with existing shapes: should a shape be destructed, it's name also has to be erased from the map.
The other option (or if there are multiple other options, by all means let me know) is to make a Shape returns it's name. Being an interface it could be like this:
interface Shape
{
void Render();
...
string Name();
}
However this means every implementation has to take care of providing the Name()
implementation and they're likely to going to be doing that all in the same way, like
class Rect : Shape
{
public:
Rect( string name ) : { this->name = name; }
string Name() { return name; }
private:
string name;
}
That's quite some boilerplate and DRY is a holy rule so raises more questions: do I get rid of the pure interface and make it abstract instead (not ideal for unit testing)? Or do I add an extra layer with a default Shape implementation like NamedShape which partially implements Shape and just provides Name() (extra inheritance layer is not ideal either)?
this
.