I understand why it is a good idea to code to an interface rather than to a concrete class. I find it hard to implement though as other methods generally need to use properties of the given object. Have I got the wrong end of the stick?
C# Design – Coding to Interfaces
cdesign
Related Solutions
The following are simple principles you can apply to helping you understand how to balance your system design:
- Single Responsibility Principle: the
S
in SOLID. You can have a very large object in terms of number of methods or the amount of data and still be upholding this principle. Take for instance the Ruby String object. This object has more methods than you can shake a stick at, but it still only has one responsibility: hold a string of text for the application. As soon as your object starts to take on a new responsibility, start thinking hard about that. The maintenance issue is asking yourself "where would I expect to find this code if I had problems with it later?" - Simplicity counts: Albert Einstein said "Make everything as simple as possible, but not simpler." Do you really need that new method? Can you accomplish what you need with the existing functionality? If you really think there needs to be a new method, can you change an existing method to satisfy all of what you need? In essence refactor as you build new stuff.
In essence you are trying to do what you can to not shoot yourself in the foot when it comes time to maintain the software. If your large objects are reasonable abstractions, then there is little reason to split them up just because someone came up with a metric that says a class should be no more than X lines/methods/properties/etc. If anything, those are guidelines and not hard and fast rules.
[1] Add virtual "getters" & "setters" to your properties, I had to hack another control library, because I need this feature:
abstract class Control
{
// internal fields for properties
protected int _Width;
protected int _Height;
protected int _BackColor;
protected int _X;
protected int _Y;
protected bool Visible;
protected int BorderWidth;
protected int BorderColor;
// getters & setters virtual !!!
public virtual int getWidth(...) { ... }
public virtual void setWidth(...) { ... }
public virtual int getHeight(...) { ... }
public virtual void setHeight(...) { ... }
public virtual int getBackColor(...) { ... }
public virtual void setBackColor(...) { ... }
public virtual int getX(...) { ... }
public virtual void setX(...) { ... }
public virtual int getY(...) { ... }
public virtual void setY(...) { ... }
public virtual int getBorderWidth(...) { ... }
public virtual void setBorderWidth(...) { ... }
public virtual int getBorderColor(...) { ... }
public virtual void setBorderColor(...) { ... }
public virtual bool getVisible(...) { ... }
public virtual void setVisible(...) { ... }
// properties WITH virtual getters & setters
public int Width { get getWidth(); set setWidth(value); }
public int Height { get getHeight(); set setHeight(value); }
public int BackColor { get getBackColor(); set setBackColor(value); }
public int X { get getX(); set setX(value); }
public int Y { get getY(); set setY(value); }
public int BorderWidth { get getBorderWidth(); set setBorderWidth(value); }
public int BorderColor { get getBorderColor(); set setBorderColor(value); }
public bool Visible { get getVisible(); set setVisible(value); }
// other methods
public Rectangle ClipRectange { get; protected set; }
abstract public void Draw();
} // class Control
/* concrete */ class MyControl: Control
{
public override bool getVisible(...) { ... }
public override void setVisible(...) { ... }
} // class MyControl: Control
I know this suggestion is more "verbose" or complex, but, its very useful in real world.
[2] Add an "IsEnabled" property, do not confuse with "IsReadOnly":
abstract class Control
{
// internal fields for properties
protected bool _IsEnabled;
public virtual bool getIsEnabled(...) { ... }
public virtual void setIsEnabled(...) { ... }
public bool IsEnabled{ get getIsEnabled(); set setIsEnabled(value); }
} // class Control
Means you may have to show your control, but don't show any information.
[3] Add a "IsReadOnly" property, do not confuse with "IsEnabled":
abstract class Control
{
// internal fields for properties
protected bool _IsReadOnly;
public virtual bool getIsReadOnly(...) { ... }
public virtual void setIsReadOnly(...) { ... }
public bool IsReadOnly{ get getIsReadOnly(); set setIsReadOnly(value); }
} // class Control
That means the control can display information, but cannot be changed by the user.
Best Answer
I don't see why needing properties matters. Don't focus on what you need to perform the operation, but rather what operations are needed. The data needed to perform said operations will be determined by the implementing classes.
For example, you have a
Shape
interface. One of the methods in this interface isgetArea()
. You say that anything that is aShape
must be able to calculate its area - that implies that it must have the appropriate properties and members to do so. If aCircle
class implements the shape interface and needs agetArea()
method, that implies that (sincegetArea()
doesn't take any parameters), that theCircle
instance must be aware of it's radius. If aRectangle
class implements theShape
interface, that implies that it must somehow maintain its length and width.