4

Let's say I have an application which consists of both client and server. Client is using MVVM pattern (with WPF) and server is simply a WCF service which fetches some data from database and returns data as DTO-objects to client. In client, DataAccess layer converts these DTOs to domain objects and passes them to Model. ViewModel uses Model to fetch data (Domain Object) and populates itself with it.

enter image description here

To optimize database performance, each ViewModel is given only the data it really needs and nothing more (as recommended by many sources). For example, let's say there is an entity called DbCustomer which has 30 properties, and there are also 3 different Views related to customers: CustomerProfileView, CustomersListView and CustomerThirdView. Every view needs different portion of data: CustomerProfileView uses 20 properties, CustomersListViewuses 10 properties and CustomerThirdView uses only 4 properties. For each View, only required properties are fetched from database and delivered to ViewModel.

Now the problem arises: how should I design my Domain Objects to support this?

Solution 1, one partially loaded Domain Object (no-go)

If I have only one Customer Domain Object which is used by all ViewModels, it would have different data depending on the ViewModel that requested it. Obviously this is a no-go way because if I have to use this Customer object somewhere else I cannot be sure does it have enough properties loaded.

For example, I might have method GetDataStoragePath which is supposed to return string describing path to customer's private files. The method requires properties FirstName, LastName, SSN and IsExternalCustomer. Now, let's say CustomerThirdView doesn't need IsExternalCustomer, so it is not loaded when CustomerThirdViewModel requests Model to load Customer. Now if I use this Customer somewhere else (it is not a ViewModel specific object), the method GetDataStoragePath will fail.

Solution 2, three different Domain Objects

In another solution there would be 3 different Domain Objects (used as data containers) with suitable interfaces, and thenGetDataStoragePath would depend only from this interface. Example:

public interface ICanGetDataStoragePath {
    string FirstName { get; }
    string LastName { get; }
    string SSN { get; }
    bool IsExternalCustomer { get; }
}

public CustomerProfileData : ICanGetDataStoragePath { ... } // Implements interface
public CustomerListViewData : ICanGetDataStoragPath { ... } // Implements interface
public CustomerThirdViewData { ... } // Does NOT implement interface

public class CustomerLogic : ICustomerLogic {
    public string GetDataStoragePath(ICanGetDataStoragePath customer) {...}
}

This would lead to Anemic Domain Model but it is not a problem in my opinion. However, it seems messy since I can easily imagine that there would be 20 different methods with different needs which would result in 20 interfaces (and only for Customer, there are LOTS of other domain objects also). Of course in this simple case I could pass all four parameters separately to GetDataStoragePath but in real life there are many more required properties.

Are there any other options? What would be the best way to solve the problem?

user544511
  • 759
  • 6
  • 15

1 Answers1

2

Your model obviously has to much Data. Why not make 3 models and one composite model?

i.e.

public class CustomerProfile 
{
    public string Phone { get; set; }
    // other profile fields
}

public class Customer 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string SSN { get; set; }
    public bool IsExternalCustomer { get; set; }
    public CustomerProfile Profile { get; set; }
}

Then you'd put all of your always required fields into the Customer class and group the rest together, i.e. in a CustomerProfile class. If it's null, then that data wasn't fetched and isn't available

Tseng
  • 61,549
  • 15
  • 193
  • 205
  • 1
    Customer entity with 30 properties was a simplification, a more realistic example is entities A, B, and C with 10 properties each. Some of properties are common for all entities (e.g. Creator, which identifier who created the entity, CreationTime, Modifier etc.). Sometimes my Domain Objects needs all properties from A + some properties from B. Sometimes my Domain Objects need only a few properties from A. Sometimes one porperty from each A, B and C would be sufficient. Also, there is no such thing as "always required fields" because different Views really require different data. – user544511 Aug 01 '14 at 15:13