Reputation: 142
I'm working on a legacy application wich has some flaws due to inheritance, but I'm struggling to solve it properly.
At the moment the structure of the WinForms looks like this:
BaseForm
ListViewForm : BaseForm
ListViewFormReadOnly : ListViewForm
ListViewFormWithDetailForm : ListViewForm
DetailForm : BaseForm
ConcreteForm : ListViewFormWithDetailForm
There is a method inside the BaseForm which is called sth like protected virtual void InitializeMyStuff()
which is overwritten in the inherited instances.
e.g.
public class BaseForm {
public BaseForm() {
//.. do stuff
//.. do other stuff like initialize DB connection or read app.config values and initialize properties..
}
public virtual void InitializeMyStuff() {
throw new NotImplementedException();
}
}
public class ListViewForm : BaseForm {
protected BindingSource GridBindingSource { get; set; }
public ListViewForm {
//do special stuff like adding the grid and some buttons
}
}
public class ConcreteForm : ListViewForm {
public override void InitializeMyStuff() {
GridBindingSource = my_bindingSource;
SomeOtherUsefulProperty = myValue;
Foo = new Bar();
// etc.
}
}
//Usage:
var myForm = new ConcreteForm();
myForm.InitializeMyStuff();
As you can imagine this creates some problems like: - "What things do I have to set at this point for the form to work" - "What things may not be initialized yet?" - "Which properties and method calls are at my disposal yet" and some other interesting thoughts about what may be going on in that magic blackbox.
How can I refactor this so that it gets more clear what is happening? Remember that this is a project with about 150 or more concrete forms.
My initial thought was to encapsulate those magic properties like the GridBindingSource
for example into an object (e.g. FormConfiguration
) and make it private in the BaseForm
.
e.g. something like that
public class BaseForm {
private FormConfigObject _formConfig = new FormConfigObject();
protected override void OnLoad()
{
InitializeMyStuff(_formConfig);
}
protected virtual void InitializeMyStuff(FormConfigObject config)
{}
}
The problem I have here is: the FormConfig object of the ListForm would have to have other properties for example, like GridBindingSource
but I can't just change the signature in the derived classes to an ListFormConfigObject
isntead of the FormConfigObject
..
Can anybody suggest possible solutions to get out of this dilemma?
// Edit: straightnened out the code to what actually happens and getting rid of the virtual call in the constructor violation.
Upvotes: 3
Views: 231
Reputation: 35891
The main question is this: are there any objects inside BaseForm
that:
BaseForm
's constructorIf such objects exist then probably they should be made polymorphic, and passed into BaseForm
's constructor from subclasses.
A simple example, on of many possible scenarios:
abstract class RandomPicture
{
public RandomPicture()
{
shapes = new List<Shape>();
InitializeRandomShapes();
// do some initial drawing calculations
}
protected abstract void InitializeRandomShapes();
protected List<Shape> shapes;
}
//... subclasses initialize the shapes
This can be changed to:
abstract class RandomPicture
{
public RandomPicture(AbstractShapeCollection shapeCollection)
{
shapes = shapeCollection;
// do some initial drawing calculations
}
private AbstractShapeCollection shapes;
}
And now subclasses provide the required information through the abstract object, so the base class can proceed with it's task.
Splitting information into various objects like this is a good refactoring start, as you create more smaller objects, that are easier to test and manage and reveal the underlying structure of a mess that you've encountered. It helps also to reduce the number of violations of Single Responsibility Principle.
Upvotes: 3