My 2 cents on new CSLA

Injecting NHibernate Repository into CSLA ObjectFactory is much easier than doing this in CSLA BO.

AutoMapper is very hard to use to pass data from NHibernate model to CSLA BO due to many flag setting in DataPortal methods.

Aggregate root pattern is missing from CSLA, processing child list is completely different in ORM world. CSLA is still following the table-BO one-to-one style.

CSLA sample app has demo code of using ORM like EF or Linq2Sql, but MODEL in those ORM is just used as data structure. It’s fair to keep CSLA BO business rich, but why use ORM for? Just to connect to database?

The way CSLA using WCF is weird, a real world SOA app should not have a contract with just CRUD operation defined in it.

Exception handling is different, while it definitely makes sense for UI/F5 developers, it drove my nuts when looking for exception when things don’t work, exception suppose to bubble up all the way, not hidden in control somewhere.

N-level undo is interesting. Again, who is using it?

Most wonderful features in CSLA:

  • Very rich and thoughtful UI controls, like cslaActionExtender, error provider and the usage of datasource on WinForms/WPF. Drag and drop, property setting, etc… I really miss it, especially when doing UI tasks.
  • Broad UI/OS support, even covers iOS with monoTouch on hand. Using it as a rich screen DTO in app isn’t a bad idea. For data access, stick with NHibernate.

My demo app of how to use CSLA with NHbernate. Value Object pattern is used to process child line item list, flag comparison when updating list is possible, but not worth if lint_item_id doesn’t matter.

Advertisements

IRepository

I was trying to write a similar post as Mike did. Because I’m currently using LINQ DynamicQuery, so my IRepository looks like this:


    public interface IDynamicQueryable<T> 
    {
        IEnumerable<T> FindAllByCriteria(string criteria);
        IEnumerable<T> FindAllByCriteria(Func<T, bool> criteria);
    }

    // Most simple repository implement this one. 
    public interface IRepository<T>  
    {         
              T FindById(int id);
              T Insert(T data);
              T Update(T newData, T oldData);
              void Delete(T data);
     }

    // Some fancy entities implement this one instead. 
    public interface IDynamicQueryableRepository<T> : IDynamicQueryable<T>, IRepository<T>{}

I spilt the dynamic part from IRepository, just trying not annoy developer create too many never used FindAll() method in their entities. And also I think this is closer to Interface segregation Principle (not really sure). But this indeed gave me flexibility to control the function diversity on different entities, e.g., some entities might never need list-editing/retrieval function.

I do like this LinqDynamicQuery very much and don’t mind to make my repository coupled to Func<T, bool> (what’s this indeed? And what’ the difference than Expression<Func<T, bool>> shown in Fluent NHibernate’s IRepository?)  Here is a good example, if no DynamicQuery:


    public interface ICityRepository : IDynamicQueryableRepository<CityBO>
    {
        IEnumerable<CityBO> FindAllByProvinceId(int provinceId);
        IEnumerable<CityBO> FindAllByCountryId(int countryId);
    }

By using DynamicQuery,


    public class CityListFactory : BusinessListBaseServerFactory<CityBOCollection, CityBO, ICityRepository>, ICityListFactory
    {
        public CityBOCollection Fetch(CountryBO parent)
        {
            // Don't need FindAllByCountryId() any more.
            return Fetch(x => x.CountryId == parent.CountryId);
        }
        public CityBOCollection Fetch(ProvinceBO parent)
        {
            return Fetch(x => x.ProvinceId == parent.ProvinceId);
        }
    }

Extract Validation rules out from CSLA BO

The first priciple of SOLID rules is SRP, it would be nice if we can extract validataion rules out from BO. And I couldn’t belive it was so easy to do implement.

The classic way:

private void AddCustomRules()
        {
            // Custom validation
            ValidationRules.AddRule<EmailBO>(EmailRoleValidValues<EmailBO>, EmailRoleProperty, 1);

        }

The revised version:

// EmailBO
   protected override void AddBusinessRules()
   {
      EmailRuleFactory.CreateOn(ValidationRules);
   }

public class EmailRuleFactory
{
   public static void CreateOn(ValidationRules rules)
   {
      rules.AddRule<EmailBO>(EmailRoleValidValues<EmailBO>, "EmailRole", 1);
   }

