(Bad) design habits

(Bad) design habits

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


burmajam posted on Monday, June 05, 2006

Hi all.

First of all I want to say that my English is not good enough, but I’ll do my best to explain the problem. It is design problem. In the attachment is UML class diagram that I need to implement in CSLA 2.0.x for the following  request:

This is Merchandise and Service tracking program. I need Merchandise object with its quantity change list. Changes are tracked via Documents.  There are few kind of Documents with their  DocumentItems. DocumentItem contents can be merchandise or service. Documents are incoming or outgoing in aspect of merchandise quantity. If DocumentItemContents (GoF Adapter pattern) is MerchandiseChange it changes Merchandise quantity or price. If it is ServiceChange it just tracks down usage of Service. I need to review each merchandise change list and be able to navigate from each change list item to document that made that change. Because each type of document has the same behavior, some properties (like date, document number, …) and each document has collection of its own DocumentItems, I thought I should generalize Document and DocumentItem objects, put the most business logic in them and then inherit them for concrete types of documents and their concrete items (GoF Factory + Template Method patterns).

 

The biggest problem I have is implementation of inheritance in CSLA 2.0, their OR mapping and navigation from general class association to concrete object (i.e. DocumentItem.contents is declared as DocumentItemContents, but it is abstract and it is either MerchandiseChange or ServiceChange). I know how to implement this in Borlands ECO framework, but I’d like to do it in CSLA. I think there’s a lack of CSLA documentation based on inheritance. I know it’s not the best practice, but most of the patterns are based upon it.

 

I hope I was clear enough, I really did my best :) Are there some idea guidelines, diagram redefinitions, … please :)

RockfordLhotka replied on Monday, June 05, 2006

Because CSLA .NET 2.0 makes such heavy use of generics, inheritance for the purpose of polymorphism is virtually impossible.

Instead, you can use interfaces to accomplish your goal. A bonus is that this approach typically makes your data access (ORM) easier to manage as well. This article

http://www.lhotka.net/Articles.aspx?id=b8515cd9-7f8e-43df-9efd-cd958dfdc21a

should help describe how to use interfaces to get polymorphic child items in your collections, which should allow you to have various types of line items that all have some common interface elements.

skagen00 replied on Friday, June 30, 2006

RockfordLhotka:

Because CSLA .NET 2.0 makes such heavy use of generics, inheritance for the purpose of polymorphism is virtually impossible.

My lord, you aren't kidding!!!  Everytime I think I solve one of the issues I bumped into another one.

I have a question, one of which isn't related to the inheritance aspect.

It seems that the interface needs to declare the Update/DeleteSelf/Insert/Fetch methods which aren't traditionally public in CSLA. As the collection loops through the IChild objects on an update, it needs to call IChild.Update() and IChild.Insert() as necessary. They seem to need to be in the interface in order for this to work. 

My class definition is as such:

public sealed class ProfileMemberCollection<T> : BusinessListBase<ProfileMemberCollection<T>, T> where T : IProfileMember

I liked this approach as I am able to say that I want a member collection of only one specific ILineItem implementation type/non-polymorphic (or I can use T = ILineItem for all ILineItem implementation types). Note, I'm not sure if I have all the generic stuff correct just yet, but my question really isn't in relation to that.

When I noticed the problem, I attempted to deal with the Update/DeleteSelf/Insert (Fetch is a slightly different animal) by tagging an internal interface on the class that "T" would also implement (IProfileMemberInternal). But the compiler didn't like me placing this internal interface implementation restriction on T, as the collection class is public.

So, what I found worked for me was to cast the object to the internal interface for the purpose of doing the Update/DeleteSelf/Insert. It compiles - but should I be able to cast from one interface to another like that?

((IProfileMemberInternal)profileMember).DeleteSelf();

For the fetch, that is a different animal - but I wanted to write about my experiences trying to get a polymorphic collection to work and to ask if you had any suggestions of an alternative to my internal interface.

Copyright (c) Marimer LLC