Proper way to inherit from generic base class

Proper way to inherit from generic base class

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


miker55_2 posted on Friday, October 30, 2009

I'm trying to make a ReadOnlyListBase collection in CSLA 3.7 for Silverlight and although I have it working, I'm not sure if I am declaring things property.  I was using the ProductList example from the video series, but I want to expand on that by pushing the property declaration up to a generic base class.

Can someone with a higher pay grade than me please tell me if I am doing this correctly?

[Serializable]
public abstract class cmpQryCustomersBaseBOC<T, C> : ReadOnlyListBase<T, C>
  where T : cmpQryCustomersBaseBOC<T, C>
  where C : cmpQryCustomersBaseBO
{
}

[Serializable]
public abstract class cmpQryCustomersBaseBO : ReadOnlyBase<cmpQryCustomersBaseBO>
{

  protected static PropertyInfo<string> custnameProperty = RegisterProperty<string>(c => c.custname);
  public virtual string custname
  {
    get { return GetProperty(custnameProperty); }
  }
}

[Serializable()]
public partial class cmpQryCustomersBOC : cmpQryCustomersBaseBOC<cmpQryCustomersBOC, cmpQryCustomersBO>
{
}

[Serializable]
public partial class cmpQryCustomersBO : cmpQryCustomersBaseBO
{
}

TIA!

Mike


RockfordLhotka replied on Friday, October 30, 2009

Generally speaking, you should avoid using inheritance to gain properties. Declaring a property in a base class complicates the heck out of your app - specifically data access - and is usually not worth it.

In my view property declarations are not code, so trying to reuse a property declaration is a red herring. Totally counter-productive, because the result is reuse of code that took maybe 3 seconds to write, and the addition of complexity and coupling that will almost certainly waste hours of support time over the life of the application.

Using a base class to implement common rule methods is reasonably acceptible. But even there it is better to favor composition (collaboration) over inheritance. Again, this is because inheritance is one of the most tightly coupled relationships available between classes, and coupling is the ultimate evil in software. Therefore most inheritance triggers evil.

Of course it is Halloween, so if you are going to bring evil into your app, now's the time :)

RockfordLhotka replied on Friday, October 30, 2009

Well, where the trouble comes in is when you need to load one set of data into two different logical types.

 

This has been discussed a few times before, but consider the classic case of a Product that has DomesticProduct and InternationProduct subclasses. These two subclasses share most of the same properties, so you put them in the base class.

 

Then consider your data access code. The data portal will be creating and retrieving the subclass type, not the base class. But you don’t want coupling, so what do you do?

 

Well, you hit the database twice to get the data, once to get the properties defined by the subclass and again to get the properties defined by the base class.

 

OR

 

You make the subclass know exactly which fields are necessary for the base class to load its data. Now the base class doesn’t do its own data access – that’s all handled by the subclasses. Add a field to the base class, and you must remember to update the DAL code for all the subclasses, or they won’t provide the base class with the required values.

 

It is a total mess.

 

I’m not saying that you should use collaboration to store property values either, as that’d lead to the same problem. I’m saying you shouldn’t view properties as “meaningful code”. If an object needs data to do its job, it should have that data itself – simple and clean.

 

But if it uses logic/behaviors that are common with other objects, then those behaviors should be normalized into a separate class so the behaviors can be reused. In CSLA this is most notably rule methods, and occasionally algorithmic methods outside of rule methods.

 

In other words, centralize meaningful behavior and try to reuse that (through collaboration, or if you must, through inheritance), but don’t try to reuse property declarations because they aren’t meaningful code – not when you can stamp them out in just a couple seconds using a snippet…

miker55_2 replied on Monday, November 02, 2009

Thanks to both of you guys for all of the input. Actually, the only reason I wanted to make it a base class was so that I would have the option of overriding the properties if I ever needed to. I also wanted to have an AddBusinessRules method in the base class (which gets constantly re-generated by a code generator), and then be able to override that method in a non generated source code file where we make our custom changes.

I used that method quite successfully in a WinForms project with Csla 2.6, but Silverlight seems to be more challenging. I'll look into doing what I need without the base class.

Thanks,

Mike

Kevin Fairclough replied on Wednesday, November 04, 2009

So what your saying is that I shouldn't be doing the following (which I am Sad [:(] ):

public abstract class Entity<T> : BusinessBase<T>
 where T : BusinessBase<T>
{
 cslaprop Id
 cslaprop Version
 cslaprop CreatedOn
 cslaprop CreatedBy
 cslaprop ModifiedOn
 cslaprop ModifiedBy 

 ...other stuff...
}

public class Item : Entity<Item>
{
 ...stuff...
}

I should be creating snippets for these property blocks and effectively copy/paste them into every class?

Kevin

RockfordLhotka replied on Wednesday, November 04, 2009

I'm a pragmatic person. If you are declaring properties in a base class and you are happy with how that is working for you, then be happy.

But there are some very real drawbacks to doing this, mostly around persistence as I noted earlier, and that can cause maintenance issues over time as you add fields to the base class and forget to load them from one of your subclasses - because finding where to update the data access code is a manual search-and-fix model, which is always error-prone.

So yes, I personally would put the property declarations into each class. If I want the classes to be polymorphic, I'd either define abstract property declarations on the base class or use an interface - and since the base class is generic the only real option is to use an interface.

What I would put into the base class are common rule implementations. If there are rules around some of these properties that are unique to this family of object types, I'd implement them in the base class so I can easily associate the rules with the properties in each subclass.

Copyright (c) Marimer LLC