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.

Lightweight class representation

I have a Book class thats defined as follows:
class Book
  int id;
  string Summary;
  string author;
  List<Photo> photos;
  List<Review> reviews;

Now this object is ideal for me to display book details but my customers usually arrive at the the details page from a page that dislays a list of books. So now, I have to create a lightweight object to display details of each book in a list.

class BookLite
  int id;
  string 3_line_summary;
  string author;

What is the best way to approach this?
Urumi Send private email
Monday, January 01, 2007
The whole idea of two classes representing the same thing is a bit fishy if the only reason is the data footprint... But if you rreally must, then either have a field of "lightweight" class within the "full" class and expose its interface in the full class, or derive the "full" class from the "lightweight" one. (The latter will only work if nothing else is *ever* derived from the Book class, or you will end up with implementing some things twice. So I recommend the former approach for the general case.)
Tuesday, January 02, 2007
P.S. In this particular example you gave, if the List<Review> type allocates dynamic memory - which I presume it does - then such field's footprint is negligible. What is kept  within your object's data is really a pointer, not the whole heavy list. So you are not getting any serious advantage from having two classes.

Just make one complete class and arrange these lists to be filled/loaded only when needed, not for every instance.
Tuesday, January 02, 2007
This kind of smells like a homework question, but yes having two different classes for the same info is going to have synchronization implications. Really you want a single model with the info and then these individual pages are views that use that single source of information.
Meghraj Reddy
Tuesday, January 02, 2007
The idea of having one class to list Books and another to provide the details of a single Book strikes me as being totally stupid. The essence of encapsulation is that you have a single class/object that contains ALL the properties and methods for each entity. So there should be a single Book class that deals with the contents of the Book table in the database.

If you are using the MVC design pattern (and if not, why not?) you will find that the 'List Books' transaction uses a different combination of View and Controller than the 'Show Book Details' transaction. It is up to the Controller to tell the Model (in this case an instance of the Book class) what records to retrieve from the database, and up to the View to format that data for display, either multiple horizontal rows for the List screen, or a single row displayed vertically for the Detail screen.

The Book class does not decide how many records to retrieve from the database - it carries out instructions passed to it by the Controller. Likewise it does not decide what details to display and in what format - that is the responsibility of the View.
Tony Marston Send private email
Tuesday, January 02, 2007
A usual way would be to only have one class, for example Book: the photos and reviews member data need not be initialized (they could be null) until/unless someone explicitly requests that data.
Christopher Wells Send private email
Tuesday, January 02, 2007
There is nice name for this: Proxy pattern (check GoF book).
Also, ask Google about lazy loading.
Tuesday, January 02, 2007
In the example you give, lazy loading of the two subordinate collections gives only minimal increase in footprint, and the collections can be transparently populated on demand to provide the functionality you need all in a single class.

There are good cases for having a lightweight class and a full-featured class (with easy conversion between them).  Criteria for this would be a MUCH larger difference between the feature profiles needed in two or more distinct scenarios AND it would need to outweigh the additional maintenance overhead of two classes with at least some common identifying behavior between instances.

This doesn't seem to be one of those cases (but could grow into one).
Cade Roux Send private email
Tuesday, January 02, 2007
You are referring to the idea of behavior-driven object design.  It is certainly not without its detractors (as evidenced by the above posts), but it is certainly a valid alternative.

The idea is that your classes are designed to fulfill their behavioral requirements, rather than data storage requirements. 

So your BookInfo class could contain the name of the book, the name of the author (not just the author id), the summary and any other information that would commonly be used in a list of books.  It's ok to denormalize your data here so that it is easier to used in your list.  (i.e., AuthorName is a first class property of the BookInfo class.  You're not going to instantiate an Autor object so you can get the name using the AuthorId, etc.)  BookInfo would be read-only, of course (which is why you can denormalize the data safely), and only contain the information you need to make selections, since making selections are the sole reason for BookInfo's existence.

The Book class, on the other hand, exists to allow drilling down into its information and for editing its contents.  It can be a lot more complex than your example class and contain behaviors and data that would be too heavyweight and simply inappropriate for use in a simple list.
Tuesday, January 02, 2007
What you're looking for is Lazy Loading.

In my code, I generally represent this with a getSummary method which would get enough info for something like a search result.  A request for anything else can load the whole object.
KC Send private email
Tuesday, January 02, 2007
Jake has hit the nail on the head.

Object-Oriented Design is about normalising behaviour - dividing an application's behaviour into suitable classes, each of which has a Single Responsibility (google for Single Responsibility Principle).

In the example provided, the Book class could be responsible for creating, updating and deleting books.  A BookInfo class, as Jake alluded to, can be responsible for holding information on books for a specific display purpose, such as in a list.

Should there be a requirement for more book related behaviour not covered by the responsibiltiies of Book or BookInfo, then creating more 'Book' classes is often a good choice choice giving each Book class just one reason to change (see SRP again).

I've not read any Object design method that prescribes that item of data shall sit in just one class.  The early posters in this thread are writing, rather aggressively, about data-driven design where one focuses on the data an object holds, trying to avoid duplication of data amongst the classes of a system.

Just remember that OO is all about behaviour and you'll be doing fine.
sensible Send private email
Tuesday, January 09, 2007

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

Other recent topics Other recent topics
Powered by FogBugz