   private static bool EmailRoleValidValues<T>(T target, Csla.Validation.RuleArgs e) where T : EmailBO
   {...}
 

All the validation tests still passed!

Note: I had to expose protect Parent field from BusinessBase. And PropertyInfo is not available either, fortunately ValidationRules.AddRule() can still take string literal.

This might also be helpful is user wants to switch between different sets of valudation rule based on certain instance value.

We could do the same thing to AuthorizationRules which will be more meaningful. Security should definitely be built as a separated common service, instead of building into Domain Object.

Enable DataGrid Header-Clicking Sorting

Most search results  said the header-clicking-sorting feature comes internally with dotNet Framework. But for some reason I just could make this happen, until I read an old article on MSDN about custom data binding, which kept mentioning about Rocky. And the reason is very simple, programmer should bind a SortableBindingList<T> to dataGrid to make use of those internal sorting features.

Csla.EditableRootList has to be wrapped in Csla.SortedBindingList then to bind to dataGrid.

SortedBindingList has most of the functions embeded including: Add, Insert, Delete, but not Save. I need to convert SortedBingList back to EditableRootList by using it’s internal property: SourceList.

Rocky didn’t make SortedBindingList serializable for some reason. Anyway, the UI code is very simple:


        public CountryBOCollection List
        {
            get
            {
                return (CountryBOCollection)
                  ((SortedBindingList)this.countryBOCollectionBindingSource.DataSource)
                      .SourceList;
            }
            set
            {
                this.countryBOCollectionBindingSource.DataSource
                    = new Csla.SortedBindingList(value);
            }
        }

I tried to move this type conversion to presenter, then I realized I need two lists in presenter: one sortable list for displaying and editing, one savable list just for saving. Presenter code is polluted just by this limitation in SortedBindingList. It looks much better by leaving type conversion still in UI, and who knows someday this limitation might go away?

Csla.ObjectFactory III – What’s wrong with UpdateChildren()

Derick Bailey’s post about Csla vs DDD brought out a simple but very interesting question :

Which one is correct?
Person.AddCertificate(), or Person.Certificates.Add()?

Almost the same? But it turns out the 2nd one is NOT “correct”, at least, not in DDD way.

That’s the problem in CSLA. Always thinking in table, data-centric design/dev. An extreme example, FieldManager.UpdateChildren().

How about save? Person.UpdateEmail() or Person.Email.Update(). [Email.Child_Update() in classic CSLA way.]

CSLA is not an ORM tool/framework, but BO carries all the dirty flags, in fact it’s DataPortal doing all the relationship maintenance work. RootBO.Save() is handling all the updates of its children, through FieldManager.UpdateChildren() jumping into each childBO’s internal private Child_XYZ methods. Handy, “clean”, but it’s not “correct”.This is the exactly same problem when I was trying to switch to the new Csla.ObjectFactory way: I had to keep an extra set of Protal methods in child BO, those child portal method,  to work with Parent BO’s FieldManager.UpdateChildren() method.

What if we ignore FieldManager completely? Just let Person.Save() directly call DataPortal.Update<EmailBO>(person.Email) ? Or DataPortal.Update<TelephoneBOCollection>(person.Telephones) ? Then child BO can still use  the general AbstractFactory which only have root level CRUD methods.

The direction Rocky made in ObjectFactory looks right, child CRUD should be done by root BO.  The thing is, it’s not backwards completable. It’s trying to retire FieldManager.UpdateChildren()!

The update route should be RootBO.Save -> Root Factory.Update -> Child Factory.Update, don’t call child BO’s internal Child_XYZ anymore.

Currently for legacy reason I still keep the following code in my ChildBO to bump calls from parent to child’s own factory, those UpdateChildren() in root BO can be alive for awhile, until I move them to root factory, which should be the newly strongly-typed customized UpdateChildren().


private void Child_DeleteSelf(){ DataPortal.Delete(this);}

private void Child_Insert(IParent parent){
     this.ParentId = parent.Id;
     DataPortal.Update(this);
}

private void Child_Update(){
     var newBO = DataPortal.Update(this);
     DataMapper.Map(newBO, this);
}

It might just looks like a wrapper trick, but those DataPortal calls are actually in Factory class now which indeed is in an external true service layer.

In my app, it’s one AbstractFactory for all BOs, both root and child.

I do have a problem now, where should I put transaction scope attribute? It shouldn’t be a big deal, possible solutions:

  1. Create some extra methods in factory not in transaction Scope dedicated for child methods,
  2. Unit of Work pattern?

Look back Ryan’s ProjectTrackerHybrid code, all the child propertis are not registered! Which means they are not in fieldmanager at all. It’s ORM’s job to handle the realationship UpSet (Update/Insert).

Csla.ObjectFactory Part II – Difficulties on Child BO

I was wondering  why CslaFactory only needs to implement CRUD, no child methods at all. Other developers post the  same question on forum.

Rocky’s answer made sense, it your own Facotory’s responsibility to handle all those relationship. My specific problem on this is, FiledManager.UpdateChildren() is not available any more.

First, the FieldManager property in BO is protected, this can be fixed by adding new method in our BaseBO to make it public. The root BO changed to CslaFactory then. But, next challenge is, this UpdateChild is not going through DataPortalSelector->DataPortal_XYZ route, it still uses Reflection to look up the ‘Child_XYZ” method right in your child BO, not in CslaFactory class at all!

You have to manage your own update route by looping through all the children from your root BO! Forget the powerful FieldManager.UpdateChildren().

Relationship is built in DAL. ?? When start using DTO, I know it is the dead weakness. The word around is pulling relationship up to Csla BO and rely on those magic UpdateChildren methods. Now, updateChildren is gone, I have to create a real business explicit UpdateChildren.

