views:

208

answers:

4

Given an application that involves, say, Companies, I might have a Company class. I will have a data access layer that populates a List <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?

+4  A: 

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.

Kirschstein
I was thinking of something even more "crazy" such as having the Search Result as just one element in the display. I might also want a list of diary reminders in a grid and a current weather summary. Would I aggregate my CompanySearchResult, WeatherSummary and ReminderList in a MyComplexFormViewModel class specifically for that form or web page?
Michael
@Michael - In that scenario I would probably make a container view that held a CompanySearchResult, WeatherSummary and ReminderList
Kirschstein
@Kirschstein - is a "container view" the same or different to what I proposed with the MyComplexFormViewModel idea?
Michael
@Michael - What I gathered from what you were saying is that you're thinking of copying each attribute from Model A,B and C to your ComplexView. I would have a view that contained A, B and C instead.
Kirschstein
@Kirschstein - no, I was thinking that class ComplexView would have the following public properties: CompanySearchResult (being a collection of searchresult objects), WeatherSummary and DiaryReminderList (being a collection of DiaryReminder objects).
Michael
@Michael - Yes, I would do that. Sorry, I got a little bit confused it seems.
Kirschstein
@Kirschstein - probably the fault is mine in misuing the term "aggregate". I'm new to all this :o)
Michael
A: 

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.

TcKs
IMHO, this is just plain wrong.
Frederik Gheysels
@Frederik: Why do you think? I used this scenario in several succeeded business projects and it works prety good.
TcKs
I agree with Frederik tbh, it seems to be overly complicated for little gain.
Kirschstein
+3  A: 

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.

Matt Wrock
+1  A: 

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.

disown
Hmm. ORMs. Another avenue of exploration for me... Can you suggest a good starting point?
Michael
@Michael - There are tonnes of questions relating to .NET ORMs on stackoverflow, just do some browsing. NHibernate would usually come most recommended for big projects, although it has a steep learning curve (but getting better). For smaller projects and 'hit the ground running' type of affairs, perhaps Subsonic or LinqToSql if you already have a database schema.
Kirschstein
I do not think this is a good approach.You should not use 'lazy loading' mindlessly. You need to think where and when you'll apply lazy loading instead of mis-using it like this.More info: http://davybrion.com/blog/2009/11/theres-lazy-loading-and-then-theres-lazy-coding/I would prefer the 'View' / SearchREsult classes. Even when using an ORM like NHibernate, this is very easy to use / support. You can just query on your domain model, and use a projection in order to get a 'View' object back.
Frederik Gheysels
Mis-using? This is why lazy loading was invented - do defer the loading of data due to different use-cases. Producing one DAO per view is effectively the same as integrating the data access layer into the view, something I wouldn't recommend. Then you might as well interface with the data source directly via some standard API - say SQL?
disown