tags:

views:

264

answers:

2

Hi all,

This question follows on very closely to one I asked earlier but I do not think they are the same thing so thought it was sensible to split them up (which is a little ironic when you hear the question).

Previous question

I have a web application that was split into two projects:

1) The ASP.NET site 2) DLL that contained the busines objects, logic layer methods and DAL methods. They where split into different namespaces but all within the same DLL.

The more I looked at it and extended the development the more I realized I was very much going down the wrong road. I wanted to split them up into separate DLL's so that I could have a clear separation of duties.

Once I had the code in different DLL's I realized that a lot of classes called each other. For example when a List of Client objects were created in the DAL it would also call the companyDAL.cs and get a list of Companies that the Clients belonged to. So I now had two classes that directly referenced each other. This seems like a rather bad thing! It smelt bad but I carried on and tried to separate things out where I could.

To that end I took all the objects out to interfaces and changed all references to them to the interface.

I was hoping to use some sort of DI (just learning about that at the moment) so for each object I created a constructor that took in a Factory for that DLL, (this factory would create a new instance of each object that the class might require). I also put a default constructor in that would call the DI constructor with a default Factory to ensure that there was always one factory used.

It all compiled so I gave it a spin and got a stackoverflow! This is were I fully realized that if I have two classes that require each other you can not instantiate without the other.

Factory
{
   IClient CreateNewIClient()
   {
         return new Client();
   }

   ICompany CreateNeIwCompany()
   {
          return new Company();
   }
}

Client
{
    private ICompany _company;

    public Client() : this (new Factory()) {}

    public Client(Factory factory)
    {
        _company = factory.CreateNewICompany();
    }

    public Client GetClientbyID(int id)
    {
       .... do stuff to get client from db
       ... got client object and companyid from db.
         client.Company = _company.GetCompanybyID(companyid);
        return client;
    }
}

 Company
 {
    private IClient _client;

    public Company() : this (new Factory()) {}

    public Company(Factory factory)
    {
        _client = factory.CreateNewIClient();
     }

    public Company GetCompanyWithAllClients(int companyid)
    {
         .... do stuff to get a company out and client ids
         .... for each client id found
          company.Clients.add(_client.GetClientByID(clientid));
          return company;
    } 
 }
  • Am I going about the DI thing all wrong, is it that factory idea ok?

  • How should I avoid the classes needed each other? The reason they are like that at the moment is to avoid repeated code. I am sure I could write cleaner SQL to get it all out in one go, or at least in a couple of queries in the same method, but I was trying to avoid repeating code in different places.

Thanks for any and all suggestions.

A: 

Maybe you could use some ORM tool for you DAL, like NHibernate or Linq to SQL? NHibernate will map your data into objects with bi-directional links (if you want).

Edit: typo

Cheers, Rok

rrejc
NHibernate is something I want to look at but I think it is important for me to understand how things should be put together before I use tools to automate any of it, otherwise I worry that I would be just hiding some of my problems
Jon
+1  A: 

This isn't so much an answer as a clarification of the problem. I think your factory is complicating things somewhat (in that you get a stack overflow exception versus not being able to compile at all).

The problem is a circular dependency. You cannot instantiate A without an instance of B, and you cannot instantiate an instance of B without an instance of A.

public class Company : ICompany
{
    private IClient _client;

    // OK so first build a client and pass it in
    public Company(IClient client)
    {
       _client = _client;
    }
}

public class Client : IClient
{
    private ICompany _company;

    // OK so first build a company and pass it in.  Oh.  I can't... :(
    public Client(ICompany company)
    {
        _company = company;
    }    
}

Misko has an article about this which may be of some use: http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

Basically: Your class design is the problem and it needs fixed. The factory is just confusing the issue :)

Mark Simpson
Mark, you have hit the nail on the head. Would your recommendation be to occasionally have some repetitious code, i.e. some of your sql statements may do a very similar thing? With regards to this situation in a business logic level and the Company Object needing a instance of a client object but only knowing the ID should it call the Client DAL level object?
Jon