views:

116

answers:

2

Hi,

I recently posted this C++ DAL question about how best to design a 'loadCar' method in a C++ DLL, with the consensus being that 'bool DAL::loadCar(int id, Car&) {}' would be the best signature to use.

Now, it so happens that in a lot of our use cases the client code will often want to retrieve the car's manufacturer with the car object. The 'car' table in the database has a foreign key (MANUFACTURER_ID) to the manufacturer table. I'm now thinking of having an optional field in the Car class, something like:

class Car
{
  public:
    void setModel(...);
    void setEngineSize(...);
    Manufactuer getManufacturer();

  private:
    Manufactuer /* Reference, Pointer or Value - TBD */ manufacturer_;

  // etc.
};

The question is would you have the Manufacturer private member as a pointer, reference or a simple value type, i.e. one of:

Manufactuer *manufacturuer;
Manufactuer &manufacturuer; // Illegal - needs to be initialised, so use Null Obj Pattern?
Manufactuer manufacturuer;

Now, the loadCar method would have a bool loadManufactuer parameter (default false). I.e. we only want the cost and storage overhead of loading the manufacturer some of the time. This makes me think that I should store the Manufacturer as a pointer (1st option).

Note, the reason I'm not pusing the composition up a level is that I want the DAL to be able to compose a Car + Manufacturer using a single database query. Note that although not shown here the user could query for a collection of Car objects.

I was unsure about using a pointer as it feels like I'm now mixing pointers with references, but can't see how this would be done otherwise without introducing a lot of temporary variables. Maybe a Singleton Null Object would help?

Hope that makes sense.

+1  A: 

You should take a slightly different approach I feel. why not have a manufacturer ID in the Car object? If a manufacturer is needed at some point, then load via the id. You can hide that by lazy loading.

Basically have a manufacturer object that only populates the fields if those fields are accessed.

Preet Sangha
Because the a large number of loads will need the manufacturer. It would be prohibitively expensive in our real application to go to the database again when manufacturer data is required.
ng5000
+1  A: 

Since Manufacturer can be the same for many cars I would create a Manufacturer Service which will manage Manufacturer collection as collection of pointer. This service will be able to create Manufacturer, destroy Manufacturer, search Manufacturer, provide, etc... This Singleton class will have a load function that will get data from database and generate all manufacturer.

Then the Car object will be able to ask Manufacturer to the service and store the pointer. By using this way, Car classes will only use Manufacturer pointer whereas Manufacturer pointers management will be the fact of the service.

Patrice Bernassola
I like this idea ... a cache of manufacturer objects would be a good plan. Especially if combined with preet's idea.
Goz
Just remember to externalise the caching strategy from either the car or the manufacturer. This will allow you to manage them in more controlled ways and more flexibly.
Preet Sangha
In our real application these object represent data tables that change very frequently. The cache TTL would therefore have to be so low as to not be worth it. Also, in our real world the size and number of "manufacturers" would place a real memory burden if we were to cache them all.
ng5000