When it comes to layered applications with modern ORMs, I'm often unsure of how the specific classes should be created to adhere to so-called "best practices" while also paying attention to performance requirements.
Consider that you may have any number of the following types of objects in an application:
Domain Entities - these are rich classes that contain business logic (right?) and, depending on the ORM capabilities, may directly relate to the persistence design.
DTOs - these are simpler classes that strip business logic in order to pass data around to internal and external clients. Sometimes these are flattened, but not always.
View Models - these are similar to DTOs in that they're simpler and devoid of business logic, but they are usually pretty flat and often contain additional bits that relate to the UI they're serving.
The challenge I have is that in some cases the mapping of domain entities or any persistence-oriented class to a simpler entity like a DTO or ViewModel prevents you from making important performance optimizations.
For Example:
Let's say I have some domain entities that look like this:
public class Event
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime EventDate { get; set; }
// These would be reference types in most ORMs
// Pretend in the setter I have logic to ensure the headliner =/= the opener
public Band Headliner { get; set; }
public Band Opener { get; set; }
}
public class Band
{
public int Id { get; set; }
public string Name { get; set; }
public Genre Genre { get; set; }
}
In the real world these might be much more complicated, with various business logic, maybe some validation calls, etc.
If I'm exposing a public API, my DTO might look very much like this example, sans any business logic.
If I also have, say, an MVC web app I want to show a list of events on, I might want a view model that would look something like this:
public class EventViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime EventDate { get; set; }
public int HeadlinerId { get; set; }
public string HeadlinerName { get; set; }
public int OpenerId { get; set; }
public string OpenerName { get; set; }
}
Often, people just pull a full domain entity with references, then use a mapping utility to hydrate the view model.
However, let's say I have tens of thousands of records. Now the ORM is probably creating a storm of queries to populate the full reference objects (which may be much more complicated than this example, with their own references). It doesn't take long for performance to start to seriously suffer.
What's the question?
I know I'm not the only one to run into this issue, so I'm curious to know how people maintain a layered application while still accounting for the need to maintain performance while generating multiple objects that represent the same underlying domain information.
It doesn't feel right to have two Event
-ish objects representing the same persisted data, but at the same time it doesn't seem like the persistence layer should know about DTOs or view models, otherwise what's the point of striving for separation?
So how do you solve this? Does persistence know about strict, detailed representations of domain entities as well as lighter-weight depictions of the data in those entities? Are those lighter-weight depictions DTOs or some domain entity lite?