views:

39

answers:

1

Design philosophy question:

  1. Suppose I have a user control which draws a graph of the characteristics of a collection of objects.
  2. The control is placed on a form with a long-lived controller class that exposes the collection of objects to draw from.
  3. The form also contains a control which allows to switch between 'modes' or different plotting styles. The logic that the objects being drawn from use to expose their public properties is fundamentally different between different modes, but the control doesn't care about this.
  4. The initial caching of data to the object instances is quite laborious and causes performance issues with some functions of the displaying control.
  5. Despite having different logic, the object instances represent the same set of modelling variables/things (however you like to imagine them) before and after a mode change

The nature of the problem in point 3 suggests that the collected instances should be taken as abstract bases, and there be two different derived classes with different internal logic. Unfortunately this suggests that the entire collection of objects should be completely regenerated at each mode switch, wasting clock cycles.

Does anybody have any examples of a neat pattern for transferring cached data between different implementations of a base? I considered an overloaded constructor that takes an instance of the base class, but that sounds quite horrible at first look. Maybe people disagree and like this style, in which case I'll consider the matter settled.

edit #1:

Some clarification of the specifics of this problem; I'd guessed my original question was probably quite vague...

Let the binding property which the control attaches to be List<BaseClass> ControllerClass.Items, for example.

Let the properties which the control interrogates to do its work be things like

double BaseClass.NumericProperty
IEnumerable<Thing> BaseClass.AggregateProperty

Let there be (at least) two different subclasses of BaseClass called DerivedClass1 and DerivedClass2. When the control switches mode, the intent is that ControllerClass.Items will represent a list of items which perform the appropriate internal logic to expose those properties.

I am suggesting that internally on a mode switch, i.e. setting Controller.Mode = NewMode, the controller will create a new set of DerivedClass2 by doing something like _list_internal[i] = new DerivedClass2(_list_internal[i]) where _list_internal currently contains a set of DerivedClass1s, then raise an event (like an INotifyPropertyChanged or whatever) to inform the control. The constructors of both DerivedClass1 and DerivedClass2 take a BaseClass as an argument, which is broken down to retrieve the data that will be common to both.

My question is, is this a recognised pattern; if not, why not, and what are the alternatives, keeping in mind efficiency and the need to not throw away data every time the UI does anything.

+2  A: 

I agree with mikemanne that the question is a little vague, but from what I understand, for maximum performance when switching modes, you'll have to accept a slightly higher startup crunch:

  • The controller should work with both the graph user control and the mode switcher. Basically, it becomes a page controller instead of a task controller.
  • The controller should pre-hydrate and maintain a collection of objects that contain the base data for all display modes. These can be the actual objects from your domain model, or a collection of lightweight DTOs that contain the results calculated from the domain.
  • The controller, when asked to switch modes, should employ a seperate DrawHelper class to transform the data points into the graph. Each DrawHelper works for one graphing mode, and they all look the same to the controller (they inherit from the same base type or interface). This is known as a strategy pattern.

The following are no-nos:

  • DO NOT put the logic required to turn the data into a graph point into your domain model. The domain model should not have to know how you plan to use its data, because if it did, and that changed, the domain object would change when the domain (its basic responsibility, which should be its only one) didn't.
  • DO NOT rehydrate the data every time without exception. This is what you know you're trying to avoid, but to do so, make sure your controller is actually "long-lived"; many web framework lifecycles destroy everything used on the server side between requests, only keeping the "session" statebag around and requiring you to re-hydrate your controller.
  • DO NOT put the drawing logic in the controller; it will get huge. You shouldn't even put the DrawHelper selection logic in the controller; instead, have the Controller know about a "factory" that can give it the DrawHelper it needs based on the current mode.
KeithS
Accepted as the answer because something **KeithS** said prompted me to change my tactics somewhat. I am experimenting with making the `BaseClass` a generic, which takes something I'm calling a `PluggableDTO`. This way the functional logic can be swapped out with the main controller being none the wiser, as there's an extra layer of abstraction sitting between them AKA the appropriately designed BaseClass. If anybody's interested I'll post a code sample when it's somewhere near working.
Tom W