    public class AbstractObjectFactory : ObjectFactory, IBusinessBaseServerFactory
        where BO : MyBusinessBase
        where TRepository : IRepository
        where DTO : class, new()
    {
        protected IRepository _repository = StructureMap.ObjectFactory.GetInstance();

        public virtual BO NewBO()
        {
            return (BO)Activator.CreateInstance(typeof(BO), true);
            //            return new BO();
        }

        public virtual void InsertChildren(BO bo){}
        public virtual void UpdateChildren(BO bo){}
        public virtual void DeleteChildren(BO bo){}

        public virtual BO Create()
        {
            var obj = NewBO();
            MarkNew(obj);
            obj.GetValidationRules().CheckRules();
            return obj;
        }

        public virtual BO Insert(BO bo)
        {
            var data = _repository.Insert(bo.BuildDTO());
            if (data == null) throw new DataException(“Repository Insert return null.”);
            bo.LoadFromDTO(data);

            InsertChildren(bo);
            // FieldManagar().UpdateChildren(bo) is not through CslaFactory.
//            bo.GetFieldManagar().UpdateChildren(bo);

            return bo;
        }

    public class StakeholderFactory : AbstractObjectFactory
        , IStakeholderFactory
    {
        public override void InsertChildren(StakeholderBO bo)
        {
            // Update Alias Name Child
            var factory = new StakeholderAliasNameFactory();
            for (int i = 0; i < bo.AliasNames.Count; i++)             {                 bo.AliasNames[i] = factory.Insert(bo.AliasNames[i]);             }         } [/sourcecode] This looks weird. And my solution of mocking Parent for testing update Child is useless then, because that assume root BO is calling FiledManager.UpdateChildren. One solution is to  re-write those update children code into my CslaFactory class. More coding, does it look more clear? I’m not sure. One of my root BO has 7+ children, I don’t think it’s worth to move.

Another quick dirty fix might be, still leave those Child_XYZ methods in Child BO for legacy purpose, inside put DataPortal_XYZ to redirect call to CslaFactory. This solution can keep parent update code same as before, still using UpdateChildren(), also the Child BO will look more like a switchable BO.

Enough, now I fully understand Ryan’s statement: Csla is great, but we need relationship.

Look how Ruby and NH dealing with relationship: has_many, belongs_to. Simple and clear.

Csla.ObjectFactory

This is  a new feature from Csla 3.6, which is trying to make Csla more TDD friendly.

Benefits:

DataPortal_XYZ methods can be moved into your own ObjectFactory class, BO will look a little bit thinner. Yes, you can now make BO contructor to be public, ( in standard csla way BO’s ctor should be private), if you are tired of using Activator.CreateInstance.

Because now you have full control to this ObjectFactory, and this class is not static, you can mock it when unit-testing UI/Presenter. But, the default usage of ObjectFactory doesn’t support Interface. Fortunately,  Rocky allow you to create your own FactoryLoader, by setting it into your app.conifg to redirect:

<appSettings>
<add key=”CslaObjectFactoryLoader” value=”YourNameSpace.YourFactoryLoader, YourAssembly” />

Ryan Kelley is using this tech to create his GenericFactoryLoader in his ProjectTrackerHybrid demo.

We have lots of Stored Procedures to deal with, so create a base AbstactObjectFactory is very hard. So I changed Ryan’s GenericFactoryLoader to make it not taking generic interface.

Here is what I tried:


        public virtual Type GetFactoryType(string factoryConnectionString)
        {
            if (factoryConnectionString == null)
                throw new ArgumentNullException("factoryConnectionString");

            parser.Parse(factoryConnectionString);

            var factoryTypeName = parser.FactoryType;

            // parser doesn't work , use csla default ObjectFactoryLoader
            if (string.IsNullOrEmpty(factoryTypeName))
                return new ObjectFactoryLoader().GetFactoryType(factoryConnectionString);

            return Type.GetType(factoryTypeName);
        }

        public virtual object GetFactory(string factoryName)
        {
            var factoryType = GetFactoryType(factoryName);
            if (factoryType.IsInterface)
                return StructureMap.ObjectFactory.GetInstance(factoryType);

            return new ObjectFactoryLoader().GetFactory(factoryName);

        }

[CslaFactory("Factory Type=MyFactory.ICityFactory")]
// Classic way to declare ObjectFactory
//    [CslaFactory("MyFactory.CityFactory, MyFactory")]
[Serializable()]
public class CityBO :BusinessBase<CityBO>
{...}