Search code examples
c#oopdesign-patternscode-organization

C# Class Library - Where is design flaw and How do i solve it


In a typical organization application i create, entities User,Projects,Company,Contacts exists. For the user class defined below i think i will hit with a circular dependency. How should i modify the class below to solve the problem.

User

  • Username

  • Company

  • Projects List<Projects>

Project

  • ProjectName

  • Resources List<Resource>

  • Project Head User

Resource

  • ResourceId

  • ProjectId

  • ReportingHead User

You must have already found the flaw but,as you see ReportingHead, ProjectLead is already User class this makes it query for information about projects for them ,which will result in another cycle to retrieve the users for their project.

Even though resource is associated with project i will have to add a property projectId( First it was of type project) because i had a IResourceRepository to create resource for a project which would return a instance of Resource. How should the class be designed now so that it makes sense?


Solution

  • You could spend some time reading on aggregates and aggregate roots.

    What's an Aggregate Root?

    Decide one of your entities as a root and make a try and see if it fits your scenarios. I give you an example. This is very hard without knowing your scenarios though so see it as a example:

    I go for Companyas aggregate root.

    Company
      Name:string
      Projects:IList<Project>
    
    Project
      ProjectName:string
      Resources:IList<Resource>
      Projecthead:Employee
    
    Resource
      Employee:Employee
      (ResourceType probably)
    
    Employee
      Name
    

    (Ids are left out but will probably be in some baseclass if you want to DB Persist)

    Now you must make sure that you only access this Aggregate-root through the root Company. This is about isolation and it feels pretty weird that you cannot do a method like user.GetAllMyProjects() anymore but that will make it easier for you later on. Instead you can make a method like project.HasGivenUserAccess(User user). Thats probably enough but it depends on your scenarios.

    Feel free to attack this design with some scenario that you don´t think it handles and I will edit my post.