Jon
Jon

Reputation: 15200

Class design with N-tier architecture

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;
    } 
 } 

Thanks for any and all suggestions.

Upvotes: 0

Views: 625

Answers (2)

Mark Simpson
Mark Simpson

Reputation: 23365

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 :)

Upvotes: 1

rrejc
rrejc

Reputation: 2682

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

Upvotes: 0

Related Questions