Dienstag, 28. Februar 2012

firemonkey ain't the VCL

While I'm finishing my MVVM framework, I encountered this sobering fact: Firemonkey ain't the VCL.

This is especially true for my ViewModelBinder, which relies on TComponent's Components property to check for controls on the view that match a property or method on the viewmodel. 
Whilst VCL stores its component hierarchy in TComponent.Components, firemonkey introduced a new property: TFMXObject.Children. 
This leads to the fact that in the end I need to make two seperate versions of my framework, one for firemonkey and another for the VCL, unless I find a better solution.
It's a pity to see how existing paths aren't used.

Donnerstag, 2. Februar 2012

it's been a while since my last post...

...but I had my reasons. And now it's all good.

Having had a creative break (ok, my primary work took all of my brains), I revised my work on MVP up to back then.
I had a look around at current presentational patterns and came across PresentationModel aka MVVM.
I digged into caliburn micro, a really great MVVM ramework by Rob Eisenberg. I had a look at his teriffic presentation video from MIX10, back in March 2010. Cudos to him, I was overwhelmed. It took me a while to understand what's going on (I actually have no NET knowledge at all), but I finally got it.

I began to implement my own MVVM framework, inspired by Rob's caliburn micro.
I had some try on XE2's Binding mechanism, but I found it rather bloated, so I created my own simply Binding engine. XE2 Bindings are really hard stuff to grasp, though I managed to use them all by code.

I wanted to make use of Dependency Injection which I'm really fond of. I had a peek at SpringFramework, but in the end I came up with my own solution to that either. If you aren't aware of DI at all, have a look at Nick Hodges' Depenedency Injection series, really cool stuff.
First I created a common IoC, but after that I made a small special version for use with my MVVM framework.

Here's a list of the currently available features:

  • Interface driven MVVM design,  following the ConventionOverConfiguration principle, to keep things easy and understandable.
  • Simple Binding system with support for data formatting and validation using attributes, customizable.
  • Bindings supports list and grid controls, and can be easily extended to support other controls as well.
  • Simple, "to the point" IoC container with MEF style field injection (using attributes) to eliminate dependencies.
  • TViewModelBinder, TViewLocator, TViewManager types to handle views and viewmodels.
  • ...more to come!





Freitag, 28. Oktober 2011

How do I talk to my Presenter (asks the View)?

Reacting on user input is a vital task for an application. But how can this task be acomplished using PassiveView? There are several options to choose from, depending on your liking and your needs.

First off, you can use events. Simply put, you add an eventhandler to your presenter, and a setter method to the  viewinterface.
interface

type
   TMyPresenter = class
      procedure DoOnButtonClick(Sender: TObject);
   end;

   IMyView = interface
     procedure SetOnButtonClick(event: TNotifyEvent);
   end;

   TMyView = class(TForm, IMyView)
     procedure SetOnButtonClick(event: TNotifyEvent);
   end;

implementation

procedure TMyView.SetOnButtonClick(event: TNotifyEvent);
begin
   MyButton.OnClick:= event;
end;


That's it, your wiring is set up.

Another way is to pass the view a reference to the presenter and call the relevant methods of the presenter in the coresponding eventhandlers of the view. But this way we introduce some coupling between view and presenter, which ain't really bad, but I don't like it personally so I won't cover it here.

A third option is the use of an adapter class and anonymous functions, as introduced with Delphi 2010. For an explanation to anonymous functions look here.
this looks like this:
interface

type
  ICommandAdapter = interface
    procedure SetCaption(const Value: string);
    procedure SetCommandAction(const Value: T);
  end;
  
  IParamLessAdapter = interface(ICommandAdapter);

   TCommandAdapter = class(TBaseAdapter, IParamLessAdapter)
   private
     FInvokable: TProc;
   protected
     procedure DoOnClick(Sender: TObject);
   public
     constructor Create(AControl: TObject); override;
     procedure SetCaption(const Value: string);
     procedure SetCommandAction(const Value: TProc);
   end;

implementation

constructor TCommandAdapter.Create(AControl: TObject);
var m: TMethod;
begin
   inherited Create(AControl);
   if IsPublishedProp(FControl, 'OnClick') then begin
     m.Code:= self;
     m.Data:= MethodAddress('DoOnClick');
     SetMethodProp(FControl, 'OnClick', m);
   end;
end;

procedure TCommandAdapter.DoOnClick(Sender: TObject);
begin
    if assigned(FInvokable) then
      FInvokable; // <- executes the procedure
end;

procedure TCommandAdapter.SetCommandAction(const Value: TProc);
begin
   FInvokable:= Value;
end;

The advantages of this solution are the same as in my previous post, UI designer don't have to worry about any implementation other than creation of the correct adapter, and the presenter developer keeps full control. 
 By creating your own TCommandAdapter classes and thanks to anonymous functions, you can use parameterized functions with any number of parameters and thus create handlers for virtually any situation, and there all implemented with the same ease.


