Class Design – Reusing a Top-Level DTO as a Child in Another DTO

class-designcode-reusedtojson

What is the recommendation regarding re-using DTO's as a child in another DTO?

I'm using ASP.NET Web API (C#) and consuming the results with Angular 1.x (not sure if that really matters).

I have the following DTOs

class SiteDto {
 public int SiteId {get;set;}
 public string Name {get; set;}
 public DateTime CreatedDate {get;set;}
  ...
}

class SiteEventDto {
 // pk
 public int SiteEventId {get; set; }
 // fk
 public int SiteId {get; set;}
 public DateTime EventStartDate {get; set;}
 public DateTime EventEndDate {get; set;}
 ...
}

I want to return a list of SiteEvents with a site name (for example). Is there a recommendation for the link between SiteEvent and Site to get this parent information? For example, I see the following possibilities:

  1. Re-use existing DTO: Use the existing Site DTO as a property within the SiteEvent DTO (e.g. public SiteDto ParentSite { get; set; } )

    • Pros:
      • Code re-use
      • Scalable
    • Cons:
      • Potentially a lot of extra bloat (for web-based/json-based calls especially) due to unneeded properties and possibly additional parent hierarchies
  2. Create new parent DTO: Create a child-DTO specific to this task (e.g. class SiteEventSiteDto { … ) and reference that through a child property on SiteEventDto

    • Pros:
      • Reduce additional bloat from unused fields
    • Cons:
      • Minimal code re-use
  3. Flatten class structure: Flatten the class structure to simply include a "SiteName" property in the SiteEventDto (e.g. public string SiteName { get; set; } )

    • Pros:
      • Reduce additional bloat (even more)
    • Cons:
      • Minimal code re-use

It probably makes sense to look at each case individually and assess the following questions:

  • Do I foresee a need for additional properties off the parent object?
  • How difficult is it to add a new property in a flat structure?
  • How much bandwidth is the bloat going to really cost the user?

I guess my questions to the community are:

  • Is it common practice to re-use a DTO for more than one controller (scenario #1, above) or is that considered a bad practice for some reason? Or, does it make more sense to create a new child DTO or use a flat structure when possible?
  • And lastly, do my ramblings above seem like a good approach to this problem?

Best Answer

Re-use existing DTO, Create new parent DTO and Flatten class structure

Choosing between reusable code (sometimes it makes us feel like squaring the circle) or customization (sometimes it makes us feel like having a deja vu) is a matter of needs and preferences.

You already exposed pros and cons of each solution. Now, you have to balance them:

  • Those pros that suit better your needs.

  • Those cons that don't prevent you from meeting the requirements.

Assess and answer the following questions:

Do I foresee a need for additional properties of the parent object?

Providing additional properties (that might seem unnecessary at first glance) you could be saving calls to the server. Cutting down concurrency and saving device's resources is always welcome into any system.

How difficult is it to add a new property in a flat structure?

Depends on how hard is to retrieve the property:

  • Do we need to execute additional queries? How many? What kind of queries?
  • Do we need to make the actual query more complex? What sort of complexity are we introducing?
  • Do we have to call external services? ....

How much bandwidth is the bloat going to really cost the user?

  • How often are users going to ask for the complex DTO? (If it's requested just once during the "session". Is there any cost?)

  • Is it a requirement to make light resources?

  • Is important to use the less bandwidth possible?

  • Is there any sort of bandwidth consumption limitation?

Ok... Too much questions

All these kind of questions might lead to premature optimisation. Start by the simplest one. Apply KISS principle.

Finally...

And lastly, do my ramblings above seem like a good approach to this problem?

It's necessary to know the project and the requirements, in order to say which solution is advisable/good/best

So far, all 3 are legit and "good" if they solve the problem.