Developing a Business Object to Represent a Hierarchical Organization Structure.

Developing a Business Object to Represent a Hierarchical Organization Structure.

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


tarekahf posted on Wednesday, December 30, 2009

I have to design a class, set of classes or Business Object to represent a Hierarchical Organization Structure (Tree-Like or Composite Structure).

The Org. Struct of the company looks like the following:

- Root
- Complex
- Departments
- Divisions


The structure is stored in a very flat and simple table (only one table) which has 3 fields, something like:

- OrgCode,
- ShortName,
- LongName.

Where OrgCode is a string of fixed char length, divided in virtual segments, where each segment represent the code and the level (Depth).

For example, the code:

OrgCode = 0100305

Is actually "01-003-05",

where 01 is Operations Complex, 003 is Finance Department, and 05 is Customer Payments Division.

The table is stored in Adabas/Unix Platform, and I can have read-only access to the table via OLE/ADO.NET or ODBC.

I want to build a recursive structure using a Business Object to represent such Organization Hierarchy.

I did some search, and found this website which describe a method for building composite objects:

http://www.dofactory.com/patterns/patterncomposite.aspx#_self1

Finally, I must wrap the completed Business Object Interfaces with a Web Service, so that such functionality could be access from nearly any front-end such as MS-Access, IE, Adobe LiveCycle PDF Forms, and/or Lotus Notes.

I want to implement this project using CSLA approach.

Appreciate your help and recommendations.

Tarek.

ajj3085 replied on Wednesday, December 30, 2009

I've implemented a composite pattern using Csla.  It requires you to do some work that Csla would normally do, because you're really combining a BB with a BLB in a single class.  It seems to work though, although the cavet is that I implemented this prior to Managed Properties / Fields, and I have yet to try to convert them.  So everything is private backing.

My abstract base class inherits the normal generic BB.  I've also impelemented the generic IEnumerable interface, Csla.Core.IParent, ICustomTypeDescriptor.  You also need to track children and deletedChildren yourself, since you're inheriting BB (I just used an IList[T]) in your Node subclass.

In the Leaf subclass, I overrode all the child related methods (Add, Remove, ChildCount, etc) and simply call the base (which throws a NotSupportedException).  I did this because I sealed those methods at the leaf level, so that leaf subclasses cannot override them, and it also removes them from Intellisense. 

In the Node class, I have a private class which subclasses BindingList.  The only need is to create a method which is decorated with an OnDeserialized attribute.  You then loop through the collection and call base.SetItem for each item.  This is one of the things Csla does for you I think.

That's the grand overview... but it does seem workable.  I even have a Node subclass which take the heirarchy and flattens it for use in a DataGrid. 