Donnerstag, 27. Oktober 2011

Send it by letter or eMail?

There are many ways to implement communication between view and model when using MVP.

  1. Following the SupervisingController path, the model communicates directly to the view using bindings of any kind created in the presenter. DSharp comes to my mind, or Delphi XE2 LiveBindings. This is convenient, but it's also harder to UnitTest.
  2. Going down the PassiveView road, there are again several approaches to setup the links between model and view. Because PassiveView is more loosly coupled via interfaces to the view, it provides a better testing ground. I'll explain these in the following.

One way is to implement getters/setters for each EditControl's Value property (e.g. TEdit.Text, TDateTimePicker.Date) in the UI, getters only for readonly properties (think of Username of a Login screen: we will never set a value for this one) and setters for those that will only be written to (TLabel etc.). This way is using least ressources and easy to implement, but requires more coding.
You need to implement any feature by hand, e.g. disableling controls, marking required fields with a special color, validation and such become methods on your ViewInterface so the presenter could call them.
IMyView = interface
  function GetName: string;
  procedure SetName(value: string);
  procedure MarkNameAsRequired;
  function GetBirthdate: TDateTime;
  procedure SetBirthDate(Value: TDateTime);
  procedure MarkBirthDateAsInvalid; // Birthdate cannot be in the future or before 100 years
  procedure SaveButtonEnabled(Value: boolean);
 ....
end;

This could be endlessly continued, but I'm sure you get the point. The UI designer is left to implement all this, and the presenter developer must rely on the designer to do his job well.

Another way is to use an adapter pattern, or rather a class implementing the adapter pattern. Such a class would be used as a mediator to communicate data and actions (thanks to Daniele Teti who gave the idea). It would have some basic logic in itself.
IMyStringAdapter = interface
  function GetValue: string;
  procedure SetValue(value: string);
  Procedure SetEnabled(value: boolean);
  procedure IsRequired(value: boolean);
  property Value: string read GetValue write SetValue;
 ....
end;

TMyStringAdapter = class(TInterfacedObject, IMyStringAdapter)
private
  FProp: string;
  function GetValue: string;
  procedure SetValue(value: string);
public
  constructor Create(Control: TObject; Prop: string);
  Procedure SetEnabled(value: boolean);
  procedure IsRequired(value: boolean);
  property Value: string read GetValue write SetValue;
  ....
end;


The implementing view would then create once an instance of TMyStringAdapter with the control it should be bound to and a property being passed in the constructor.
NameAdapter:= TStringAdapter.Create(NameEdit, 'Text');


That's all! UI guys have nothing more to be concerned about, and the developer needn't to worry about anything that eventually isn't properly implemented.

Of course, one might argue I could create some specialized controls or at least adapterclasses for special controls. But the way I use it the UI designer can still decide which controls he wants to use to display a certain value. The presenter developer has full control over what's happening within the view, whatever it might look like.

And, as you may have noticed, model and view remain unaware of each other. exchanging one or the other require allmost zero changes in code.




Mittwoch, 26. Oktober 2011

You better start with a model!

Currently, I'm working on a Model-View-Presenter framework for Delphi. Why? Primarily out of pure curiousity, but there is more. For in-depth information about this pattern I recommend to look here

Although Delphi's RAD VCL is a well grown framework itself, it lacks of what is called "separation of concerns". Developing with Delphi (or any other RAD tool) is mainly about throwing components onto a form and fill in the appropriate eventhandlers for business logic. That way your UI and your logic become tightly coupled, which is bad.
This is bad because it makes revising an application which has grown over years harder or, even worst, impossible. UnitTests are not easy to accomplish as well, and your application will likely have more bugs, which are harder to trap.

With MVP, an evolved version of MVC (Model-View-Controller), you get a well structured separation of concerns, and retain full control over what's happening, and when.
Of course, the buy isn't cheap: Delphi was designed absolutely different, so you have to do lots of handcrafted work. The result though is a rock solid application which is testable and extensible, and less error prone.
The implementation I'm working on is using the PassiveView approach.
PassiveView, other than the so called SupervisingController, gives you the best possible separation between the view and the presenter, the view becomes a dumb interface with nearly no code at all. This means that tests are run exclusively against the presenter (and the model).

Where should I start?
With Delphi, one normally starts developing a UI and afterwards or besides crafts the model (but mostly will stick to DB aware controls and Datasets). This may be a good thing for prototyping and small apps, but for a real business application this is just not suitable.
By first developing a business model based on the requirements given, then a presenter to serve the controlling and communication requirements and finally the interface for user interaction, your application becomes more secregated and maintainable. Some parts can be built once and then be used in different applications. Another plus is, you can concentrate on one matter a time and do that right!

Your application becomes rock solid!


implementing "interface public"

I finally decided it was about time to start blogging. So here it is, my first blog.
I'll post here random bits of my programming activity as a hobbyist, mainly delphi programming.