views:

117

answers:

4

Update: Please read this question in the context of design principles, elegance, expression of intent, and especially the "signals" sent to other programmers by design choices.

I have two "views" of a set of objects. One is a dictionary/map indexing the objects by a string value. The other is a dictionary/map indexing the objects by an ordinal (ordering integer). There is no "master" collection of the objects by themselves that can serve as the authoritative source for the number of objects, but the two dictionaries should always both contain references to all the objects.

When a new item is added to the set a reference is added to both dictionaries, and then some processing needs to be done which is affected by the new total number of objects.

What should I use as the authoritative source to reference for the current size of the set of objects? It seems that all my options are flawed in one dimension or another. I can just consistently reference one of the dictionaries, but that would codify an implication of that dictionary's superiority over the other. I could add a 3rd collection, a simple list of the objects to serve as the authoritative list, but that increases redundancy. Storing a running count seems simplest, but also increases redundancy and is more brittle than referencing a collection's self-tracked count on the fly.

Is there another option that will allow me to avoid choosing the lesser evil, or will I have to accept a compromise on elegance?

A: 

If both dictionaries contain references to every object, the count should be the same for both of them, correct? If so, just pick one and be consistent.

Mark Ransom
Just want to register my dislike for this option because it implies to other programmers there might be a _reason_ I chose that dictionary over the other, when in fact there is not.
Chris Ammerman
+3  A: 

I'd suggest encapsulation: create a class that hides the "management" details (such as the current count) and use it to expose immutable "views" of the two collections.

Clients will ask the "manglement" object for an appropriate reference to one of the collections.

Clients adding a "term" (for lack of a better word) to the collections will do so through the "manglement" object.

This way your assumptions and implementation choices are "hidden" from clients of the service and you can document that the choice of collection for size/count was arbitrary. Future maintainers can change how the count is managed without breaking clients.

BTW, yes, I meant "manglement" - my favorite malapropism for management (in any context!)

Ken Gentle
Hopefully it doesn't end up being a "manglement" object.. There are plenty of those around as it is!
Dana the Sane
A: 

I don't think it is a big deal at all. Just reference the sets in the same order each time you need to get access to them.

If you really are concerned about it you could encapsulate the collections with a wrapper that exposes the public interfaces - like

  • Add(item)
  • Count()

This way it will always be consistent and atomic - or at least you could implement it that way.

But, I don't think it is a big deal.

Tim
+3  A: 

I would create a class that has (at least) two collections.

  • A version of the collection that is sorted by string
  • A version of the collection that is sorted by ordinal
  • (Optional) A master collection

The class would handle the nitty gritty management:

  • The syncing of the contents for the collections
  • Standard collection actions (e.g. Allow users get the size, Add or retrieve items)
  • Let users get by string or ordinal

That way you can use the same collection wherever you need either behavior, but still abstract away the "indexing" behavior you are going for.

The separate class gives you a single interface with which to explain your intent regarding how this class is to be used.

Steve Duitsman
Exactly what I was going to say. I'm to the point where I NEVER pass around an un-encapsulated collection any more. I've always got an object wrapping it because a collection alone isn't a full object--it can't be protected and doesn't mean anything.
Bill K