Saturday, September 13, 2014

Spring4D 1.1 release and roadmap

Today I am happy to officially announce the release of version 1.1. And also it is the 5th anniversary of Spring4D (at least according to the commit history).

Thanks Paul who started the project and all the others that made Spring4D what it is today:
A modern RTL extension and the most powerful dependency injection container written in Delphi that can compete with those in other languages easily.

For the 1.1 release we have fixed many bugs, refactored and cleaned up the internals of the container and implemented many neat new things. And of course added support for Delphi XE7.

After 5 years and finally getting past version 1.0 we felt it was time to get some official logo for Spring4D to be recognizable and here it is - thanks to Chris Wagner for his help!


New feature - automatic factories

There is one particular feature I am very proud of - and thanks to Philipp Schäfer who had brought me to this idea: automatic factories.

When you are dealing with dependency injection you often have the case that you cannot create everything upfront. Mostly because some information is missing that the user enters during the use of the application. That is when factories and lazy initialization come into play. You obviously created factory classes in the past and registered them into the container so they could be injected into other classes that used them.

You don't have to do that anymore because the container now can create these factories for you!

Let's look at some example:

type
  IMyService = interface
    ['{9C0B02FE-5A69-4409-ACA6-C702CE4D9B44}']
    procedure DoSomething(const msg: string);
  end;

  IDialogService = interface
    ['{A65920CC-E729-4E3B-BD3C-20A9BBDFE753}']
    procedure ShowDialog;
  end;

  TMyService = class(TInterfacedObject, IMyService)
  private
    fAnotherServiceFactory: IFactory<string, IDialogService>;
  public
    constructor Create(const anotherServiceFactory: IFactory<string, IDialogService>);
    procedure DoSomething(const msg: string);
  end;

  TDialogService = class(TInterfacedObject, IDialogService)
  private
    fMsg: string;
  public
    constructor Create(const msg: string);
    procedure ShowDialog;
  end;

constructor TMyService.Create(
  const anotherServiceFactory: IFactory<string, IDialogService>);
begin
  fAnotherServiceFactory := anotherServiceFactory;
end;

procedure TMyService.DoSomething(const msg: string);
begin
  fAnotherServiceFactory(msg).ShowDialog;
end;

constructor TDialogService.Create(const msg: string);
begin
  fMsg := msg;
end;

procedure TDialogService.ShowDialog;
begin
  ShowMessage(fMsg);
end;

Some pretty straightforward code with only one thing that might look unfamilar: IFactory is a new type that can be resolved by the container automatically and comes from the unit Spring.Container.Common and is similar to TFunc but with $M+ which is required for the container to automatically resolve this type using TVirtualInterface.

So how does the registration code look like?

  container.RegisterType<TMyService>;
  container.RegisterType<TDialogService>;
  container.RegisterType<IFactory<string, IDialogService>>.AsFactory;
  container.Build;

  myService := container.Resolve<IMyService>;
  myService.DoSomething('Spring4D rocks!');

The new method AsFactory tells the container to treat this interface or delegate type (if it has method typeinfo on) as factory and it automatically creates the implementation. Any arguments passed are then passed to the container as arguments for the resolution process. That means in this example the string getting passed to the DoSomething method and into the factory is then passed to the container to be injected to the constructor of TDialogService.

What's coming next?

There are several things we want to do in the next couple of months.
  • As you might have seen we have something new in development that is known to some as marshmallow: an ORM that Linas Naginionis contributed to Spring4D. He and Cesar Romero are new on the team and are currently working on the migration and integration into the library.
  • Honza has been working on a better logging solution that will be used internally by the container and can be used in your applications and will have several backends (for CodeSite, SmartInspect or for simple text or console logs). It also can be easily extended to your needs.
  • I have been working on an easy to use interception (AOP) library that can be integrated into the container or used as standalone to do some nice things - those of you attending the EKON 18 in November in cologne will probably see more of it shown by Nick and me.
Along with these new features we also want to write more documentation and how-to articles introducing you to all the features in Spring4D and show advanced dependency injection techniques.

We are eager for your feedback!

As always your feedback is welcome. Are you using Spring4D in your software? Please let us know! You have ideas how to improve the library or want to contribute? Don't hesitate to contact us.