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.
The main question is this: are there any objects inside BaseForm that:
are required to be initialized in BaseForm's constructor
depend on the concrete implementation of the subclasses
If 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.
Related
I have two classes that I would like to share code between. These classes represent screens in my app, and both inherit from a base screen class. The first class (MyList) already exists, and encapsulates most of the behavior that I want to perform. The second class (MyNewList) needs only to slightly tweak the behavior in the first class.
Normally, I would have MyNewList inherit from MyList and be done with it. But, in this case, both classes have common code which is auto-generated into those classes. This code causes loads of warnings because MyNewList is hiding MyList members without using new or override.
To make things even stickier, some of that code could be shared 100% (exact same fields), and the rest needs to be unique to each class.
To make matters more difficult, the code generator cannot be modified to change the output. I also cannot trigger the code generation into a separate abstract base class, which would allow both classes to inherit from the common base.
The two classes represent different custom implementations. It is possible to simply use the first class and add some branching logic to perform the behavior that MyNewList wants (and eliminate MyNewList). However, my lead developer would like it to be a separate class. I understand that desire - it's cleaner if we can use inheritance, but I don't see a solution here.
Below is my code, attempting to use inheritance:
public class MyList : ScreenBase
{
protected override void PageLoad()
{
base.PageLoad();
//Do page loading type stuff
}
protected override void PageRefresh()
{
base.PageRefresh();
//Do page refreshing type stuff
}
protected override void PageClose()
{
base.PageClose();
CloseThePage(RESULT_CLOSE);
}
#region Auto-generated code
public const string RESULT_LOAD = "Load";
public const string RESULT_BACK = "Back";
public const string RESULT_CLOSE = "Close";
public string Property_Date
{
get { /*get date from somewhere*/ }
set { /*assign date to somewhere*/ }
}
public void CloseThePage(string result)
{
//Route to next location based on result
}
#endregion
}
Second screen:
public class MyNewList : MyList
{
protected override void PageLoad()
{
base.PageLoad();
//Do additonal page loading behavior
}
//allow the rest of the base behavior to take over
#region Auto-generated code
public const string RESULT_LOAD = "Load";
public const string RESULT_BACK = "Back";
public const string RESULT_CLOSE = "Close";
public string Property_Date
{
get { /*get date from somewhere*/ }
set { /*assign date to somewhere*/ }
}
public void CloseThePage(string result)
{
//Completely different routing behavior here
}
#endregion
}
Everything inside of the #region Auto-generated code region shows hiding warnings with this approach.
How can I reuse MyList's event code from inside of MyNewList?
I've got a class with a list of properties, and the properties themselves have a list of properties. I need the "grandchild"- property to be able to request data from it's parent's parent (sorry for the confusing terms - there's no inheritance here). To clarify:
class ClassA
{
list<ClassB> Children
var SomeOtherProperty
}
class ClassB
{
list<ClassC> Grandchildren
}
class ClassC
{
var GetSomeOtherProperty()
{
...
}
}
The data may change during run time so I can't just pass it once and be done with it, I gotta be able to get it dynamically.
I could always pass the parent all the way down to the grandchild in the ctors, but I was taught it's a bad practice, so I'd rather avoid it.
I've been reading about passing data back/downwards via events using mutable EventArguments- I'm wondering if that'd be an OK solution for what I've got (I'll need to do it twice each time- sort of chase the tail of the first eventarg). Are there any pitfalls I need to be aware of?
Do I have any other options for this situation?
Thanks!
If possible, you can use the design pattern composite. First, create a base class 'note' with a list of notes for the children and a virtual method 'DoAction'. Then derive all other classes from this class and override the method with own implementation.
Now you can build up a tree of notes and do a traversal on all of it childs. For each of them, call 'DoAction'.
Hope you get the idea...
Since classes A, B & C are not liked via inheritance, therefore, I would like to avoid any direct wiring between these classes as it will make the design a little complicated as the system would evolve.
Moreover, since class B has nothing to do with the data, I dont want it to get effected by it.
Therefore, I would like to take out the communicate via a separate route to keep the classes loosely coupled -
here is a sample code to explain my idea -
public interface IPublisher
{
event EventHandler OperationOccurred;
}
class ClassA : IPublisher
{
List<ClassB> Children;
event EventHandler OperationOccurred;
public ClassA()
{
BroadCaster.Instance.RegisterPublisher(this);
}
protected virtual void OnOperationOccurred()
{
if (OperationOccurred != null)
OperationOccurred(this, new EventArgs());
}
}
class ClassB
{
List<ClassC> Grandchildren;
}
class ClassC
{
public ClassC()
{
BroadCaster.Instance.BroadCastNotificaiton += Instance_OperationOccurred;
}
void Instance_OperationOccurred(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
/// <summary>
/// A singleton class ... Like a single braodcast tower just one in the city
/// </summary>
public sealed class BroadCaster
{
public static BroadCaster Instance { get; private set; }
//Static constructor
static BroadCaster()
{
Instance = new BroadCaster();
}
// private constructor
private BroadCaster(){}
public event EventHandler BroadCastNotificaiton;
public void RegisterPublisher(IPublisher publisher)
{
publisher.OperationOccurred += Publisher_OperationOccurred;
}
void Publisher_OperationOccurred(object sender, EventArgs e)
{
if (this.BroadCastNotificaiton != null)
this.BroadCastNotificaiton(sender, e);
}
}
I have implemented broadcaster a singleton object, but all I want to convey is a single point of communication.
Hope it helps.
I haven't done this for a while and I need to find out if this is the best OO way to go. I am having trouble assigning (Setting) the protected properties in a base class in the derived class. I have a solution but I like to know if this is the best design pattern to use or is there a better way?
My Base class
public abstract class EmailBase
{
protected string Subject { get; set; }
protected string To { get; set; }
protected string From { get; set; }
protected virtual void Send()
{
using (MailMessage mail = new MailMessage())
{
// Ok send message here...
}
}
}
I have two different email templates that I need to send so I thought it would be a good idea to have two derived classes, however I will post the code for one derived class for the problem at hand.
public class DerivedOne: EmailBase
{
private const string emailTemplate = "some static text for the body...";
public DerivedOne()
{
}
// This is how I want to set the base class properties,
// but it feels I am just duplicating properties...
public string To
{
set
{
base.To = value;
}
}
And in the controller...
// A send email button was pressed by the user
private bool SendEmail(Model)
{
DerivedOne eMail = new DerivedOne()
{
To = Model.To;
};
}
I tend to not send the properties through the derived constructor as I believe setting up properties tends to be cleaner. However, I know in the derived constructor you can set the base properties : base()
So this is why I have asked, am I wrong to create the same properties in the derived class so the controller can see it? (as the protected properties cannot be seen outside of inheritance of course)
Yes, I think that you right with your doubts. We should tend to avoid duplication wherever possible and use the full power of OOP.
Plus, you could avoid a lot of problems by making your classes immutable and providing dependencies via constructor. If class needs dependency to be consistent, this dependency should be provided via constructor. Doing this could guarantee yourself(and other programmers) that you can't create instance of class without providing this dependency. For example, in your case I believe you can't send Email without providing To information, so it's better to provide To via constructor. The same reasoning could be applied for other dependencies.
Plus, assigning protected properties in derived classes in itself could be a problem and could lead to violations of Liskov-substitution, Open-close and other SOLID principles. But, of course, sometimes it could be useful, and there is no general rule of not doing this.
I'm currently working on a C# program that creates a List, of object Task, the object Task is a base class and many other inherit from it. What I want to is compare the type of one of the object within said list to see which form should be opened in order to edit it.
This is the code I have already created.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
if(checkTask.GetType is Note)
{
noteBuilder editNote = new noteBuilder(todoList);
editNote.Show();
}
else if(checkTask.GetType is extendedTask)
{
extendedTaskBuilder editTask = new extendedTaskBuilder(todoList);
editTask.Show();
}
else if(checkTask.GetType is Reminder)
{
reminderBuilder editReminder = new reminderBuilder(todoList);
editReminder.Show();
}
else if (checkTask.GetType is Appointment)
{
appointmentBuilder editAppointment = new appointmentBuilder(todoList);
editAppointment.Show();
}
}
On a secondary note would it be easier if instead of passing the list between the forms and generating a new object of the form that display information that I instead pass a single object between forms and just update the form every time a new element is added to the list.
Many thanks
Have you tried checking like this:
if (checkTask is Note)
{
}
...
Have you considered creating a base class for all types you are now switching between and call a virtual (abstract) method?
Put all code now in the if in the overridden abstract method.
Advantages:
- The intelligence of the switch is within the classes where it belongs.
- When a new type is added you get a compiler error to also add this feature to the new type.
I suggest that instead of doing that series of ‘if’ clauses, you use inheritance to achieve what ou need. First you create a virtual method in your base class. A virtual method means it won't have any implementation in the base class, only the declaration:
public class Task
{
(...)
public virtual void ShowEditForm(IList todoList);
(...)
}
Then you create the child class methods (I'm assuming the todoList object is a IList, but just change it if it is not).
public class Note: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new noteBuilder(taskToEdit)).Show();
}
(...)
}
public class Reminder: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new reminderBuilder(taskToEdit)).Show();
}
(...)
}
I didn't write all the classes, but I think you've got the idea. To call the method, you just call the method from Task class, and the right method will be executed:
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
checkTask.ShowEditForm(todoList);
This way, when you want to create new types of Task, you just have to create the child class, with the proper method, and the inheritance system will do the rest.
One more thing, the override keyword in the child method declaration is important, because it says to the compiler that this method should be called even if you call it from the BaseClass.
First, to your second note. What you are talking about doing is having a global object that all forms refer to in some parent. That can work, however you will need to make sure there is some mechanism in place that makes sure all of the forms are synchronized when one changes, and this can get messy and a bit of a mess to maintain. I am not necessarily advocating against it per say, but just adding words of caution when considering it :)
As to your posted code, it would probably be better to turn this into a Strategy Pattern approach, where all forms inherit from a base class/interface which has a Show method. Then all you need to do is call checkTask.Show(todoList);. If you do not want that coming from the Task, then you could have your forms all inherit from the above base and you could use a factory pattern that takes in the Task and list and returns the appropriate form on which you simply call form.Show();
Code like this is difficult to maintain, you are probably better off abstracting this out, like so (assuming Task is not the one included in .net):
public interface IBuilder
{
void Show();
}
public abstract class Task
{
// ...
public abstract IBuilder GetBuilder(TaskList todoList);
// ...
}
public class Note : Task
{
public override IBuilder GetBuilder(TaskList todoList)
{
return new noteBuilder(todoList);
}
// ...
}
// etc.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
IBuilder builder = checkTask.GetBuilder(todoList);
builder.Show();
}
Alternately, you can use an injection pattern:
public abstract class Task
{
protected Task(Func<TaskList, IBuilder> builderStrategy)
{
_builderStrategy = builderStrategy;
}
public IBuilder GetBuilder(TaskList todoList))
{
return _builderStrategy(todolist);
}
}
public class Note : Task
{
public Note(Func<TaskList, IBuilder> builderStrategy) : base(builderStrategy) {}
}
// ...
note = new Note(x => return new noteBuilder(x));
I know that C# does not offer multiple inheritance. And I know there' are workarounds like this one for instance.
But here's a problem that I faced today, can't figure any ELEGANT workaround. I'll add some abstract code-sample so you get it quicker...
(let it be a real-life ASP.NET code - cause those "class A, class B" code-samples are really confusing):
public class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage, JQueryPage;
Compose out the functionality? This is better for Single Responsibility. You'd have to think carefully about your constructors.
interface IAdminPage {
public string AdminPageMethod();
}
interface IJQueryPage {
public string JQueryPageMethod();
}
internal class AdminPage : IAdminpage {
private string someString;
internal AdminPage(string value) {
this.someString = value;
}
public string AdminPageMethod() {
return "AdminPage result with some string: " + this.someString;
}
}
internal JQueryPage : IJQueryPage {
private int someNumber;
internal JQueryPage(int value) {
this.someNumber = value;
}
public string JQueryPageMethod() {
return "JQueryPage result with number: " + this.someNumber;
}
}
class AdminJQueryPage : IQueryPage, IAdminpage {
private readonly IAdminPage adminPage;
private readonly IJQueryPage jqueryPage;
public AdminJQueryPage(string someString, int someNumber) {
this.adminPage = new AdminPage(someString);
this.jqueryPage = new JQueryPage(someNumber);
}
public string AdminPageMethod() {
return this.adminPage.AdminPageMethod();
}
public string JQueryPageMethod() {
return this.adminPage.JQueryPageMethod();
}
}
If you really want multiple inheritance, look at Scala's traits
Edit: added passing of constructor values to composed out classes. Also made the classes internal (cannot be accessed or constructed outside the assembly) because they are only ever constructed by the AdminJQueryPage class, which is the 'public-facing' class.
I came from C++ too and dont miss it, especially since reading Refactoring [and using a non-OOTB tool for that].
You can use PostSharp to post process based on placing attributes on your AdminJQueryPage which would achieve the exact same effect.
Or you can Extract Method code into helper classes and call that (i.e., Joe's example)
Or you can put the helpers in a single base class and call from that.
Either way your code will be clearer.
It's only a matter of time before your mixins start overlapping, and then your general suite of techniques for managing that complexity needs to kick in - in C++, MI should only have been one tool in a suite - rather than a very sexy hammer.
its possible to fake a mixin by specifying a interface and creating extension methods for that interface. however I'm not use this will help overriding methods, only adding new ones. you are of course able to then call an extension method when overriding, but that is basically the same as extracting the methods to a helper class, but with a little more sugar
Even if it was possible, one problem with the semantics of an MI-based solution to the specific problem you raised is what happens on the markup side? The Render() method that generates the markup would run first in one class, and then in the other? That's probably not the behavior you want when both classes generate entire pages.
If you're open to solutions that are outside of the language itself, there are several elegant options in ASP.NET that will address the type of issue you raised (changing the actions taken during an event in the page life cycle). For example:
Page Adapters
Control Adapters
Custom user controls
HttpModules
Master Pages
Tag mapping
The best choice will of course depend on the details of your application. In case it's helpful, I cover those options in my book, including sample code: Ultra-Fast ASP.NET.
The simplest approach is to build a hierarchy - allow AdminPage to inherit from JQueryPage like so:
public class AdminPage : JQueryPage
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
}
public class JQueryPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
RegisterJQueryScript();
base.OnLoad (e);
}
}
//now here's what I REALLY miss in C#
public class AdminJQueryPage : AdminPage
My guess is some of this awkwardness comes from the ASP.NET page model, which uses overridden base class methods.
You can to do this with Interfaces
public interface IJQueryPage
{
}
public abstract class AdminPage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
//if not an admin - get out
if(!CurrentUserIsAdmin()) Response.End();
base.OnInit (e);
}
protected override void OnLoad(EventArgs e)
{
if (this is IJQueryPage)
{
RegisterJQueryScript();
}
base.OnLoad (e);
}
}
public class AdminJQueryPage : AdminPage, IJQueryPage
{
}