Dependency Injection vs. DataPortal and Service Locators vs. Static Factory Methods

Dependency Injection vs. DataPortal and Service Locators vs. Static Factory Methods

Old forum URL: forums.lhotka.net/forums/t/4514.aspx


Bob Matthew posted on Tuesday, March 18, 2008

I’ve been doing a lot of reading lately regarding Inversion of Control (IoC), but more specifically, the Dependency Inversion Principle which essentially states that even though your object depends upon my object for help, it shouldn’t depend on my object directly, only the interface or abstraction of my class.  This allows my object to be swapped out easily without your object either knowing or caring.  The bottom line in all of this is to create loosely-coupled, easily-maintained software.

The crux of loose coupling is: How does your object get an instance of my object?  As I see it, we’ve got 3 possible solutions.

  1. Call my object’s static factory-create method, but this tightly couples your object to mine and we’re right back where we started.
  2. Create some sort of service locator that resolves a type/interface into an instance of my object, but that would completely bypass my static, factory-create method and the DataPortal_Create.
  3. Instantiate your object directly by calling the new constructor (which would normally be private) and having Windsor Castle or some other IoC framework inject the dependencies (either through the constructor or property setters), but how would this work when using the DataPortal?  The DataPortal just calls your object’s default, parameter-less constructor and doesn’t perform IoC injection.  The IoC framework would also call my object’s default, parameter-less constructor rather than my factory-create method. 

What about static methods at all?  It would appear that static methods, by their very nature at somewhat at odds with OOP.  With loosely-coupled designs, as many interactions as possible become purely interface-based.  Currently I abstract functionality shared by multiple classes to another class and often times I don’t have to make it an instance class to get the work done that I need, which introduces a nice, tightly-coupled dependency.

In the end, I’m having some difficulty reconciling some of these practices to a CSLA-centric view of the world.  Any advice or experience you guys having implementing any dependency injection or even service locator functionality would be greatly appreciated.

Rocky – anything new on the DataPortal_XYZ factory methods as per this post: http://forums.lhotka.net/forums/post/13044.aspx

Thanks

nermin replied on Tuesday, March 18, 2008

Hi Bob,

 

Most IoC frameworks support constructing objects through calling Factory Method, instead of calling a constructor ( which in csla case is generally private).

 

Check David Hayde’s post where he gives examples for Windsor and Spring.  StructureMap also supports it as well as MS Unity (I can get you examples for those frameworks as well):

 

http://codebetter.com/blogs/david.hayden/archive/2007/12/13/factory-method-support-in-castle-windsor-and-spring-net.aspx

 

 

From: Bob Matthew [mailto:cslanet@lhotka.net]
Sent: Tuesday, March 18, 2008 4:02 PM
To: Nermin Dibek
Subject: [CSLA .NET] Dependency Injection vs. DataPortal and Service Locators vs. Static Factory Methods

 

I???ve been doing a lot of reading lately regarding Inversion of Control (IoC), but more specifically, the Dependency Inversion Principle which essentially states that even though your object depends upon my object for help, it shouldn???t depend on my object directly, only the interface or abstraction of my class.  This allows my object to be swapped out easily without your object either knowing or caring.  The bottom line in all of this is to create loosely-coupled, easily-maintained software.

The crux of loose coupling is: How does your object get an instance of my object?  As I see it, we???ve got 3 possible solutions.

  1. Call my object???s static factory-create method, but this tightly couples your object to mine and we???re right back where we started.
  2. Create some sort of service locator that resolves a type/interface into an instance of my object, but that would completely bypass my static, factory-create method and the DataPortal_Create.
  3. Instantiate your object directly by calling the new constructor (which would normally be private) and having Windsor Castle or some other IoC framework inject the dependencies (either through the constructor or property setters), but how would this work when using the DataPortal?  The DataPortal just calls your object???s default, parameter-less constructor and doesn???t perform IoC injection.  The IoC framework would also call my object???s default, parameter-less constructor rather than my factory-create method. 

