Business logic question

Business logic question

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


ajj3085 posted on Monday, August 07, 2006

Hi,

I need some advice, as I don't know the best way to proceed. 

I have a quote object, which is what you'd expect.  The user may modify the quote as much as they want.  At some point, they send the quote to the customer.  At this point, the quote becomes readonly.  The only way to change it is to make a revision, which basically is a completely new document which is pre-populated will all the data from the old document (and the revision is tied to the original, to track history).  Also, it shouldn't be possible to send to the customer if the quote has a revision which supersides the previous version.

Basically the requirement is this; the user needs to specify they are sending the quote to the customer.  The user will be able to fax the document or send it via email.  Either way, a Pdf will be created first, and then printed or attached to a new email. 

Obviously I need a method which is similar to save, but also sets a flag to mark the quote readonly.  But is it the BO's responsibilty to create the Pdf?  The UIs responsiblity?  I'm leaning toward the latter, as its a presentation thing, but I just want to be sure.

Andy

RockfordLhotka replied on Monday, August 07, 2006

I agree that you either need a method that sets the flag and calls Save() to "close" the quote.

I would think that the PDF creation is very much a reporting operation. If you read my 1.0 book, I had a bit of discussion where I split the concept of reporting into "report" and "list", where a "list" is something you create against easy-to-get data. Lists can be generated using client-side report generation tools, and that seems to be the case here.

ajj3085 replied on Monday, August 07, 2006

That's what I though; the thing that throws me sometimes is that the pdf generation is a requirement at the time the quote is created.. then I start wondering.. kind of like if some business operation fails, and email needs to be sent.

Thanks for the feedback; kinda out of it today.

Andy

ajj3085 replied on Monday, August 07, 2006

There's only one piece about this that I'm missing; whats to stop the UI layer from generating the Pdf or exporting the data some how before locking it to prevent any changes?

Thats why I get stuck sometimes... it seems like the answer is nothing... yet it is a business rule that the order cannot be sent to a customer before its locked. 

Am I worrying about nothing here?

Andy

SonOfPirate replied on Monday, August 07, 2006

In keeping with a behavior-based design, it would make sense if you have an object whose responsibility it is to generate the PDF file, e.g. QuotePdfGenerator.

In dealing with this VERY frequent topic, we usually look at it this way: The PDF file itself is a presentation component, but the source of the PDF is a business object. 

So, this would allow you to implement the process in one of two ways:

  1. Have a GeneratePDF or ToPDF (or whatever) method on your Quote object.  Your UI code calls this method.  Inside the method, the Quote object delegates to your helper class for the work.
  2. Have a static Generate method on the helper class that accepts a Quote object as an argument.  The UI code calls this method passing in the Quote object.

or, better yet, do both!  Then you have the option at any time.

But, that doesn't really answer your questions about which way to deal with it.  Truth be told, this is just semantics as odds are the GeneratePDF (or whatever) method on your Quote object is just going to call QuotePdfGenerator.Generate(this), so it is actually just another way of doing the exact smae thing.

The rule of thumb I usually use when trying to determine which way to go is to decide if you have or need to have an instance of the object you are working with.  If this is the only thing you are doing with the object, than using the static method on the helper class is the perferred approach.  If you have the object in memory already, use the object's method to initiate the operation.

For example, if you have the following code:

Quote q = Quotes[QuoteIdDropDownList.SelectedValue];
q.GeneratePdf();

I'd rather use this approach:

QuotePdfGenerator.Generate(Quote[QuoteIdDropDownList.SelectedValue]);

because you aren't using the instance for anything other than this function.

On the other hand, as an example, if you are using a form that has the Quote stored in a private variable and multiple operations are performed on that object, I would do the following:

dataSource.GeneratePdf();

Ultimately, by having methods in both places, how you use them is really up to you and preferences.  Everyone develops their own preferences and logic based on their own experiences, so it is highly subjective.  This is just the informal rule-of-thumb we try to apply to this situation to make the same decision.

Of course, you raise a valid point in regards to enforcing business rules that govern who and when the method may be used.  Based on this, I would say that calling the method on the object is the better path.  Inside this method, which ultimately delegates to the helper class, you can implement your validation rules to control access to the method.

Hope this helps.  Good luck.

ajj3085 replied on Tuesday, August 08, 2006

I think this is the route I will go; it doesn't eliminate the problem (the UI developer can build their own report, etc etc.) but perhaps by providing a method here I can exploit the 'laziness' factor that I will always use the method here to generate the quote (or order, or invoice).

It won't be a pdf, it will be a ReportingSerivces LocalReport.. which can be exported to pdf.

Thanks
Andy

Copyright (c) Marimer LLC