The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Designing domain objects

Hi all. I've got a question that I think good design principles can help with, but I'm at a loss for how. Note that I'm simplifying the situation for the sake of explaining it clearly.

Suppose I've got a big customer database where I'm persisting lots of information about my customers. Now I want to put a web service in front of the database which supports basic CRUD operations. Simple, right?

Suppose, though, the customer has dozens of properties. And of course, some of those properties could be forcing joins across huge tables. Now think about, say, the GetCustomerByName operation. it's going to return a whole massive Customer object every time. But most, or all, of the clients could care less about many of the properties (in fact, they all only want a few, but it's a different small subset for each client). Is there some way to have our cake (a small number of find operations), and eat it too (a small number of Customer DTOs)?

Any thoughts are welcome. Thanks!
Andrew Wagner Send private email
Friday, August 15, 2008
> Any thoughts are welcome.

Create a single "Customer" type.
The "Customer" type has a bajillion properties.
In most SELECT statements, only initialize some subset of all possible properties.
Return null or throw an exception if the client asks for a property that wasn't initialized/retrieved by the select statement.

class Customer
  //SQL SELECT initializes this dictionary sparsely
  Dictionary<string, object> properties;

  //properties invoked from client code
  public string name
    get { return (string)properties["name"]; }
  public DateTime dateOfBirth
    get { return (DateTime)properties["dateOfBirth"]; }
Christopher Wells Send private email
Friday, August 15, 2008
Then either getcustomerbyname takes a list of properties that you are interested in or you have a SetCustomerCounsumerPref and who ever is consuming these customer objects gets to specify the properties given in the response to getcustomerbyname.
Friday, August 15, 2008
I've used two different strategies:

1) Lazy Loading

2) Separate Digest and Full Objects: Customer and CustomerDigest

For big lists of customers, you would only get lists of digests (name, ID, and minimal crucial data - which could come from joins on the back end, that's not really what you're trying to reduce, but the data on the wire).  Then you could use l = CustomerDigest.ListBySearch(criteria); cdg = l[selected]; Customer.GetFromDigest(cdg);, etc.  This actually helps a bit in type safety if you have a lot of int or guid object ids, where the compiler won't be able to ensure that the int you're passing is the ID of the right kind of object you are trying to retrieve.
Cade Roux Send private email
Friday, August 15, 2008
How often would you use the massive all-inclusive Customer object?

Because I'm thinking that's probably not a very common use-case scenario.
Saturday, August 16, 2008
Out of CRUD, the focus seems to be more on R, the retrieval. The other cases are relatively straightforward.

You would like to optimize on the (1) find operations and (2) number of objects.

Let us say, you fix the number of objects (classes) to whatever you feel is acceptable, then it boils down to optimizing the find.

One way to achieve this is to load the complex join results (for all customers) into a cache (an in-memory cache like memcached). All webservice requests are serviced by in memory method calls and that should not be expensive.

Doing the same using read-only views could also be an option. An advantage of using a view over cache is that the view can be made to be updated at all times and so the data is always fresh.

You may have to experiment by having different queries and adjust the number of objects until you are satisfied with the balance.
sathya Send private email
Saturday, August 16, 2008

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz