Re: Business objects, subset of collection



Lahman,

First of all, thanks for taking the time to explain all of this.

We have a disconnect. Your model is typical of how one uses CRUD/USER
layered model infrastructures. That sort of processing is not a good
target for OO techniques. The RAD IDEs have already abstracted the
invariants of the processing in terms of Form/Query/Table and have
provided a lot of reusable infrastructure that one would have to develop
from scratch using OO techniques. In addition, such infrastructures are,
at best, object-based rather than object-oriented.
Interesting. If OO is the wrong tool for this job, it would explain
why I am having a hard time coming up with a smooth design for this
(that and the fact that I still have much to learn in the OOA/D
arena).


One way the difference is manifested is in separation of concerns for
different problem spaces. In an OOA/D context the model I provided would
be relevant in a subsystem that modeled the customer's business problem.
The rendering of the display would be handled in a different subsystem
that modeled the particular display paradigm. So for a GUI one might
have a model like:

[Display]
| 1
|
| R1
|
| contains
| *
[Window]
| 1
|
| R2
|
| Control
| *
[Control]

where [Control] is subclassed into things like [ListBox] and [Grid]. In
the GUI subsystem the only business semantics exists as labels and
titles for particular instances that are provided by the business
subsystem or, more commonly, through a configuration file.
When you say "subsystem" do you mean layers? The app is 3-tiered.

Your [InvoiceCollection] and [PaymentCollection] entities organize data
for the display and would map into instances of [Window] and [Control].
(In fact, they would both likely be GridControl instances.)
Yes they do organize data for display, but also for operation - the
user can select one or many vendors or invoices or payments and
perform some action on these (like move payment dates or remove
payments, etc.).


But mixing paradigms is usually a very bad idea from an OOA/D
perspective once one is outside the realm of CRUD/USER processing.
That's because the data structures needed to optimize the customer's
problem solution are usually not the same as those needed to optimize
data storage or display and the 1:1 mapping breaks down. So in OOA/D one
would be very careful to put [Invoice] and [Payment] in one subsystem
and [InvoiceCollection] and [PaymentCollection] in another subsystem.
That manages the mapping complexity by separating the concerns of
different problem spaces (display vs. business) so that one can focus on
one paradigm at a time. One would also encapsulate the subsystems
strongly so that objects in one subsystem would have no idea that the
objects in the other subsystem even exist.
Sorry, but I am not sure if I follow the last part: If
[InvoiceCollection] contains [Invoices], how can it be unware of
[Invoice]?

Also, would you mind elaborating on how you would separate the
collections from the elements they contain into different subsystems?
Do you know if C# (VS 2005) lends it self well to this concept?


I point all this out because it reflects a major disconnect between
OOA/D and the RAD infrastructures. So far your application sounds like
classic CRUD/USER processing. In that case using the RAD paradigm and
infrastructures will probably save you a ton of keystrokes. But that
will necessarily result in different models than I would use as an OOA/D
guy when solving non-CRUD/USER problems. (When I need to solve a
CRUD/USER problem I forget about OO and use a RAD IDE.) Thus I can't
really express the points I was trying to make in terms of your model.
That makes sense. I actually had a similar thought earlier: to
simply use a Dataset with DataViews for filtering. I have not used a
DataSet in a long time, but I guess I would have to pass the dataset /
dataview into business layer methods for the execution of operations
on the data (such as the InvoiceCollection.ChangeAllPayDates(DateTime
newDate) method I currently have). What are your thoughts on this?

By the way, what is your RAD IDE of choice?

public double PaymentTotalForDay
{
get
{
double amount = 0;
foreach (Vendor vendor in this)
amount += vendor.PaymentTotalForDay;

return amount;
}
}

This will return the total payment amount for the date specified in an
earlier call to Setfilter(filterDate). But since the VendorGrid also
needs to show PaymentTotalForMonth (regardless of day filtered on) and
PaymentTotal (no time-limiter), I wind up with two similar methods for
this. And then there are several other filter-specific methods, so it
does get a bit messy.

