Child with a reference to a child witch is also a parent

Child with a reference to a child witch is also a parent

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


Goran posted on Thursday, July 23, 2009

If we look at the Invoice entity, we see that it contains a child collection InvoiceItems, which is a collection of InvoiceItem. InvoiceItem will need to hold a reference to a Article class (1-1 relationship), since there will be a need to display article info for particular InvoiceItem (name, serial number, meaurement unit, tax rate). Article class is also part of the root collection ArticleList, so it becomes a candidate for switchable object.

In your book you state that when there is a need for switchable objects, usually its the result of a bad design. How exactly can I redesign it?

And one more thing that is troubling me, Coming from the procedural world, I find difficult to understand one thing: Article class will have many"shorter forms" of it. Example, Article class contains 15 fields which are all used when doing CRUD operations on ArticleList. In previously mentioned situation (as child of a InvoiceItem), there wil be only a need for 5 Article properties (read only access). In some other scenario, I wil lneed only 3 properties (usually when I need to choose some article to display some info about it, like in Article card) - also read only. Will I have different classes for each "shorter form" of Article class? Or i should also fetch those fields I dont care about (which highly degrades performance)?

In above situation DataTable is highly effcient - I am not interested in behavior, nor business rules, I just want to display data to user in order to make selection.

Thanks,
Goran


ajj3085 replied on Thursday, July 23, 2009

Create an ArticleInvoiceItem, which has the additional fields. These wouldn't display as columns in a grid, but it doesn't seem like you'd expect that anyway (after all, what if you later add Book, Magazine, Software, Video Game... your grid would have tons of columns which may be empty most of the time).

tmg4340 replied on Thursday, July 23, 2009

The short answer is yes, you would have separate objects.

CSLA objects are designed to fulfill a use case.  Since you note that, in this scenario, the Article information is only being displayed, you do not need/want your full (and, I presume, editable) Article object.  You would create a ReadOnlyBase-derived child object that contains only the properties that your particular scenario requires.  You would also build your data access for that object to only pull the properties you need as well.  Since you list two display-only situations, you would probably create two objects - one with the five properties you need for the one scenario, and the other with the three properties you need for that scenario.

If the property lists overlap (i.e. the three properties you need in one scenario are also needed in the other), then you could probably just create one object, and ignore the two properties you don't need in the one case.  Yes, that technically degrades performance - but unless those two properties are monstrous BLOB's of data, any performance hit taken by pulling two pieces of unneeded data is going to be negligible.

Given this style of object design, it is not uncommon at all to have multiple "versions" of an object.  You'll see Rocky talk about that in multiple posts in the forum.  When building your object designs, design the objects to fulfill the use case, without any regard to what you may have built for another use case.  If, after building your object graph, you see two objects that perform the same function in two use cases, then you can combine the objects.  Don't combine them just because they have the same data - if they have different business rules or behavior, keep them separate.  Only if the data and the behavior match should you merge them.

This isn't to say that refactoring common code isn't done - that's the point of the Assignment class in the ProjectTracker example.  But complete object re-use is not the overarching goal here.

HTH

- Scott

Goran replied on Thursday, July 23, 2009

Tahnks for the response.

@ ajj3085
Some columns from ArticleItem would be displayed in a grid, maybe I haven't been clear enough. The idea is to map grid to columns that need to be displayed, other columns can be used just for the background operations.

Invoice (InvoiceId, Number, Date, Customer, InvoiceItems)
InvoiceItems (collection of InvoiceItem)
InvoiceItem (InvoiceId, ArticleItem, Quantity, Price, TaxRate)
ArticleItem(ArticleId, ArticleCode, ArticleName, MeasurementUnit,TaxRate)

I will name it ArticleItem, because it will be reused in many different cases, like with Invoice, Order, Offer, etc

@Scott

Thanks for the very informative response, I have cleared many things now.

There is one more thing - actual implementation: Invoice fetches data from stored procedure, first resultset is used to get Invoice data, and second resultset is passed to InvoiceItems collection, which loops through data and passes each item data to InvoiceItem GetItem method, to populate itself wtith data. So far so good. Now I need to populate ArticleItem data, and I am not sure if I am using the correct way. This is how I did it: the second resultset has joined data from both InvoiceItem and Article table, and I am passing the same resultset to both classes, to use only the fields they need. Ex

// in the PurchaseItemsList class
private void Fetch(SafeDataReader dr)
{
    RaiseListChangedEvents = false;
    while (dr.Read())
    {
        PurchaseItem item = PurchaseListItem.GetItem(dr);
        item.Article = ArticleItem.GetItem(dr);
        this.Add(item);
    }
    RaiseListChangedEvents = true;
}

Is this approach good? I can make it work for sure, but since I am now trying to rewrite the whole application (which has like 100 forms), I want to do it properly at least. :)

tmg4340 replied on Friday, July 24, 2009

This approach is fine.  My only question is, if you only have one ArticleItem related to an InvoiceItem, why the separate class?  Especially considering that the data is read-only, you could save yourself some potential binding headaches if you combined InvoiceItem and ArticleItem.  Your object design can (and, in some cases, should) be independent of database structure.

If you could have multiple articles related to an invoice item, then you would need a separate class - but then I wouldn't use your JOIN-based SQL construct; I'd create a third resultset.  And your InvoiceItem would have a list of ArticleItem objects with its own factory method, similar to how InvoiceItem is constructed.

HTH

- Scott

Goran replied on Saturday, July 25, 2009

Data in AricleItem is read only - user cant change name, code, measurement unit, tax rate, etc for the article in the Invoice Form. However, LineItem is editable, since User can change ArticleItem, quantity, price, etc.

There is a read-only ArticleItems collection, and when user selects one article to place in invoice, this new LineItem.ArticleItem property has reference to current ArticleItem in collection.


Copyright (c) Marimer LLC