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 :)
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…
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