22

I am in the process of redesigning my current project to be more maintainable, and doing my best to follow good design practices. Currently I have a solution with a Silverlight component, ASP.Net host for said SL app that also contains a WCF RIA service, and a shared class library so both SL and the WCF service can share objects. Business logic is scattered all over the place, and all CRUD operations are hand coded inside my WCF services. So, I am creating a new structure for everything and will port this mess into the new format. In the process of doing this, I find that I am duplicating classes when I don't know if I should be.

My new structure is laid out as such:

Client:
Reporting.Silverlight = Silverlight Application. This will reference my DTO classes.
Reporting.Web = Holds my SL app and is the main entry point for people to get to it.

Business:
Reporting.Services = My WCF services live here. My SL app will make calls to this to do stuff, and these services will return DTO classes.
Reporting.Services.Contracts = Holds my interfaces for the WCF services, and contains my DTO classes with the DataContract decorators.
Reporting.Domain = Holds my domain objects and business logic

Data:
Reporting.Data.Contract = Holds my interfaces for repository & unit of work
Reporting.Data = Concrete implemention of repository/UoW. Entity Framework 5 context is defined here.
Reporting.Data.Models = Holds all my Entity objects so EF5 can do its thing with SQL.

I have 3 places where I have almost the exact same class, and to me it smells. Inside of Reporting.Services.Contracts I have a DTO that gets handed to the SL client. Here is one as an example:

[DataContract(Name = "ComputerDTO")]
public class ComputerDTO
{
    [DataMember(Name = "Hostname")]
    public string Hostname { get; set; }

    [DataMember(Name = "ServiceTag")]
    public string ServiceTag { get; set; }

  // ... lots more
}

I think the above DTO is fine, as it just a bunch of properties that get passed to the SL client. The vast majority of my DTO properties map to my Entity objects' properities 1:1 except for ID fields. Here is my Entity object that corresponds with the above DTO:

[Table("Inventory_Base")]
public class ComputerEntity
{
    // primary key
    [Key]
    public int AssetID { get; set; }

    // foreign keys
    public int? ClientID { get; set; }

    // these props are fine without custom mapping
    public string Hostname { get; set; }
    public string ServiceTag { get; set; }
    // ... plus a bunch more in addition to my navigation properties
}

I am using the code first approach with EF5. I'm still in the very beginning stages of my re-write, and so far I have the impression that business logic should NOT be inside my EF Entity. DTO's shouldn't have business logic either. That means it goes into my domain model, right? Well, that gives my 3rd almost identical class in Reporting.Domain

public class Computer
{
   public string Hostname { get; set; }
   public string ServiceTag { get; set; }
   // ... lots more, pretty much mirrors the DTO

   public string Method1(string param1)
   {
       // lots of methods and logic go in here
   }
}

Having 3 almost identical classes can't possibly be the right way to go about this, can it? Should I be putting all my business logic inside the EF entity, then projecting the result into a DTO that gets passed across the wire? If it is a good idea to cram all my domain/business logic inside the EF entity classes, structurally should I move that assembly to my business layer and outside my data layer, even though those objects are the ones that get saved to my database? Ideally I'm trying to keep any references to Entity Framework contained within my data projects and outside of my business projects. I have about 200 or so classes that I'm porting over and will comprise my domain, and I expect this thing to scale to a lot more functionality once I get this re-write done. Any insight on how to structure this thing and keep it DRY would be much appreciated.

In case it helps define what I'm trying to do any better, let me know if I should include my repository/unitofwork methodology that I am following.

Bill Sambrone
  • 4,334
  • 4
  • 48
  • 70
  • possible duplicate of [ORM Entities vs. Domain Entities under Entity Framework 6.0](http://stackoverflow.com/questions/18109547/orm-entities-vs-domain-entities-under-entity-framework-6-0) – Gert Arnold Sep 10 '13 at 21:00
  • Hi Gert - I liked your answer in that linked question and it clears up quite a bit for me. My understanding is that it's okay to use the Entity objects as domain objects if they're identical and it's practical. I do expect my later domain classes I add to be different that my entity objects, however. In that situation, would I still need to tripicate my classes between DTO/Domain/Entity-for-my-ORM? – Bill Sambrone Sep 10 '13 at 23:20
  • DTO/Domain/Entity solution aims to build sperate exclusive model for seperate concerns. Entity makes sense only when persistence infrastructure hampers you from building a refine domain model. if your domain is not that complex, you could use entity for domain model. So as DTO. – Yugang Zhou Sep 11 '13 at 01:04
  • @BillSambrone For parts of the domain, probably. Where the entity model structure hampers the programming of succinct business logic, dedicated domain classes must be created. These classes will have no direct counterpart in the entity model, so it's no triplication (or duplication) any more. _Mapping_ is a more appropriate term here. The same goes for DTOs. I often use DTOs rather than entities when a UI layer requires a flattened/aggregated data structure that has no match in the entity model. DTOs must also be used if you want to decouple the presentation layer from data/business logic. – Gert Arnold Sep 11 '13 at 07:12

1 Answers1

27

Having 3 almost identical classes can't possibly be the right way to go about this, can it?

IMO they aren't "3 almost identical classes", they don't serve the same purpose. They are rather multiple facets of the same domain notion, each one tailored for the needs of a specific layer.

It's the price to pay for modularity and clear separation of concerns. The more ports (as in Hexagonal Architecture's Ports & Adapters) you have, the more facets you'll need and the more mapping you'll have to do.

A good article on this : http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping/

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • That is a good read. My takeaway is that if I want to keep this thing layered, I really DO need to have my DTO classes, Domain classes, and Entity classes. They all appear similar, but all are "responsible" for different things. Do you have a recommendation for a good mapping framework that will reduce my hand mapping that I will need to do? – Bill Sambrone Sep 11 '13 at 14:46
  • 2
    I've only used AutoMapper (https://github.com/AutoMapper/AutoMapper) which works great for me – guillaume31 Sep 12 '13 at 07:24