11

Why would you use a Dependency Injection Framework when you can simple use the following pattern?

unit uSomeServiceIntf;

interface

type
  ISomeService = interface
    procedure SomeMethod;
  end;

var
  CreateSomeService: function: ISomeService;

implementation

end.

unit uSomeServiceImpl;

interface

type 
  TSomeService = class(TInterfacedObject, ISomeService)
    procedure DoSomething;
  end;

function CreateSomeService: ISomeService;

implementation 

function CreateSomeService: ISomeService;
begin
  Result := TSomeService.Create;
end;

procedure TSomeService.DoSomeThing;
begin
  ...
end;

end.

unit uInitializeSystem;

interface

procedure Initialze;

implementation

uses
  uSomeServiceIntf,
  uSomeServiceImpl;

procedure Initialze;
begin
  uSomeServiceIntf.CreateSomeService := uSomeServiceImpl.CreateSomeService;
end;

end.

I am trying to grasp the benefits of using a framework instead of doing this but so far I only see the benefits of this simple approach:

1) Parameterized constructors are easier to implement. E.g.: var CreateSomeOtherService: function(aValue: string);

2) Faster (no lookups necessary in a container)

3) Simplier

This is how I would use it:

unit uBusiness;
interface
[...]
implementation

uses 
  uSomeServiceIntf;
[...]
procedure TMyBusinessClass.DoSomething;
var
  someService: ISomeService;
begin
  someService := CreateSomeService;
  someService.SomeMethod;
end;

end.

What would be your reasoning to use a DI framework instead of this approach?

How this would look like using a DI framework?

As far as I know if you would use a DI framework than you would register the concrete class against the interface and then consumers of the system would ask an implementation for the given framework. So there would be a registering call:

DIFramework.Register(ISomeInterface, TSomeInterface)

and when you need an ISomeInterface implementation you can ask the DI framework for it:

var
  someInterface: ISomeInterface;
begin
  someInteface := DIFrameWork.Get(ISomeInterface) as ISomeInterface;

Now obviously if you do need to pass parameters to create an ISomeInterface the whole thing gets more complicated with the DIFramework (but simple with the approach described above).

menjaraz
  • 7,551
  • 4
  • 41
  • 81
RM.
  • 1,984
  • 19
  • 29
  • Not sure what you mean by "convenience"?. Influence? – Warren P May 10 '11 at 13:20
  • @Warren, maybe the OP wants to know the reasons to choose either the pattern exeplified or the DI container... – Fabricio Araujo May 10 '11 at 18:40
  • Could you also add a more concrete example of how you would use the given pattern? I am looking at adding some kind of DI framework to our project but if there is a simpler way I am all for it.. I don't quite follow your example though. – awmross May 11 '11 at 00:11
  • "OP wants to know the reasons to choose either the pattern exeplified or the DI container" - yes, that is what I would like to know – RM. May 11 '11 at 20:35
  • "Could you also add a more concrete example of how you would use the given pattern?" Updating original post – RM. May 11 '11 at 20:35

2 Answers2

7

In your case you have to know the name of the factory function ptr (var CreateSomeService) in advance, at design-time. Sure, the interface and the function ptr are coupled together in the same Delphi unit file, but that's just a Delphi relic, global var is not thread safe and not access-protected.

And what if you got an interface at runtime, as a result of some function or a read from a config file - you don't know what factory function to call to get the actual instance of an implementor.

DIFrameWork.Get(ISomeInterface) as ISomeInterface hides the factory function from you so you only need the interface, not both the interface and the factory function. If you would try to hide the factory function then you'd also have to hide the parameters. (and would end up with something much like that DI framework).

Boris B.
  • 4,933
  • 1
  • 28
  • 59
  • if the CreateSomeService function is a generic function of a factory class would that be appropriate? ie. TFactory.GetInstance: InterfaceType; – Martien de Jong Nov 22 '19 at 14:11
0

the DI factory helps when you need an interface that someone else made and instructed the IoC container to create, sometimes an external library will hide the implementation from you. If you are the one creating the interfaces as well as using the interfaces you should look at the factory pattern creating the object for you based on the scope of the item, with the consideration of it being scoped as a singleton or the same for all in a "transaction".

You could generate a static class for singletons like "settings" what about the database session involved with a transaction that is touching the state of several objects... not so funny then. You should consider the right solution for the "right problem".

Walter Verhoeven
  • 3,867
  • 27
  • 36