Design everything property, and your UIs should all be able to use the same BOs (assuming they have the same use cases, just different methods of accessing the business logic.

HTH

Andy

tarekahf replied on Wednesday, December 30, 2009

Hi Andy,

Thank you for your feedback. However, I feel I am a bit lost, or actually totally lost.

It sounds a lot of work to make it CSLA Compliant, right ?

I don't want to shoot myself in the foot, just to apply CSLA by force ?

Would you mind give me a samle code to show me how to make the following classes CSLA Compliant :

- Component,
- Composite,
- Leaf Node, and
- Child Nodes...

I need to see if it worth the effort to apply CSLA here, and what is the added value ?

Appreciate your feedback.

Tarek.

ajj3085 replied on Thursday, December 31, 2009

Actually most of the work is in implementing collection related functionality, since your abstract base class inherits BusinessBase, which is not a Csla collection type.  Most of the composite patterns I've seen show Java code, and its the same there; you're not starting with a collection subtype, just a plain object.  When I implemented it, I was using the Head First Design Patterns book as a guide.

You'd want to use Csla if the following are true (or most of them are):

Your use cases are the same in all your front ends, so you want a central business library.

You want a consistent way to build your business layers for applications.

You want to be able to replace the database backend or design with out changing your business rules and their UIs (in Csla you'd update the code in the DataPortal_xyz methods, and that would likely be all you need to do).

You need to be able to switch between two-tier and three-tier deployments easily.

It sounds like some of these might be true for you.  In your case, you mention a web service and an IE front end (so I assume you'd use Asp.net).  If the use cases are the same for both of those, your web service could use your csla based library, and your Asp.Net page would likely use the csla based library directly (there's little value in using a web service if you have control of everything).

HTH

Andy

tarekahf replied on Thursday, December 31, 2009

Thank again, Andy.

Is it possible that you give me sample code how to implement BB and BLB for the related composite design pattern ?

Thanks.

tarekahf replied on Sunday, January 03, 2010

I found this article which shows how to implement composite patterns using ASP.NET (VB):

http://wiki.asp.net/page.aspx/359/composite/

I think this will make it easier to use CSLA since it does not user Abstract Classes. It uses Interfaces instead.

Tarek.

tarekahf replied on Sunday, January 03, 2010

I did some testing, and I realized that I really do not need to use Interfaces nor Abstract classes. They are just making the situaiton complex.

I used the following model which is working fine:

Public Class OrgComponentList(Of MyType)
Inherits List(Of MyType)

End Class

Public Class OrgNode2

Protected mOrgLevel As Integer
Protected mOrgFlatCode As String
Protected mOrgUnitCode As String
Protected mOrgUnitDescEng As String
Protected mOrgUnitDescArb As String
Private mOrgNodeChildren As New OrgComponentList(Of OrgNode2)()


Public ReadOnly Property OrgFlatCode() As String
Get
Return mOrgFlatCode
End Get
End Property

Public ReadOnly Property OrgLevel() As Integer
Get
Return mOrgLevel
End Get
End Property

Public ReadOnly Property OrgUnitCode() As String
Get
Return mOrgUnitCode
End Get
End Property

Public ReadOnly Property OrgUnitDescArb() As String
Get
Return mOrgUnitDescArb
End Get
End Property

Public ReadOnly Property OrgUnitDescEng() As String
Get
Return mOrgUnitDescEng
End Get
End Property

Public Sub New(ByVal OrgUnitDescEng As String)
mOrgUnitDescEng = OrgUnitDescEng
End Sub

Public Overridable Sub Add(ByVal c As OrgNode2)
mOrgNodeChildren.Add(c)
End Sub

Public Overridable Sub Remove(ByVal c As OrgNode2)
mOrgNodeChildren.Remove(c)
End Sub

Public Overridable Sub Display(ByVal depth As Integer)
Console.WriteLine(New [String]("-"c, depth) + mOrgUnitDescEng)
' Recursively display child nodes
For Each component As OrgNode2 In mOrgNodeChildren
component.Display(depth + 2)
Next
End Sub

End Class


Public Class OrgNodeLeaf2
Inherits OrgNode2

' Constructor
Public Sub New(ByVal OrgUnitDescEng As String)
MyBase.New(OrgUnitDescEng)
End Sub

Public Overloads Overrides Sub Add(ByVal c As OrgNode2)
Console.WriteLine("Cannot add to a leaf")
End Sub

Public Overloads Overrides Sub Remove(ByVal c As OrgNode2)
Console.WriteLine("Cannot remove from a leaf")
End Sub

Public Overloads Overrides Sub Display(ByVal depth As Integer)
Console.WriteLine(New [String]("-"c, depth) + mOrgUnitDescEng)
End Sub

End Class

In other words, the Composite Node is a normal class, which has everything. The Leaf Node, is inherited from the Composit Node, and it will overried some methods of the parent class. I think this approach will allow me to convert this model into CSLA more easily.

I have done a test using console application and it works.

Now the question is:

- What I will loose if I do not use Abstract Classes nor Interfaces ?

- Do you think this will make it easier to apply CSLA Model ?

Tarek.

ajj3085 replied on Tuesday, January 05, 2010

The abstract just lets you define some points where you force subclasses to implement something, if there's no sane default.  Don't think you'd lose anything by not having one, but it can be a clue that the class is incomplete on its own (which your ultimate superclass will be, since its neither a node nor a leaf).

The interfaces I mentioned, some might be required, some might be handy (its been a while since I did the implementation).

IParent from Csla, I have an impelementation for RemoveChild, which I believe is required in some cases (at least, I likely implemented it for a reason, becaues I didn't implement ApplyChildEdit, that method just does nothing).

IEnumerable I would think is important, since composites usually mean you need to move through the collection some how.  In this case, using some kind of tree traversal.  Also, it lets you use the foreach construct.  Also, don't forget about Linq, which only works on types which impelement IEnumerable.

ICustomTypeDescriptor I had to implement, or things won't work correctly, such as wrong values in databinding, and some other weirdness.  I don't recall the exact problems, but without it things just wouldn't work.  You'll have to reimplement this in subclasses too if you add properties which aren't on the base class (which I have for some special case line items used or reporting).

tarekahf replied on Wednesday, January 13, 2010

I've completed the development of the CSLA BO and Web Services. Its really cool to do such a job.

I am thinking to share the code, if anyone is interested.

I now fully understand the Abstract Classes, the relation to the Composite Model, and how to implement CSLA approach in the Business Logic and Web Service Layers.

Tarek.

ajj3085 replied on Wednesday, January 13, 2010

Hi,

I'd be curious to see the higher level solution you came up with.  Did you end up using abstracts and / or implementing some of those interfaces?

Andy

james phe replied on Wednesday, January 13, 2010

I'm very interested in your implement,please share your code to me.

my email is james_phe@126.com

Thanks!

larmister replied on Thursday, January 21, 2010

I too am interested in how you implemented your solution using CSLA approach.

tarekahf replied on Thursday, January 21, 2010

I am glad you are all interested.

I just finished Umbraco Level 1 Certification in the UK. I will post the details in within a couple of days.

Tarek.

tarekahf replied on Sunday, January 24, 2010

I have attached the class and the web service code I developed. Also, I added the code I used in MS Access 2003 to consume the web service. And here is a snapshot of MS Access:

Hope it will be of value to you.

 

Tarek.

Copyright (c) Marimer LLC