What about static methods at all?  It would appear that static methods, by their very nature at somewhat at odds with OOP.  With loosely-coupled designs, as many interactions as possible become purely interface-based.  Currently I abstract functionality shared by multiple classes to another class and often times I don???t have to make it an instance class to get the work done that I need, which introduces a nice, tightly-coupled dependency.

In the end, I???m having some difficulty reconciling some of these practices to a CSLA-centric view of the world.  Any advice or experience you guys having implementing any dependency injection or even service locator functionality would be greatly appreciated.

Rocky ??? anything new on the DataPortal_XYZ factory methods as per this post: http://forums.lhotka.net/forums/post/13044.aspx

Thanks



Bob Matthew replied on Tuesday, March 18, 2008

I would love to see any links you can get me for examples relating to StructureMap and Unity.

Thanks!

nermin replied on Thursday, March 20, 2008

Bob Matthew:

I would love to see any links you can get me for examples relating to StructureMap and Unity.

Thanks!

Sorry it took me a while to digg this out.  From Jeremy himself, this is the Factory Method example for upcomming StructureMap 2.5.  Lets say you have a csla object Project that has a static factory method Project.CreateProject().  Then to register it with the StructureMap you would do following: 

StructureMapConfiguration.BuildInstancesOf<Project>.TheDefaultIs(

	ConstructedBy<Project>( () => Project.CreateNew() )

);

Obviosly if you are not using .Net 3.5 you can simply replace the labmbda expression with an anonymous delegate that calls  the factory method.

Since this is not officially released yet you would have to get the latest StructureMap code from subversion repository.

http://structuremap.sourceforge.net/Default.htm

Nermin

nermin replied on Thursday, March 20, 2008

By the way Jeremy already has a blog post about this:

http://codebetter.com/blogs/jeremy.miller/archive/2008/03/20/if-you-need-something-in-structuremap-but-you-can-t-build-it-with-new.aspx

Things happen fast in Open Source world!

nermin:

Sorry it took me a while to digg this out.  From Jeremy himself, this is the Factory Method example for upcomming StructureMap 2.5.  Lets say you have a csla object Project that has a static factory method Project.CreateProject().  Then to register it with the StructureMap you would do following: 

StructureMapConfiguration.BuildInstancesOf<Project>.TheDefaultIs(

	ConstructedBy<Project>( () => Project.CreateNew() )

);

Obviosly if you are not using .Net 3.5 you can simply replace the labmbda expression with an anonymous delegate that calls  the factory method.

Since this is not officially released yet you would have to get the latest StructureMap code from subversion repository.

http://structuremap.sourceforge.net/Default.htm

Nermin

 

Boris replied on Wednesday, March 26, 2008

Got the latest StructureMap bits from SourceForge (should be 2.5) and tried it...
All I'm getting is: "The name 'ConstructedBy' does not exist in the current context"  

Something is still fishy with the Factory Methods.

nermin replied on Wednesday, March 26, 2008

Would you mind posting the code for the registration of the object being constructed by the StructurMap?

 

Nermin

Boris replied on Wednesday, March 26, 2008

No problem...

I. For a class with a default Ctor everything is kosher:


   public class Patient {}

 

    [TestMethod]

    public void PatientTest()

    {

        // I don't want to use the StructureMap.config file

        StructureMapConfiguration.UseDefaultStructureMapConfigFile = false;

 

        StructureMapConfiguration.BuildInstancesOf<Patient>()

            .TheDefaultIsConcreteType<Patient>();

 

        Patient patient = ObjectFactory.GetInstance<Patient>();

    }

 

2. For a class with no default Ctor, (CSLA BO) all I’m getting is: “That CunstructorBy does not exist in the current context”

 

public class CslaPatient

{

    // private ctor

    private CslaPatient() { }

 

    public static CslaPatient NewCslaPatient()

    {

        return new CslaPatient();

    }

}

 

    [TestMethod]

    public void CslaPatientTest()

    {

        StructureMapConfiguration.UseDefaultStructureMapConfigFile = false;

 

        StructureMapConfiguration.BuildInstancesOf<CslaPatient>

            .TheDefaultIs(ConstructedBy<CslaPatient>(() => CslaPatient.NewCslaPatient()));

    }

 
