DDD "View Objects"?
Given an application that involves, say, Companies, I might have a Company class. I will have a data access layer that populates a List &l开发者_运维问答t;Company>. However, there will be times (such as displaying a search result) where I only need to display the Company name, telephone and postcode properties, and it seems to me that populating the entire Company object with all its properties seems wasteful.
What would be the right way to go about this in terms of a DDD design? Would I create View specific classes, such as a CompanySearchResult object which only exposes the properties I'm interested in displaying?
That sounds like a reasonable approach to me.
Later on, if the customer comes to you asking for your SearchResult
to display something unrelated to the Company
model - something crazy like the number of nearby ice cream shops you'll have a much easier time appending this to your CompanySearchResult
than your domain object.
This is what is typically known as a "view model" or a Data Transfer Object. You may not want your view to have access to the entire data tree exposed by your domain model. Especially if exposing your domain model means that your view will have to dig deep into your object graph to pull the data it needs, a View Model can make alot of sense to simplify working with the model objects. In your case, if you are simply pulling direct properties off of the model object, it would make sense if you want to hide the extraneous data not needed by the rest of your domain model.
The approach you suggest can quickly increase the number of DAO:s you need to create and become a maintenance nightmare. The approach that several ORMs take is to proxy the data access, so your data access layer will return a list of interfaces, and the database call will be postponed until you invoke the data accessor, for instance
list.getCompany(1).getName()
. This is call lazy loading. You will still need to make a trade off between making many small or fewer big queries. This type of tasks is one of the strengths of ORMs, you can usually ask your ORM to prefetch parts of the object graph which you think will be used, and leave out other parts.
I use a crumble of the entity attributes. For example:
// interface for "ID" attribute of Company entity
public interface ICompany_ID {
Guid CompanyID{get;set;}
}
// interface for "Name" attribute of Company entity
public interace ICompany_Name {
string Name{get;set;}
}
// interface for "Logo" attribute of Company entity
public interface ICompany_Logo {
byte[] Logo{get;set;}
}
// interface for all attributes of Company entity
public interface ICompany : ICompany_ID, ICompany_Name, ICompany_Logo { }
// base class for classes based on Company entity
public abstract class CompanyBase : ICompany_ID {
// implementation of ICompany_ID interface
}
// class for all attributes of Company entity
public class Company : ICompany {
// implementation of ICompany interface (all attributes)
}
// class for Company name lookup
public class CompanyNameLookup : CompanyBase, ICompany_Name {
// implementation of ICompany_Name interfade
}
This crumble allow me to work with different attributes of different entities and all is type-safe. however, your data-layer must support this scenario.
The next way is dynamic creation of lookup classes, but it is much more complex. On the other side, it is much more flexible.
EDIT: Then the selection can be for example:
var companies = (from c in db.Table<ICompany>()
order by c.Name
select new CompanyNameLookup { ID = c.ID, Name = c.Name }
).ToList();
or for danymicly created types:
var companies = (from c in db.Table<ICompany>()
order by c.Name
select DynamicTypeFactory.New<ICompany_ID>( c.Id ).And<ICompany_Name>( c.Name ).Create()
).ToList();
The DynamicTypeFactory
is class with static method New
and fluent interface for danymic creation classes at run-time.
精彩评论