views:

21

answers:

1

I have a class that I wrote fairly early on in my vb.net programming experience which inherited from another class it really should have composed. The base class is a relatively generic nested dictionary-based collection; let's call the descendant class a "Car".

Right now there's a lot of code that does things like 'MyCar!Color.st = "Red"' (I use the generic collection rather than real properties to facilitate data interchange with code written in VB6, and also to facilitate comparisons of cars; given three cars X, Y, Z, I can e.g. detect any changes between X and Y and apply those changes to Z).

Is there any nice way to refactor the code to use composition rather than inheritance? Which properties/methods should the "Car" object wrap, and which ones should be accessed through a data-object property? Should a widening conversion be defined between a car and the collection object? Are there any gotchas when doing such refactoring?

+1  A: 

You could start by saying Car has a function (or method; not sure of the vb.net terminology) to get its collection - and that function would initially return this (or self, or whatever vb calls it).

Now replace all direct references to Car-as-Collection with Car.getCollection(), both within the Car class and outside.

Finally, make the change: create a member variable, initialize it, return it from getCollection(), and stop inheriting from Collection. If you missed any references in step 2, they'll show up as compile errors at this point. Fix them and your refactoring is complete.

Carl Manaster
The replacing of direct references to car-as-collection would seem the tricky part. Perhaps create stub methods in Car that shadow those of the collection, rename them with a unique prefix, and then find/replace that prefix to "data."? That should successfully convert all implicit references other than those using the default property; my thought would be that the default property could just be wrapped. Would that seem like a good idea? Most of the data associated with each Car will be in the collection, so Car!Color would seem nicer than Car.data!color. Does that seem like a good idea?
supercat
@supercat without seeing the code, it's hard to say for sure, but I would think that the transformation you suggest would be just as much work as the direct change. Nevertheless, if (for instance) Color is something particular to cars, something that will be referenced frequently, it's a fine idea to create methods which make that clear. Defining your API in this way - "every car has a color" - independently of how it's represented internally - is what class design is all about.
Carl Manaster
The idea behind using the abstract collection object rather than more rigid properties was to allow abstract comparisons between Car objects. When a car "comes into the shop", I clone it to record its information; the next time it comes in, I can see what's changed. New properties can be added without the comparison logic having to know about them. The collection is essentially schema-less, which is somewhat icky, but I don't know how else to set up objects for exchange with VB6 and abstract comparisons.
supercat