I’ve tried specifying the PluginType and the PluggedType in the StrucureMap.config and included that – didn’t help either…

 I guess, I’m missing something or have to do some more reading…

 I have to say though, StructureMap + Rhino is really something good!

nermin replied on Wednesday, March 26, 2008

Borris,

I have built a quick test around ProjectTracker's Project object.  Following works:

[TestMethod]
public void TestMethod1()
{
 StructureMapConfiguration.UseDefaultStructureMapConfigFile = false;


 StructureMapConfiguration.BuildInstancesOf<Project>().TheDefaultIs(
  new ConstructorExpression<Project>(delegate { return Project.NewProject();})
 );

 Project project = ObjectFactory.GetInstance<Project>();
 Assert.IsNotNull(project);
}

You will notice I am not using ConstructBy, but rather just build the new ConstructorExpression.  Little bit less fluent but works.  I think that there is work in progress on this feature, and untill Jeremy stamps 2.5 for release, we will still have a little issue here and there.

I must say that my test above was originally failing:

Test method TestProjectTracker.UnitTest1.TestMethod1 threw exception:  System.Security.SecurityException: User not authorized to add a project.

After commenting out the authorization rule in CanAddProject() and just setting it to return true test passed.  (I can not set my domain account to a "ProjectManager" role, which is what the auth rule was about).  Therefore it appears to me that DI in this case works.

Please let me know if you have any questions.

 

Nermin

Boris replied on Wednesday, March 26, 2008

Nermin,

I was just going to try something very similar.
I figured Jeremy is probably still working on that, and the API is not finalized...

All I can say is: Thank you very much!!
It works, and we have the best of both worlds ;)

It's nice to be here...

RockfordLhotka replied on Wednesday, March 19, 2008

Bob Matthew:

Rocky – anything new on the DataPortal_XYZ factory methods as per this post: http://forums.lhotka.net/forums/post/13044.aspx

That turned out to be a lot harder than I'd hoped, and the result (to me) wasn't compelling - especially given the complexity introduced by the change.

The last thing I want is to have CSLA end up as complex as many pattern-happy frameworks seem to do. That flies in the face of my primary goal, which is to make it easier to write OO business layers. Patterns are great, but not if their negative consequences outweigh their positive consequences.

I may yet introduce some extra extensibility points in the data portal (on the server it is just a chain of responsibility after all). But my original thought of allowing wholesale replacement of parts of the process was just not a good idea. Mostly because I'd end up supporting cases where people didn't understand the various dependencies in the chain and thus created a mess. Not useful to anyone.

What is more interesting to me is the use of a separate DAL, and the use of a factory model (or locator or whatever you want) to load/invoke that DAL. And that works with the existing data portal model just fine.

RockfordLhotka replied on Saturday, April 12, 2008

I think it is important to only use a design pattern where the pattern provides more value than it does cost. Patterns always have a "consequences" section in their description, where good and bad consequences are listed. A pattern should only be used if the goodness outweights the badness.

Dependency injection is powerful and enables some goodness. It is also often complex and thus introduces a lot of badness.

The data portal is designed for simplicity. It is designed to provide a very abstract technique for moving objects between client and server (if there is a server).

I find it hard to envision a scenario where someone would want to replace the data portal itself - especially for testing, when most bugs occur because people do something that violates one of the data portal's rules. You want to go through the data portal or you'll miss the most important bugs in your tests!

What people really want to do for testing is to transparently replace their DAL.

Months ago I ripped the data portal apart and started to rewrite it to open it up. The further into that process I got, the more I realized what a nightmare I was creating. If people can do wholesale replacement of the data portal they can totally break most/all of CSLA's features. And (in theory) I'd have to support people who did such a silly thing. Not gonna happen!

Even a simpler scenario, like allowing replacement of SimpleDataPortal and ChildDataPortal seems iffy to me. Easy for me to do, but the consequences are huge!

Those two objects implement a sequence of events that MUST HAPPEN for CSLA to work. If you look through the (really quite simple) code in SimpleDataPortal you see a sequence of steps. Every one of those steps MUST HAPPEN. Failure to perform a step, or performing a step out of sequence, introduces a bug that cascades through the entire framework's operation.

