I'm working on an order-entry system. One of the functions we're providing is allowing users to create a template of parts of an order. An order can consist of several items, each of which has a relatively complex hierarchy of components, and customers tend to order the same types of things over and over. So we're allowing the users to construct an order and save any part of it as a template that can be imported into future orders. There will also be a set of screens to create templates from scratch. These are essentially the same as the order screens, minus some functionality (like cost calculations) that's not related to templates.
Database-wise, the template data is stored in separate tables in the database, though the structure is pretty much identical to the order tables. Adding a template to an order is not a server-side thing - we're not going to issue a database command that adds everything and then re-load the order on the client. This is a two-tier desktop app, so we're taking advantage of that by pre-loading the templates to the client when the order screen is first opened.
Given how templates work, the object hierarchy for them is 99.5% the same as the hierarchy for orders - outside of the top-level object, pretty much everything else is the same. As such, I'm looking at merging the two hierchies and only having one set of objects. Directing to the appropriate tables is easy enough - but I'm wondering whether the "proper OO way" would be to create a second hierarchy of objects.
(We may do this anyway, but in that case we would be creating read-only versions that would be used on the order screen. No template editing functionality is needed there, and it could provide memory-consumption and performance gains. We're going to test first.)
The pro's to creating a second set are that it's not a 100% match - templates will have no objects for line-item costs, for example - and it really is a different type of functionality in the application. The con is that they're so close that I'd be essentially creating many child objects that are different in name only. Sure, they write to different database tables, but it's only the table name that's different. Add in that the screens to create an order and a template will be largely the same...
Any thoughts?
Though perhaps not a direct answer to your question, this is the reason DataPortal_Create() exists.
The idea behind DataPortal_Create() is to allow you to initialize a new object as it is created - often by pulling in data from config tables or templates.
So in general, if you want to pre-load and cache the template data, then I'd suggest you create a set of read-only objects for that purpose.
Then your order object's DataPortal_Create() method can include code to determine if it should initialize the order based on a template, or just return a blank order or whatever. If it needs to pre-load based on a template, it can use the cached read-only template objects to load itself as appropriate.
Actually, the templates will not be for an entire order - at least the users aren't asking for it. The templates will be for an item (or part of an item). Constructing an item from its constituent components can be a non-trivial exercise, and in this case there is no pre-defined catalog of items - only a list of components and basic item types. So in a way, the templates will serve as an item catalog that's built over time.
Anyway, that doesn't change the fact that DataPortal_Create() is how the order items will be created. One of the many selling points for using CSLA was the built-in functionality for creation by template. It just seems like an awful lot of data transfer code, especially when you factor in that the objects are, from a property perspective, identical. We'll end up with a significant percentage of code that looks like this:
OrderItem.A = TemplateItem.Awhich would also be on the children and grandchildren of the "OrderItem" object. We could take advantage of reflection, but the reflection code would still have to be in each object. Contrast that with something like this:
OrderItem = TemplateItem.Clone()
where one line of code gets it all done. It's this kind of thing that got me thinking that maybe the order and template objects should be the same object.
You may be able to use DataMapper to help copy the properties
without writing so much code.
Rocky
That's true - I never thought about using that. I think that would work nicely. It would still have to be in each object, but it's a lot less code.
Thanks!
So then would you also create separate Template objects for creating templates from scratch? While technically a different use case from creating an order, creating a template and creating an order contain largely the same steps. The screens they use in the application will be the same, with some conditional logic to hide the pieces that are order-creation-specific. Outside of the top-level object (Order vs. Template), and the omission of the pricing data from the template hierarchy, they are the same object tree. They write to different database tables, but the table structures are the same.
So again, I'm looking at creating objects that, to my way of thinking, are essentially different in name only. This seems like duplication of code, when a couple of internal behavioral flags might be all that's needed. But that also fairly tightly couples order creation and template creation. Right now, that's not a problem - but if the templates turn into a catalog of sorts, I could see different authorization requirements at that point. Not necessarily a big deal, since only one set would apply at object creation...
If I understand correctly, the user can be entering an order and
then just decide to save it as a template instead of an order right?
So to me that sounds like a command object that can take an
OrderEdit object graph and save its data into the template tables. So when the
user clicks “Save Order” you’d call _order.Save(), but when
they click “Save as Template” you’d do something like this:
OrderTemplateConverter.SaveTemplate(_order)
And OrderTemplateConverter would be a CommandBase-derived object
that would (probably) bring the OrderEdit object to the server, and then pull
out its properties as needed to save them into the template table(s).
Rocky
From: tmg4340
[mailto:cslanet@lhotka.net]
Sent: Tuesday, July 10, 2007 1:27 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: Create separate objects for templates?
So then
would you also create separate Template objects for creating templates from
scratch? While technically a different use case from creating an
order, creating a template and creating an order contain largely the same
steps. The screens they use in the application will be the same, with
some conditional logic to hide the pieces that are
order-creation-specific. Outside of the top-level object (Order vs.
Template), and the omission of the pricing data from the template hierarchy,
they are the same object tree. They write to different database tables,
but the table structures are the same.
So again,
I'm looking at creating objects that, to my way of thinking, are
essentially different in name only. This seems like duplication of code,
when a couple of internal behavioral flags might be all that's needed.
But that also fairly tightly couples order creation and template
creation. Right now, that's not a problem - but if the templates turn
into a catalog of sorts, I could see different authorization requirements at
that point. Not necessarily a big deal, since only one set would apply at
object creation...
Well, sort of - a user can choose to take portions of an order and save it as a template. They would still likely save the order as well. But that's not exactly what I'm asking about here. I'm sorry I'm being so confusing...
I have two issues to contend with: creating templates from a portion of an order as the order is being created, or creating templates from scratch. For creating templates from an order, I would agree that a TemplateConverter object is the way to go. That is actually fairly easy, since the structures are so similar.
What I am trying to tackle now is when a user wants to create a template from scratch. My problem is that the way a user creates a template and the way the user creates an order are basically the same. The application will use the same screens, and the object tree for a template and an order are the same (minus the branches that deals with order cost and order payment.) The validation of data is the same. The tables that template and order data are saved to are different names, but are structurally the same. The people that enter orders and enter templates would be the same.
So should I create separate objects for templates, or should I merge them with the order objects? Creating a separate set of objects would isolate the functionality, and more directly relate to the use cases, but the two sets would be essentially identical. That could change down the road - I could see separating the group of people who create orders from those who create templates - but that's purely speculation on my part, and that's still relatively easy to handle within one set of objects. And I see template and order structure & functionality to be fairly tightly integrated for the life of this application, since one feeds the other.
I know this is really starting to stray from a strictly CSLA-related question...
Copyright (c) Marimer LLC