how to deal with large amounts of similar business objects

how to deal with large amounts of similar business objects

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


BlueScreenISU posted on Wednesday, March 07, 2012

Hello,

we are building an application with CSLA 4.1.0.0.

Our application is using very similar business objects, which use the same behavior and data to represent our use cases. There are like 150 of those objects.

We are looking for a way to solve this problem with CSLA to reuse the data and behavior. We do not like to reimplement this exact same code in all of those classes.

We really do want to couple the 150 objects to the same data/behavior. Of course every object implements additional own data/behavior.

Our question is: How to create such a scenario with CSLA?

Blue

Marjon1 replied on Wednesday, March 07, 2012

The real reason to avoid doing this is because if at some point in the future 100 of the objects need a similar behavior and the other 50 don't then it can make it very difficult to implement. However, hopefully the psudeo-code below will at least guide in the right direction. The use of the interface is really important, and I would not recommend doing without it. If at any point you want to use the data / behaviors in a common way without having to know about which type of object it is specifically; trying to use generics to do this, just doesn't work.

Please forgive any obvious mistakes, am writing this quickly before going to bed and will edit the post in the morning once in the office and can check it out in more detail.

-----------------------

Public Class BaseClass(Of T as BaseClass)

   Inherits BusinessBase(Of  T)
   Implements IBaseClass 

'Declare properties common to all, should be in the interface

'Declare methods common to all, should be in the interface

'Depending on the data access model you use, you may need some methods that are always called in the specialized classes to do fetch, insert, update, etc depending on your needs. We have used previously OnCreate(), OnFetch(), etc..... or you can also just ensure that DataPortal_XYZ signatures match and 'always call Mybase.DataPortal_XYZ in the specialized class.

End Class


Public Class SpecializedClass
    Inherits BusinessBase(Of SpecializedClass)

 End Class

--------------------------------

StefanCop replied on Wednesday, March 07, 2012

We generate most of the business objects.  Some model (an xml in our case) defined the stereotype and special features for every b.o.

What I have learned (and I hope I understood it right) is that the b.o. mainly "code" the object graph and properties, fetching/updating and so on,
whereas the business logic should be separated in business rules (validation and calculation), such that this logic can be reused across several object graphs.
This requires some interfaces the business rule can "dock".

For generation, we started with CodeSmith and their CSLA templates. Core of the design and some good ideas is still persent, but we had to move away from the database centric approach to a more model based one (the xml I mentioned earlier). But our BOs and tables/views are different.

BlueScreenISU replied on Thursday, March 08, 2012

Hello again,

@Marjon1: This‘s a good idea. We have also tried it. What about static methods? They cannot be declared in interface, but must be accessed in UI.

Furthermore we were able to move the similar dataportal methods in the base class by adding generics to the base class.

here is a code example:

public partial class ContainerEdit<T, TK, TKk, TKkk> : BusinessBase<T>, IContainerEdit

        where T : ContainerEdit<T, TK, TKk, TKkk>

        where TK : ContainerEditText<TK>

        where TKk : DomainObject

        where TKkk : AbstractCoreMapper<T, TKk>, new()

    {

        public static readonly PropertyInfo<ContainerEditTextList<TK>> ElementEditTextListProperty = RegisterProperty<ContainerEditTextList<TK>>(c => c.ElementEditTextList);

        public ContainerEditTextList<TK> ElementEditTextList

        {

            get { return GetProperty(ElementEditTextListProperty.PropertyInfo); }

            set { SetProperty(ElementEditTextListProperty.PropertyInfo, value); }

        }

 

 

        protected override void DataPortal_Create()

        {

            using (BypassPropertyChecks)

            {

                this.ID = AbstractDAOFactory.Instance().InstantiateDAO<TKk>().GenerateID();

                this.ElementEditTextList = DataPortal.Fetch<ContainerEditTextList<TK>>(this.ID);

            }

 

            base.DataPortal_Create();

        }

private void DataPortal_Fetch(long id)

        {

            using (BypassPropertyChecks)

            {

                IAbstractDAO<TKk> dao = AbstractDAOFactory.Instance().InstantiateDAO<TKk>();

                dao.BeginChanges();

                <...>

                TKk domainObj = dao.Load(id);

                if (domainObj != null)

                {

                    using (TKkk mapper = new TKkk())

                    {

                        mapper.Map(domainObj, (T) this);

                        this.ElementEditTextList = DataPortal.Fetch<ContainerEditTextList<TK>>(this.ID);

                  }

                }

 

                dao.CommitChanges();

            }

        }

}

example of a concrete business class:

public ProcessEdit : ContainerEdit<ProcessEdit, ProcessEditText, Process, ProcessMapper>{...}

 

we are aware that it is unusal to work with so many parameters, but we were forced to do it like that, because our business objects have to work with other business objects.

@Stefan cop: thanks for your answer, but we think our business logic can not be done with CSLA rules. We also discussed code generation, but we are trying to avoid it. This may be our last option :)

Copyright (c) Marimer LLC