Too many men
There’s too many people
Making too many problems
And not much love to go round
Can’t you see?
This is a land of confusion.
Genesis, Land of Confusion
…Well, there IMHO there is a problem with the way in which we’re coding. And this problem come from the fact that the classes represent a (rather) static system designed on premise in order to address the needs of a problem which is dynamic in its nature…
There exists different approaches to guess (hence to cover) what will be the concrete needs of the (un)known client (this because most frameworks are written by 3rd parties, isn’t?) somewhere in the future in an (un)known application.
One approach is granularity. Many small classes ready for reuse – usually covering general targets – sometimes aggregated in bigger entities.
Another approach is by using generics in order to decouple the algorithm from the data types.
A third one are by using interfaces. A bunch of them, in order to allow as many uses as possible. And it seems that this is the ‘mode du jour’ today (even if is needed or not).
But with all these approaches (in which one doesn’t exclude the other) there exists a lack of flexibility in adapting them to our code. Of course there are ‘workarounds’ but I don’t want to comment now their quality in public. An example is when we use the is operator:
if aView is TcxGridDBBandedTableView then //an 'If' on each class. How sweet! with TcxGridDBBandedTableView(aView) do //Hard Cast. Best Delphi thing. FActiveFIeld:=DataController.DataSet.FindField(Controller.FocusedColumn.DataBinding.FilterFieldName); //...imagine that here we have a gazillion of if's for all Grids, Charts and Card Views...
Another one, quite common, is when we use the RTTI to see that a property exists and if exists we play with it (eg. assign some value to it). This is very ‘nice’ one because we have no support from the compiler (type checking etc.), the code is convoluted and besides that we have the honor (or should I say horror?) to work with pointers and other obscure PropInfo structures (ok, things are much better in Delphi 2010) – and of course is enough slower than a direct assignment.
But what if instead having on premise interfaces, function arguments, generics burned in the 3rd party framework we have a language structure on our side which will say “if the class looks like ‘this’ use it like ‘this’“?
For example, let’s have a class signature. A class type:
TDataAwareHighlighter = class type public procedure Repaint; //we have this just in case - see bellow published property Color: TColor; property DataSource: TDataSource; end;
And to use it…
First write my own custom procedure to ‘alter’ the behavior the 3rd party framework (in this case VCL):
procedure HighlightDataAwareControl(aControl: TDataAwareHighlighter); //ok, we can put a shorter name here begin case aControl.DataSource.DataSet.State of dsInsert: Color:=clClream; dsEdit: Color:=clYellow; else Color:=clWindow; end; end;
As you see, we didn’t use the
Repaint method. We included it in the signature though because we wanted to be sure that the component (re)paints itself. (IOW, is a TControl descendant). As an alternative we could have in the class type the
InheirtsFrom in order to allow us to use it:
TDataAwareHighlighter = class type public class function InheritsFrom(AClass: TClass): Boolean; published property Color: TColor; property DataSource: TDataSource; end;
And then in our actual code we’ll test if the
aControl.InheritsFrom(TControl) returns True.
(of course, this is not mandatory. If you want to have some class with these properties and play with them using a type class, so far so good).
And of course the actual usage will be, in our form:
begin HighlightDataAwareControl(TmyDBGrid); HighlightDataAwareControl(TmyDBEdit); HighlightDataAwareControl(TmyJvDBGrid); //JVCL! Yeah! end;
Of, course additional tooling like
TObject.IsClassTypeOf() will appear after.
- Greater flexibility in extending different frameworks (hint, hint OPFs, MVCs – these class types can act as mediator helpers between GUI and controllers)
- Higher code quality – cleaner, easier to maintain, type checking at compile time
- Speed – I hope that the compiler will resolve the calls / pointers at the compile time, right?
- Generics on steroids. – ’nuff said.
Things to discuss:
- What do you think?
- The syntax is ok? (Wording etc.)
- It should have visibility specifiers or just a simple flat list of identifiers?