Lazy Loading of certain properties in an Object

Lazy Loading of certain properties in an Object

Old forum URL: forums.lhotka.net/forums/t/310.aspx


Pradeep posted on Wednesday, June 07, 2006

 Hi,
I have an Invoice object and it has some accounting information which would be set based on other properties of the invoice object. I have a table in my database which has the various rules for setting this information. As soon as the user clicks on a button, I want to run these rules and fetch the necessary acc. information.
 
Question:
Can I have two fetch methods (not sure if even CSLA will allow this) in my invoice object's one for fetching the whole data and one for fetching the acc information alone. Or should I create a separate accinfo object inside invoice object and write a fetch method inside it?
 
Could any one tell, which is the better way.
 
Thank You
 

RockfordLhotka replied on Wednesday, June 07, 2006

I very, very strongly recommend against implementing lazy loading within the context of an object. Lazy loading is rarely a good idea in any case, and is usually a symptom of data-centric object design.

However, there are some cases where lazy loading of child objects can make sense, because the use case calls for incremental creation of objects/information. That may be the case here, you'll have to be the judge.

If you are going to use lazy loading, it is best to do it at the object level, so you'd want to do it as a child object of Invoice. Just remember to define a single, clear responsibility for each object as I discuss in Chapter 6 and that will help keep things managible.

The question I have is whether this "accounting information" is read-only or editable? From your description it certainly sounds like it could be read-only information that is used by the Invoice object in order to implement various business logic. In that case you might have some very clear responsibilities:

Invoice: Enter/edit valid invoice data

AccountingInfo: Provide read-only access to accounting parameters/settings

In this case it is absolutely valid for Invoice to have a "using" relationship (NOT parent-child) with AccountingInfo. In other words, the Invoice object, at the appropriate time, might just ask for the AccountingInfo object - which would be a read-only root object all by itself:

[NonSerialized][NotUndoable]
private AccountingInfo _acctInfo;

// ...

  if (_acctInfo == null)
    _acctInfo = AccountingInfo.GetInfo(supply params here);

 

Pradeep replied on Wednesday, June 07, 2006

Rocky,
Thanks for the reply. You are right about the "using" relationship. The invoice object uses Accounting info object. But it is editable though.  I have a set of rules which I want to maintain in the database for flexibility. These rules are based on different properties of the invoice. So as soon as the user set the properties on the invoice object and hit a button (GetInvoiceData), I pass in all required information to the database and run my rules.
 
This would later return me a set of accounting information. If my invoice information did not satisfy any of the rules, these will be blank and the user can manually set them (for now it is editable, but I am sure in the future it is going to be read-only since it is sensitive data).
 
I thought about using the CommandBase object, but it just has Update method. So think my option now is to create a new AccountingInfo object (inheriting from BusinessBase) and have a criteria object inside it. This will have a fetch method, which basically will run all the rules and return the necessary information.
 
Thanks again...

RockfordLhotka replied on Wednesday, June 07, 2006

To lazy load a child object you implement the object following the child template (MarkAsChild is called, and so forth), but you also implement a factory method (typically internal/Friend) and a DataPortal_Fetch() method. The data portal itself has no idea about root or child objects - it just routes calls to DataPortal_XYZ methods.

If I were you I'd carefully walk through the use case though, and identify sub use cases and the objects required by each. I have a suspicion that the accounting info object is not actually a child of Invoice, but rather is an editable root on its own, and that it is part of a sub use case within the overall "Create an Invoice" use case. I could be wrong, as I don't know your domain, but this is my guess.

Either that or you have two Invoice objects - the "Collect data" one and the "Processed data" one. In other words, I suspect that this is what happens:

  1. User enters data into Invoice
  2. Invoice is processed on server, with rules applied
  3. User edits data on Invoice

I think what you have here are three objects: InvoiceCollector, InvoiceProcessor and Invoice - for steps 1, 2 and 3 respectively.

InvoiceCollector is probably not a root object as such. It is probably more like a non-persisting object as I just described to Barry here (http://forums.lhotka.net/forums/permalink/1417/1496/ShowThread.aspx#1496).

InvoiceProcessor is probably a CommandBase object that moves InvoiceCollector to the server and processes it there - then discards it, and creates an Invoice object based on the processed results. This Invoice object is then returned to the UI through InvoiceProcessor.

This allows step 3 to have an Invoice object that is post-processed, with your rules applied.

Hopefully this makes sense in some way.

Copyright (c) Marimer LLC