Wednesday, November 16, 2022

Escape the Button-Click development. Part I

Over decades one major selling point for Delphi was the easy development pattern of...
Place a button on the form, click it, and put the source inside the auto-created onClick procedure.

If you have never programmed like this throw the first stone.

Is it bad?

Who am I to criticize generations of developers who have created countless products and built their businesses this way?

If you do not want to create unit tests - this way of development is probably not a problem. Perhaps your project was growing over time, I bet there was a point in time when you recognized that your source code reaches a state where it was barely maintainable. You're afraid to change something because there's a big possibility that something else will break with that change. Am I right?

I also bet you have heard about unit testing, but you were unable to adapt these simple unit test examples to your project and that's why you don't "believe" in unit testing at all...

Still not interested in unit testing?
You don't want to refactor a single line of code in your project?

ok, in this case, you can stop reading... Have a nice day.

Since you're still reading on...

Part I


Let's talk about:

- Dependency Injection
- Composition (Root)

I do not talk about MVVM  - this time -, because converting a legacy project to MVVM is not an easy task by changing a few lines of code.

So what can we do to make a first and easy step? Perhaps your First idea is to separate code from your forms... Also not so easy, because the code is full of links into form components and I bet you hold all your data in visual components. Especially if you don't use DB or other data-aware components on your form.

So lets start simple:

Take one form and create a new unit with a comparing name... Like customers.pas/dfm -> customers.handler.pas. You can call it customers.controller.pas or even customers.viewmodel.pas.

For every onClick, onDBLClick and so on you create a procedure in the new unit. As we are not in the strict MVVM envirement this time you can reference the form instance in the new unit. After some copy and paste you can delete some uses in your form unit. (This was the stupid part)

Your application should work the same ways as before.

Next step is to create a class in your new unit an put all your procedures into this class. (of course you can skip the first step an create the class directly). Now we need "somebody" to create and hold this class.

Your form could do this job or you create a Unit Compositon.pas where you put all your form and viewmodel creation.

Then you only need to link this unit to create every other unit.
Like TCompositon.CustomerView.ShowModal.

Type
  TComposition = Class abstract
    public
      Class function CustomerView : TForm;
  end;

Class function TComposition.CustomerView : TForm;
begin
  Result := TCustomerView.Create(Application);
  Result.ViewModel := TCustomerViewModel.Create;
end;

If you need any business logic in your Customer.ViewModel you could also use a dependency injection for this or you use a global service-locator...

But this part we will see in part two.

Have a nice day.