Pergunta

I'm struggling to get a good architecture for my current project. It's my fist time designing a serious n-tiers app trying to use the best practices of software engineering (DI, Unit tests, etc...). My project is using the Onion architecture.

I have 4 layers

  1. The Core Layer : It's Holding my business objects. Here I have classes representing my business entities with their methods. Some of these objects have a reference to a Service Interface.

  2. The DAL (Data Access) Layer : It defines POCO objects and implements the Repository Interfaces defined in the Core Layer. In this Layer I thought that it was a good idea to design a big utility class whose role is to convert the POCOs objects from the DAL to Business Object from the Core.

  3. The Service Layer : It implements the Service Interfaces defined in the Core. The Role of this Layer is to provide access to the Repositories defined in the DAL. I primarly believed that this Layer was useless so I directly used the Repository Interfaces defines in my Core Layer. However after some weeks spent writing very long instanciation code - having constructors taking 5-6 IRepository parameters - I got the point of Service Layer.

  4. The presentation Layer. Nothing special to say here, except that I configure dependency injection in this Layer (I'm using Ninject ).

I've changed my architecture and rewrote my code at least 3 times because many time I saw that something was wrong with my code. (Things like long constructors with long parameter lists). Fortunately bit per bit I'm getting the point of the various coding pattern found in litterature.

However I've just come across a cyclical dependency with my DI and I'm seriously wondering if my DAL2Core Helper was a good idea...

Thanks to this helper I can write code such as :

        DAL.Point p = DAL2Core.PointConverter(point); // point is a Core Object
        context.Points.Add(p);
        context.SaveChanges();

Which reduces a little code redundancy. Then each of my repositories defined in the DAL have its own DAL2Core member:

private IDAL2CoreHelper DAL2Core;

And I inject it from the Repository constructor.

The DAL2Core class itself is a a bit messy... First of all, it has a property for every Repository, and every Processor (Service Layer). The reason of the presence of the Processors is that my Core Objects need that a Processor Dependency be injected. I've put some of the repositories and Processors referenced in my DAL2Core utility class below just to illustrate :

    [Inject]
    private Core.IUserRepository UserRepository{ get; set; }
    [Inject]
    private Core.IPointsRepository PointsRepository { get; set; }


...

    [Inject]
    private Core.IUserProcessor UserProcessor{ get; set; }
    [Inject]
    private Core.IPointsProcessor CoursProcessor { get; set; }

(Since the DAL2Core Helper, is required by the repositories, a constructor injection would cause cyclical dependencies)

And then this class has lot of simple methods such as :

public Core.User UserConverter(DAL.User u)
    {
        Core.User user = new Core.User(UserProcessor);   
        user.FirstName= u.FirstName;
        user.Name= u.Name;
        user.ID = u.ID;
        user.Phone= u.Phone;
        user.Email= u.Email;
        user.Birthday= u.Birthday;
        user.Photo = u.Photo;
        return user;
    }

This class is like 600 hundred lines. Thinking about it, I realize that I don't save much code because much of the time the DAL2Core Convertion code is only called from one place, so perhaps it would be better to leave this code in the repositories ? And - the biggest problem - since I decided to decouple this helper from my Repository Classes, cyclical depencies exception are thrown by Ninject.

What do you think about the design I tried, is it a good / common practice ? And how can I smartly and efficiently perform this DAL2Core convertion without code smells. I really look forward to solving this architecture issue, I've spent the last three weeks dealing with plumbing and architecture issues and not really advancing that project. I'm becoming very late. However I really want to produce a high quality code. I just want to avoid architectural solutions that look like overkills to me, with lot of Factories etc... But I admit that some times, this feeling juste come from a lack of understanding from me (Like for the Service Layer).

Thanks in advance for your help !

Foi útil?

Solução

What you are looking to use is AutoMapper , Value injecter or something similar for this purpose.

Essentially, it is a good practice to seperate data models between layers, to reduce coupling and increase testability. If you come up with a generic Mapper you will reduce code redundancy.

Hope this helps.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top