I am confused. In your model each InvoiceCollection has only one Vendor
related to it. Where does the foreach collection come from?
The above snipped is from [VendorCollection] and it iterates though
each [Vendor].

Assuming one needs a total paid by a vendor for a particular date across
all vendor invoices, I don't see a need for InvoiceCollection,
PaymentCollection, and SetFilter. If we had
Vendor::getTotalPaymentsByDate(date), all that method needs to do is
"walk" the R1 and R2 relationships in my model. For each Payment
accessed one then just checks the date and, if a match, accumulates the
payment amount. If one needs a total for all vendors, we just need to
iterate over the vendors and sum the results of calling
Vendor::getTotalPaymentsByDate.
AFAIK, there is no way to use an argument with databinding. Example:
one of the gridcolumns is bound to
VendorCollection.PaymentTotalForDay; I don't think you can bind it to
VendorCollection.getTotalPaymentsByDate(date). But I might be wrong -
if you (or anyone) knows how to do this, please let me know.


I know, but I guess I was looking for a way to separate out all the
filter-specific responsibilities in such a way as to simplify and make
the design cleaner, but it seems that doing that just adds more
complexity.

I am not sure where the filters come in. But I am probably looking at
the solution quite differently.
By "filter-specific responsiblities" I mean methods for retrieving and
working with a subset of the collections (like the SetFilter method
and the PaymentTotalForMonth).

One way to think of it is that there are three pieces of the problem.
One is to get a set of objects that are of interest. This is just a
matter of relationship navigation, which is orthogonal to class
semantics. That is, wherever one needs to construct, say, a Payment
total, one needs to find a relationship path to the relevant Payment
objects and navigate it. That is just a matter of "walking" the
collection classes that implement the relationship path segments.

The second piece of the problem if to extract a subset of the navigable
objects based on problem constraints (if necessary). This is the
"filtering". One tests attributes of the collection resulting from
relationship navigation and prunes those that are not relevant.

The third piece is to actually do something with the objects, like
accumulating a total, once one has the relevant subset.

My point here is that the "filtering" is just part of the relationship
navigation. That is, the attribute testing is done as one accesses each
object. That requires no special objects. (If the testing is complex, it
may be delegated to another object, but it will always be invoked
synchronously by whoever is doing the ...
Yes, this is basically what I doing now. One problem I am running
into is that the performance is not that great due to the many
traversals of the various collections. I will profile and see what
can be done (caching is tricky in this scenario). If I cannot resolve
the performance issue, I will probably look into using a DataSet &
DataView instead since they might be better tools for this job.

Thanks,
Jim
.



Relevant Pages

  • Re: Business objects, subset of collection
    ... be relevant in a subsystem that modeled the customer's business problem. ... The rendering of the display would be handled in a different subsystem ... Those paradigms are abstracted quite differently than the business environment (e.g., objects like Invoice and Payment). ...
    (comp.object)
  • Re: $73 an Hour
    ... This means that the vendor has ... Blogger information indicates that the payment times have ... problems with their diesel engine supplier [Navistar]. ...
    (rec.crafts.metalworking)
  • Re: Business objects, subset of collection
    ... with amount due, payment total, etc. ... for the selected vendor ... I think one way to express my point is that the filter is the WHERE clause and one specifies the attributeto be checked in it. ...
    (comp.object)
  • Table Join
    ... Here is the query I have written using Inner join ... date format to dd/mm/yyyy format. ... Following is the results obtained for a particular vendor between 1st ... **Payment is the sum of Cash_Amt and Cheque_Amt in the ...
    (microsoft.public.access.queries)
  • Re: eBay dodginess
    ... At the time of writing there are three Bianchi bikes listed by the same vendor with all these dubious characteristics. ... There was one item he bid for which he won, but when got in contact with vendor to make arrangements to go to collect bike & make payment, all of a sudden vendor knew nothing about this ebay sale. ...
    (uk.rec.cycling)