Take Create():

  1. Create the object
  2. Tell the object the data portal is about to invoke it
  3. Mark it as new
  4. Invoke the object's DP_Create()
  5. Tell the object the data portal is done with it
  6. Put the resulting object into a DataPortalResult response message
  7. Return the DataPortalResult to the caller

This is the simplest of the operations (and I'm ignoring exception handling, which must be done in a very specific manner).

If I allowed replacement of SimpleDataPortal (and ChildDataPortal of course), you could alter the overall flow somewhat, but you MUST end up having done steps 1, 3, 4, 6 and 7. Only 2 and 5 are really negotiable - and skipping them could easily break existing business object code.

It gets worse with Fetch() and very nasty with Update().

But, if I did this, I suppose you could decide to entirely ignore the current data portal model and devise a completely different scheme for creating/loading your object with data - as long as the result is marked new, and you do steps 6-7.

Maybe something like:

  1. Use a DI framework to create an instance of the object and provide it with the DAL reference (and criteria) so it can load itself
  2. Mark the object as new (though this may be too late - the reason I mark as new where I do is because of user feedback that it needed to be early in the process)
  3. Put the resulting object into a DataPortalResult response message
  4. Return the DataPortalResult to the caller

The pre- and post-processing events would be up to the DI framework or something, as would any error handling event. You'd still need to wrap this whole thing in the same error handling code from SimpleDataPortal of course.

As I said, I went down this whole road. And then it occurred to me that I could get the same flexibility by using a provider model to get at my DAL - and that approach is a lot simpler, so I abandoned this idea.

I have yet to be convinced that the DI pattern provides a better, simpler or cleaner result here than using a provider model for the DAL. If someone establishes how that would be the case then I would consider making this change to the data portal. In the meantime, my recommendation is to use a provider model to load your DAL - which allows mocking the DAL in a very simple and clean manner.

And interestingly enough, your DAL itself needs to be designed pretty much the same to support DI or the provider model, because your data access methods (either way) need to be able to interact interchaneably with the real or mock DAL. Remember that your DAL can't load your object's properties, it must load your object's fields - and to avoid breaking encapsulation this means your object must load its own fields. This is true regardless of what other patterns we apply around this process.

Bob Matthew replied on Saturday, April 12, 2008

Rocky,

We seem to be “missing” each other on the main focus of our posts.  Perhaps I should better explain my intentions and motivations behind my most posts on the subject of dependency injection.  In addition, I shall attempt to more fully define my understanding of each concept such that any confusion may be avoided.

One of my primary goals is to minimize coupling (references to concrete types) between components in my code.  I fully understand that some degree of coupling is necessary, for example, I’m tightly coupled to the System.String class whenever I work with a string.  In many ways this type of coupling may not be undesirable, provided that I’m comfortable being bound to any changes that could be made to the System.String class.

The “issue” of coupling to the CSLA is really a non-issue.  Just as I am comfortable being coupled to System.String and many other .NET base classes, I am also comfortable doing so with the CSLA and more particularly the DataPortal.  I’m not interested in re-writing the DataPortal. Rocky, you’ve done a tremendous job with the framework.  It’s very well documented, well supported and the advantages it brings to increasing object maintainability and portability are indispensable.

Now, with all of that addressed I would like to elaborate upon what I see as a limitation of, not the CSLA, but mobile objects in general because of their very nature as mobile objects; in short, a caveat of working in a client/server environment.

Two of the most common methods for avoiding tight coupling to concrete types and instead relying on contract definitions (interfaces) are known as “service locators” and “dependency injection”.

The service locator pattern, commonly and perhaps mistakenly referred to as an object broker, is where a single static, global object provides access to new objects.  Whenever we need a new object, we go to the broker and ask for a new object that implements the desired interface.  Any object is free to go to the broker/locater to ask for a concrete instance of any interface.

Dependency injection on the other hand, while it may share similarities with a service locator, namely having a single global, static “broker” object, has one significant difference: Each component or group of classes organized for a single purpose does not reference the broker or even know of the broker’s existence.  The component, in order to receive references to its dependencies (such as a logger, database connection, etc.), has to have them injected during construction.

For further review of some of the advantages of dependency injection over service locators, please refer to the following article: http://ubik.com.au/article/named/service_locator_vs_dependency_injection

The “gotcha” that I’ve come across when attempting to reconcile dependency injection and mobile objects is that many types of dependencies a CSLA-derived class (a BusinessBase object) may need are not serializable and thus cannot be injected and shuttled back and forth across the wire during roundtrips to the DataPortal.

This means, as far as I can determine, that the only other possibility which can be used to obtain dependent references, other than direct coupling with a concrete type, is to use a service locator.

In conclusion, I just wanted others to be aware of this “issue” when attempting to implement a dependency injection pattern with a mobile object – you must ensure that any and all dependencies are fully serializable and you must also be aware of the additional payload those dependencies carry when transferring them back and forth across the wire.  These complications can be avoided when using a service locator, meaning a direct reference to the global, static broker object from within the component, and not serializing the dependencies in question.

As for our approach used by my team, we have gone with a hybrid model.  We use dependency injection for our non-BusinessBase objects which frees them of any knowledge of the broker, whereas the BusinessBase-based classes are free to access the object broker to obtain their dependencies.

 

Boris replied on Saturday, April 12, 2008

Rocky,

I appreciate your time and effort on this.
I'm always able to learn something new from you -- Thank you!

 

We are building a pretty complicated medical system using CSLA.

The expectation is we will have at least couple of thousands unit tests…
 
* So far in my case the existence of DI is mostly affecting how I write my unit tests.

BTW: I was thought to distinguish between unit and integrating tests.

-         Unit tests shall be atomic and shall not cross layers;

-         Integration tests usually exercise the whole vertical slice UI to Database

 

My goal was/is to cover my public methods with atomic unit tests!

In general, the more atomic the tests are the better; the fewer tests will break if a bug is introduced.

I understand that going through the Data Portal is very important and it should be tested! (And it this in our integration tests, actually there are cases where integration tests are the only option)

 

So, using DI + Some Mocking Framework to mock the DAL in order to stay atomic and for speed purposes (Unit tests are way faster than Integration and they are executed more often) was perceived to be a good thing in our team…

 

**

 

The second thing with DI is: It can be used to introduce new behavior on the Client or in the Server. All I have to do is update a config file and put e new functionality in newly added assembly…

 

***

 

I never thought a change in the Data Portal is needed to support DI in CSLA.

CSLA is just fine.

I can use DI on the server or in the client, why would I want to break the Data Portal?

 



Boris replied on Sunday, April 13, 2008

Here is one approach…

 

  1. Create a container/root BO class.

 

  1. Create a child object IMyChildObject, for which you want to use DI

(It would be cool if the implementations of the IMyChildObject are also BOs)

 

  1. Use StructureMap to inject into that IMyChildObject ref whatever you want, as long as it is IMyChildObject (the implementations may come from a different assemblies)

 

The injection could take place in the DataPortal_Create or in the Properties..

 

Something like:

//In the properties _myChildObject is declared as IMyChildObject

 

 

[RunLocal()]

protected override void DataPortal_Create()

{

  _myChildObject = StructureMap.ObjectFactory.GetInstance<IMyChildObject>();

  //OR use the NamedInstance:

  //_myChildObject = StructureMap.ObjectFactory.GetNamedInstance<IMyChildObject>("Implementaion1");

}

 

(In 3.5 LoadProperty will be used…)

 

(You need to be familiar with StructureMap and create an appropriate StructureMap.config file)

 

Here is a goog start with StructureMap:

http://frickinsweet.com/ryanlanciaux.com/post/Very-Quick-and-Simple-Dependency-Injection-with-StructureMap.aspx

 

http://monkeys.codebetter.com/blogs/karlseguin/archive/2007/12/10/foundations-of-programming-pt-4-dependency-injection.aspx

 

In theory the DI could take place on both sides: Client & Server…or on either of those.

It all depends on what is it exactly we want to accomplish…

Copyright (c) Marimer LLC