1

I have a Business layer (BL) and a Data layer (DL). I have an object o with a child objects collection of Type C. I would like to provide a semantics like the following o.Children.Add("info"). In the BL I would like to have a static CLASS that all of business layer classes uses to get a reference to the current datalayer instance. Is there any issue with that or must I use the factory pattern to limit creation to A class in the BL that knows the DL instance.


Let me Clarify. In the past when defining DL I create an interface IDL that the DL implements. The only objects I allow to be created from my BL are the factories which in their constructors take A reference to the IDL

IE

   IDL idlRef = new DataLayer();  
   IBlFactory iFac = new BLFactory(IDL);
   IBLa = IBlFactory.Geta(...);

As I have tried to work statics and singletons out of my system my factory creates all the objects and always passes the reference the the IDL to the new objects. Some on my team have complained about my copious use of interfaces and factories and would like to utilize concrete classes from the BL directly.

So the issue is if you have a object which can be created IE a new object are you better severed by utilizing the factory. IE

IBLA oBLA = iFac.GetBLA();

or forcing the client to always passing the reference to the DL to new object. IE BLA oBLA = new BLA(idlRef);

or would testability really be harmed by having one static property in the BL.

Static IDL CurrentDL;

Allowing albeit with some breaking of encapsulation more succinct style Assuming that each BL object will know what the currentDL is.

rerun
  • 2,045
  • 12
  • 24

4 Answers4

6

This is a common scenario so I will try to answer it in a reusable way.

The issues with static classes are:

  1. they make testing difficult (due to their ability to hold state across tests)
  2. they cannot be swapped out with an isolated test-specific version
  3. they make it difficult to swap out the default implementation with a different one (note this is the same as #2).
  4. every call requires the class name

If you could provide an instance of - let's call it an EntityManager (most ORMs have this class) into the constructor, that would be best. Make sure to give it an interface and reference it in the business layer only through that interface.

The only difference between this and your static class would be that:

  • it is passed into the constructor of the business layer class(es)
  • it can be tested
  • your business layer class knows it only by the interface name (not the class name) so the data layer can be swapped out with a new one seamlessly (even at runtime) which is very powerful when you don't want to break old code

One thing I have learned more recently when running into code that "doesn't feel right": try TDD or read some guidelines on how to make your code more testable - it often points you in the right direction.

Graeme Wicksted
  • 609
  • 4
  • 6
1

I'd recommend staying away from static classes, I've been down that road myself and it makes everything harder both to test and to implement

Homde
  • 11,104
  • 3
  • 40
  • 68
1

It sounds like you are taking a dependency on your Data Layer in your Business Layer, but do not want that direct dependency. If this is the case, create a separate 'Core' layer that contains an interface definition for your Data Layer (IDataLayer) and apply it to your current Data Layer. You may end up with code that (in C#.Net) looks like:

public class BusinessLayer {

  private IDataLayer _DataLayer;

  public BusinessLayer(IDataLayer dataLayer) { 
      _DataLayer = dataLayer;
  }

}

In this way, you can inject the proper Data Layer definition into your Business Layer. Typically, this occurs through the constructor using a technique called 'Constructor Injection'

For more on dependency injection: http://en.wikipedia.org/wiki/Dependency_injection

Dependency injection is now accomplished through the use of a Dependency Injection tool or an Inversion of Control (IoC) container. A list of containers for .Net can be found at: http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx

Jeff Fritz
  • 499
  • 4
  • 8
0

It seems (although your very abstract) that your trying to implement some type of data layer ORM. Depending on your environment I would just use an existing implementation like NHibernate for java, django for python or active record for ruby, etc. Designing an ORM is not a simple act in software design - why invent the wheel?

eggie5
  • 159
  • 1
  • 3