Properties distribution

Properties distribution

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


Gnan posted on Wednesday, February 07, 2007

Hi,

I'm new to CSLA.NET. It would be great if anyone could provide me a suggestion on creating the classes. Here is my scenario: I'm having an abstract class named "File". As per the File Type (or extension) I've derived classes namely ExcelFile, TxtFile, etc. The Root class "File" has some properties which is common to all the file types. Also, there are two file formats (or templates). As per the user choose the file template (one template having 3 columns and another having 5 columns and there is 2 similar columns remaining all are different). Now, one option is to have 3 + 3 (where 5 column - 2 common columns) properties in the root class "File" itself and the derived classes will set those properties as per the template choice. Other option could be having an abstract class "FileTemplate" where i would have two derived classes namely "FileTemplate1" and "FileTemplate2", wherein the "FileTemplate" has two common properties and the derived classes would override them and will have extra properties. Please suggest one or if there is some other better options, then please let me know.

Thanks in advance.

MSFollower

RockfordLhotka replied on Wednesday, February 07, 2007

The secret to success when using inheritance is to NOT focus on the properties you inherit, but rather to focus on the behaviors you inherit.

A property declaration (all ~12 lines of code) does not get you reuse. If all you want is a common set of properties, I recommend using an interface. That is far simpler to implement!!

But if your base class has behaviors then inheritance makes sense. In other words, if you have processing and/or rules that are common across all your File classes, then having a FileBase class with those methods is a good thing.

This is one of the hardest things to "get" around behavioral object design, because so many examples of inheritance focus on inheriting data (properties), rather than behavior (methods). But inheriting for data is wrong and should be avoided.

In other words, I recommend that you directly implement the "common" properties in all your File classes. If you want polymorphism, declare and implement an interface for that purpose.

However, if you have rules that apply to, say, the FileExtension property, then that rule method could very well be in a FileBase class so it is available to all the File classes.

robert_m replied on Wednesday, February 07, 2007

Hi !

I have recently read your CSLA 2.0 book (which I liked very much) and noticed that you strongly emphasize importance of focusing on centralizing behavior rather than eliminating data redundancy when creating object model. Which seems perfectly alright to me but...

 What's wrong with inheriting properties ? It's not like we can either inherit methods or inherit properties. Why do you think declaring and implementing an interface is a better approach than having a base class with common properties ? We might not get much code reuse if properties are simple (meaning no smart code in property getters and/or setters) but we will still get some.  Why write same things many times even if they are trivial ??

Thnx...

Robert

anyways, we plan to use CSLA for our next project Smile [:)]

RockfordLhotka replied on Wednesday, February 07, 2007

Inheriting properties is simply complex - primarily when it comes to persistence. And the result is unmaintainable code - or poor performance - your choice.

The reason is simple. Consider Product, with subclasses TaxableProduct and ServiceProduct. Product could have properties (and thus fields) for Id, Name, Price - these are common to all the products. TaxableProduct could add TaxRate, and ServiceProduct could add some sort of overtime price boost.

Already, with ServiceProduct, we see that Product needs to provide a virtual ActualPrice property, in addition to the simple Price property. So already we're altering Product to accomodate a subclass - which is a danger sign.

Then think about the simple act of retrieving a product from the database. You can't actually fetch a Product. But when you go to fetch a TaxableProduct how do you get the data? You want just one database query, so you need a SELECT statement that retrieves both the data for Product and for TaxableProduct (remember they have different fields).

Does TaxableProduct load the fields of Product? It could, they might be protected (another danger sign). Or it might call base.Fetch(dr), passing the datareader up to the base class so it can load itself. That's better - but still, TaxableProduct has to know all the fields Product needs - so there's no encapsulation here.

Remember that ServiceProduct needs to have similar (but not the same) fetch code. But it too needs to know the fields for Product.

So when Product adds a field, all its subclasses must be located and updated as well. This is a classic case of the "fragile base class".

The result is such tight coupling between the base class and the subclasses that they might as well be a single class. In fact maintainability would be increased if they were a single class, because you'd have less places to change things and keep them in sync.

An alternative to the fetch approach is to do two database calls per object. Let TaxableProduct load its fields, and have it call base.Fetch() so Product can do its own database call to load its fields. This is a performance issue, but at least it maintains some level of encapsulation and minimizes the fragile base class issue to some degree.

The point, in my mind, is that we're introducing all this complexity and fragility in an effort to reuse some template-based code. I've worked hard to make all property declarations look exactly the same, so you can create them with code-gen or snippets. Property declarations, to me, aren't real code, and they certainly aren't behavior that's desirable to reuse.

Yet you do need consistency for polymorphism. And this is where interfaces come into play.

In this model, define IProduct and implement it in TaxableProduct and ServiceProduct. Now the compiler helps you ensure that you have all the required properties, but you have none of the complexity of the fragile base class.

If you add a property to IProduct, the compiler helps you find the places it must be added - which takes very little time, thanks to snippets or code-gen.

Yes, there's still room for some error with this approach, but there's less chance overall, because the compiler is helping you, rather than potentially hiding important changes to a base class.

Bowman74 replied on Thursday, February 08, 2007

This discussion again, eh? 

Rocky, so here is my problem with focusing solely on behaviors.  In business objects behaviors almost always act on attribute data fetched from some data source or another.  If you say that you can't use shared attributes in a base class then I would argue that the vast majority of your shared behaviors can't end up in your base class either.  What you then end up with is next to no sub classing of business objects that act on data, instead you would be using interfaces for almost all cases. 

While that would work, it does not hold much interest for me.  I don't like the idea of re-coding behavior logic because I decide not to deal with any fetched attributes in base classes.  What I do do is your second option, my subclasses tell their base classes to fetch themselves/persist themselves.  While there is a performance hit, it is barely perceptible.  It is not like I am not updating collections of thousands of business objects at once where this would become a problem.  If someone is doing that then I would argue that they made an unfortunate design choice and maybe something like Flyweight was what they were looking for. 

Now if you really want to have your high performance solution where the subclasses save all the data (like your interface solution) so there is only one data call, and the compiler helps you in the case of attribute additions, and end up with shared business logic that deals with attribute data in a base class just make sure your base class exposes any required shared attributes as mustoverride properties.  Nothing will be hidden and the compiler will help you just as much as it would if you added a new public property to IProduct.  Your abstract base class shouldn't be any more fragile than your interface solution.  Pretty much works the same way as creating an interface in fact with the same issues, just with the addition of the ability to add behavioral code. 

Conceptually from a public interface point of view an abstract base class with all mustoverride properties is pretty much the same as an interface with properties.  It is just with one case you can add behavioral code and the other not so much.

Thanks,

Kevin

malloc1024 replied on Thursday, February 08, 2007

Inheritance does make your design more fragile because your subclasses become tightly-coupled to its base-class.  Any change to your base-class can have an adverse effect on its subclasses.  This is one of the reasons why you should favor composition and interfaces over inheritance.  Inheritance is useful when used correctly, but it is often overused and used incorrectly.


Here is a good article that explains the fragile base-class problem, why you should not inherit based on data and why you should favor interfaces over inheritance.  The article was written by Allen Holub, a well respected author who has written a good book on design patterns.

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html?page=1


Bowman74 replied on Friday, February 09, 2007

Malloc,

I'm afraid that really doesn't answer the mail for me. This argument has been around the block many times before.  Either solution you try will create tight coupling in one way or another.  Many of the design patterns themselves are about reducing the coupling in your application.  But all you can ever do is reduce it's impact.  All apps are tightly coupled in one way or another.  If you think your interfaces are immutable, I just reply, wait.  Those are tightly coupled too, try changing an external one after deployment and start playing the versioning game.  We, of course, can play semantic games over just what tight coupling is.

Rocky's concern around the compiler hiding changes with inheritance and helping you with interfaces is certainly valid but only one factor in making a decision.  As I stated using mustinherit properties would seem to answer his issue nicely while still allowing for the possibility of shared behaviors.  In that scenario the sub classes would still handle the persistence of the attributes.

But you are absolutely correct that inheritance is many times overused.  People jump on a band wagon and think one method is the answer to every problem.  A hammer should not be your only tool and you shouldn't view all problems as a nail.  To be honest outside of code generation I rarely use inheritance (partial classes don't give me some of features I need).  I rarely run into the fragile base class issue because outside the realm of code generation I rarely use it.  For polymorphic purposes I'm much more likely to use an interface.  But once again these are tools that should be in your shed and not discarded. 

If a particular problem calls for inheritance then that should be your solution.  If that includes some thought around persisted members then that should also be part of your decision making process.  You shouldn't force an interface to work when there may be a more appropriate solution because of an ideology.  Each decision you make has trade offs and if you think them through and are careful you can reduce the amount you are likely to get burned.  Sure some people don't and do get burned but you don't need OOP for that.

As far as Allen's article those arguments are nothing new.  As I stated we have been around the block with them many times before.  I place very little stock in appeals to authority and even less on absolutes. 

Thanks,

Kevin

ajj3085 replied on Friday, February 09, 2007

Bowman74:
I'm afraid that really doesn't answer the mail for me. This argument has been around the block many times before.  Either solution you try will create tight coupling in one way or another.  Many of the design patterns themselves are about reducing the coupling in your application.  But all you can ever do is reduce it's impact.


Um, that's the purpose of the patterns, to reduce the impact of changes.  Reducing the impact of changes reduces the chance that your change will break many other classes, meaning your code is more maintainable and accomodating of changes... and that's really the whole point of OOD / OOP. 

Bowman74:
All apps are tightly coupled in one way or another.  If you think your interfaces are immutable, I just reply, wait.  Those are tightly coupled too, try changing an external one after deployment and start playing the versioning game.  We, of course, can play semantic games over just what tight coupling is.


I think you're missing the point; with the inheritence approach, a change may cause bugs that you can ONLY find at runtime.  With interfaces, the change prevents compilation and you instantly know each class that needs to be updated.  The chance of a run-time only bug creeping in is much much lower in that case.

Bowman74:
Rocky's concern around the compiler hiding changes with inheritance and helping you with interfaces is certainly valid but only one factor in making a decision.  As I stated using mustinherit properties would seem to answer his issue nicely while still allowing for the possibility of shared behaviors.  In that scenario the sub classes would still handle the persistence of the attributes.

Your mustinherit properties don't solve anything.  The subclass implements them, but if you subclass that subclass you're back to square one again. 

Bowman74:
But you are absolutely correct that inheritance is many times overused.  People jump on a band wagon and think one method is the answer to every problem.  A hammer should not be your only tool and you shouldn't view all problems as a nail.  To be honest outside of code generation I rarely use inheritance (partial classes don't give me some of features I need).  I rarely run into the fragile base class issue because outside the realm of code generation I rarely use it.  For polymorphic purposes I'm much more likely to use an interface.  But once again these are tools that should be in your shed and not discarded.

No one is saying never to use inheritence.  It does have its place, but when you can use composition instead you usually end up with a bertter design.  Rocky was saying not to use inheritience based on what properties the super offers, but what behaviors the super offers.

Bowman74:
If a particular problem calls for inheritance then that should be your solution.  If that includes some thought around persisted members then that should also be part of your decision making process.  You shouldn't force an interface to work when there may be a more appropriate solution because of an ideology.  Each decision you make has trade offs and if you think them through and are careful you can reduce the amount you are likely to get burned.  Sure some people don't and do get burned but you don't need OOP for that.


In the example in this thread though, inheritience doesn't seem to fit very well, and that's because the decision to use inheritence is based on what data the super has, not what behaviors it has.  If basing your decision to inherit on data was valid, there would be no need for this thread at all, as there would not have been any difficulties resulting from that decision. 

Bowman74:
As far as Allen's article those arguments are nothing new.  As I stated we have been around the block with them many times before.  I place very little stock in appeals to authority and even less on absolutes.

So an old arguement automatically makes it invalid?  It seems to me these arguments have some weight behind them, becase again, here we are with a problem that is coming from basing inheritance on data instead of behavior. 

You discount the arguments because you think they are appeals to authority, but in doing so your dismissing the experience of those you deem an authority.   Also, I think the article is a little over the top, but the first paragraph states you should avoid inheritance whenever possible.  I'm not sure that's much of an absolute, and it really does seem to be a good suggestion. 

The GOF didn't come up with design patterns because they were bored; they did it because their experience had lead them to the conclusion that inheritance was overused and did have problems and a better way was needed.  So discount the experience of veterans at your own risk.

Bowman74 replied on Friday, February 09, 2007

<quote>
Um, that's the purpose of the patterns, to reduce the impact of changes.  Reducing the impact of changes reduces the chance that your change will break many other classes, meaning your code is more maintainable and accomodating of changes... and that's really the whole point of OOD / OOP. 
</quote>

Nice of you to point out that we just said the same thing.

<quote>
I think you're missing the point; with the inheritence approach, a change may cause bugs that you can ONLY find at runtime.  With interfaces, the change prevents compilation and you instantly know each class that needs to be updated.  The chance of a run-time only bug creeping in is much much lower in that case.
</quote>

Understood, but that's done with a price.  If all you need is polymorphism then interfaces are the perfect solution.  If you want shared behaviors they do nothing for you.  The genesis of this discussion was Rocky's statement that you should only inherit behaviors not persisted instance data.  My reply is that most behaviors act on instance data.  So if you think that inheritance shouldn't inherit persisted attribute data and most of your behaviors act on persisted attribute data then what are you to do? 

<quote>
Your mustinherit properties don't solve anything.  The subclass implements them, but if you subclass that subclass you're back to square one again. 
</quote>

If you are sub classing your business logic several layers deep you are asking for trouble.

<quote>
No one is saying never to use inheritence.  It does have its place, but when you can use composition instead you usually end up with a bertter design.  Rocky was saying not to use inheritience based on what properties the super offers, but what behaviors the super offers.
</quote>

Understood.  My point is that with business applications behavior almost always acts on persisted attribute data.  If you pull out the possibility of the first you are in many cases removing the possibility of the second.  Now you could make the argument for true loose coupling any instance data a method needs should be passed into it.  That would remove the problem of inheriting just behaviors. Conceptually I don't like it but it would make Rocky's plan work.  You could end up with the methods with a very large number of parameters and constantly changing parameter lists.

<quote>
In the example in this thread though, inheritience doesn't seem to fit very well, and that's because the decision to use inheritence is based on what data the super has, not what behaviors it has.  If basing your decision to inherit on data was valid, there would be no need for this thread at all, as there would not have been any difficulties resulting from that decision. 
</quote>

I'm sorry if I haven't made this clear.  My comments were directed particularly at the concept of never inheriting any attribute data and only behaviors that Rocky made.  I have made no comments on its appropriateness for the situation in this thread.

<quote>
So an old arguement automatically makes it invalid?  It seems to me these arguments have some weight behind them, becase again, here we are with a problem that is coming from basing inheritance on data instead of behavior.
</quote>

No, I don't like these arguments because they tend to be cyclical.  Everyone runs one way until the limitations of that approach become apparent.  Then they switch to the other, forgetting why they stopped using that in the first place.  Suddenly everyone remembers the problems with that approach.  Rinse and repeat.  This is not the first time we have been around this cycle.

<quote>
You discount the arguments because you think they are appeals to authority, but in doing so your dismissing the experience of those you deem an authority. 
</quote>

There is a difference between dismissing an argument that is an appeal to authority and dismissing what the authority has to say.  For example, "You should listen to Joe because he did this."  I don't place much stock in that type of argument.  I do, however, respond well to, "Joe said this because of these foo factors."  I'll certainly take a look at that.

You shouldn't listen to people's advice because just of their experience, you should judge their advice on why they say it's good advice.  There are a lot of people with a lot of experience that still give bad advice and people with little experience that give good advice.  I'm not saying that is the case here, only pointing out why appeals to authority are generally problematic on contentious issues.

<quote>
The GOF didn't come up with design patterns because they were bored; they did it because their experience had lead them to the conclusion that inheritance was overused and did have problems and a better way was needed.  So discount the experience of veterans at your own risk.
</quote>

A bit of a straw man don't you think?  If you can find anywhere where I stated that inheritance shouldn't be used with caution or that we should discount the experience of veterans I'll happily make a retraction. 

Thanks,

Kevin

ajj3085 replied on Friday, February 09, 2007

Kevin,

I had a longer post, but am replacing it with this one.

I think the stumbling point is that you interperated what Rocky said as not to inherit propeties.  I don't quite think that's what he meant. 

I think the the point was that the decision on whether or not you subclass shouldn't be made so that the subclass gets properties, but should be based on what behaviors your subclass will get.

In otherwords, you don't subclass because you want to make a class that has property X and Y, you subclass because it can Draw something.

Andy

Bowman74 replied on Friday, February 09, 2007

<quote>
I had a longer post, but am replacing it with this one.
</quote>

Replaced just in time too, I was about to reply to the old one. ;)

<quote>
I think the stumbling point is that you interperated what Rocky said as not to inherit propeties.  I don't quite think that's what he meant.
</quote>

But what he said easily could be taken that way; he has even said as much in this thread.  Hear me out and I'll try and explain my thought process (try not to get too scared).  Take a look at his first line in that post:

"Inheriting properties is simply complex - primarily when it comes to persistence. And the result is unmaintainable code - or poor performance - your choice."

He then spends quite a bit of time discussing those complexities and performance costs.  He nowhere states that while it generally has a lot of problems there may be some times when it is appropriate. 

Now role play yourself as a programmer new to OOP.  What are you going to take away from that post?  In my mind it is going to be something along the lines of "Inheriting persisted attributes makes unmaintainable code or results in poor performance, thus I should never do it."  Since most business behaviors act on attribute data that will lead directly to inheritance being pretty much discarded by those people. 

But I don't really want to debate how what someone said could be taken.  That is not nearly as interesting as actual technical issues nor really what I believe most of us are here for.

<quote>
In otherwords, you don't subclass because you want to make a class that has property X and Y, you subclass because it can Draw something.
</quote>

Trust me, we are in agreement here.  Outside of generated code I'd be surprised if I'm using inheritance in my business object designs any more than you are.  What I am afraid of is someone coming away from the discussion thinking that they shouldn't use inheritance because a potential base class has a persisted property X and Y even if it needs them to draw something.

Thanks,

Kevin

malloc1024 replied on Friday, February 09, 2007

If you read Rocky’s previous response (reply# 11883) to the one you are referring, it seems clear to me that he suggested you should design your object based on behavior not on data.  I don't think he meant that you can’t inherit properties.  It just meant that you should not base inheritance on data.  If you have no behavior, then you should use an interface like Rocky suggested.  I agree that his following response seems to contradict that a bit by suggesting you should never inherit properties.   I do see your point and now I am a little confused on what he meant.

RockfordLhotka replied on Friday, February 09, 2007

All I meant is that inheriting JUST TO GET PROPERTIES should be avoided. The costs of doing so are quite high, and it is very hard to imagine how you’d justify those costs through the “reuse” you theoretically achieve.

 

But if those properties come along with (or are required by) behavior, then the benefits of reuse might offset the fragility costs. (note the word “might” – this should be a conscious trade-off you are making)

 

Better, if you can structure your code to use composition instead of inheritance, then you can get the reuse of behavior without the fragility of inheritance. At that point, you’d have normalized the common behavior into a location where it can be used by what would have been your various subclasses. Now you have collaboration through composition, which is a more manageable form of reuse. And in this case you might STILL be tempted to use inheritance to “reuse” those common properties – and that would (typically) be a bad idea, because you are back at the first case where you are “reusing” the standard 12 lines of property declaration at the high cost of inheritance-based fragility.

 

Rocky

 

 

From: malloc1024 [mailto:cslanet@lhotka.net]
Sent: Friday, February 09, 2007 12:47 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Properties distribution

 

If you read Rocky’s previous response (reply# 11883) to the one you are referring, it seems clear to me that he suggested you should design your object based on behavior not on data.  I don't think this means that you can’t inherit properties.  It just means that you should not based inheritance on data.  If you have no behavior, then you should use an interface like Rocky suggested.  I agree that his following response seems to contradict that a bit by suggesting you should never inherit properties.   I do see your point and now I am a little confused on what he meant.



malloc1024 replied on Friday, February 09, 2007

That’s what I though you meant and I agree completely.  Thanks for clearing that up.

ajj3085 replied on Friday, February 09, 2007

Bowman74:
Replaced just in time too, I was about to reply to the old one. ;)


Whew. Smile [:)]

Bowman74:
But what he said easily could be taken that way; he has even said as much in this thread.  Hear me out and I'll try and explain my thought process (try not to get too scared).  Take a look at his first line in that post:

"Inheriting properties is simply complex - primarily when it comes to persistence. And the result is unmaintainable code - or poor performance - your choice."

<snip>

Ok, I guess I can see where you are coming from.  I never thought to take it that way, perhaps because I've read Rocky post about this subject many times before.  Fair enough.

Bowman74:
But I don't really want to debate how what someone said could be taken.  That is not nearly as interesting as actual technical issues nor really what I believe most of us are here for.

This is true, but everyone in a discussion needs to be on the same page to discuss those issues.  I know I've personally come to the wrong technical conclusion because there was a misunderstanding between myself and what the other party was trying to tell me about the issue.

Bowman74:
Trust me, we are in agreement here.  Outside of generated code I'd be surprised if I'm using inheritance in my business object designs any more than you are.  What I am afraid of is someone coming away from the discussion thinking that they shouldn't use inheritance because a potential base class has a persisted property X and Y even if it needs them to draw something.


Yes, I believe we are, and now that I understand where you are coming from I can see why you expressed concern.  Sometimes I forget that you start off 'doing things by the book' as it were.

Andy

Bowman74 replied on Friday, February 09, 2007

<quote>
This is true, but everyone in a discussion needs to be on the same page to discuss those issues.  I know I've personally come to the wrong technical conclusion because there was a misunderstanding between myself and what the other party was trying to tell me about the issue.
</quote>

Seems to happen quite a bit.  Maybe I'm just old, crotchety and pedantic but I don't think anyone will have any confusion now.  ;)

Thanks,

Kevin

RockfordLhotka replied on Friday, February 09, 2007

Kevin,

 

If you hadn’t decided to go be a hermit, lurking deep in the winding labyrinth of roads that is rural Connecticut, you might be less crotchety :) 

 

The pedantic thing, though, I think you were probably born with, and I’m afraid getting old happens to all of us eventually ;)

 

(for those that don’t know, Kevin and I go waaay back <vbg>)

 

Rocky

 

 

Seems to happen quite a bit.  Maybe I'm just old, crotchety and pedantic but I don't think anyone will have any confusion now.  ;)

Bowman74 replied on Friday, February 09, 2007

<quote>
If you hadn’t decided to go be a hermit, lurking deep in the winding labyrinth of roads that is rural Connecticut, you might be less crotchety :) 
</quote>

Hey I needed a barn to store my cars; the city three car garage just wasn't cutting it.  Besides that winding labyrinth of roads is mucho fun in the 914 (not that I encourage traveling at unsafe speeds).

Thanks,

Kevin

Kosintrouble replied on Friday, February 16, 2007

I am curious if this is worth doing inheritance or if I should just create two different classes.

Our company deems that everyone is a BusinessAssociate, everyone is stored in the same table.  So I was planning on creating a BusinessAssociate:BusinessBase which will Save, Retrieve ect from the database.  

But we also have a form online which allows subcontractors and suppliers to submit thier company as potential BusinessAssociates.  In our case, we dont want to put them into our BusinessAssociate table at this point, we only want them to submit their information for review by one of our "people" who then after making changes, adding new information we add them as a BusinessAssociate.

So I also need to create a BidListAssociate object which I was thinking would inherit the BusinessAssociate but will have two possible loads and saves.  One save going to a holding table, one load from the holding table.  Then when one of our "people" review the BidListAssociate, add the new information needed to become a BusinessAssociate it then calls the Save of the BusinessAssociate.

But I am wondering if inheritance is worth it or not, there is some shared behavior between the two, but I am not sure if this is a decent example or time to use inheritance.  I am almost leaning to have two seperate classes, and just have the BidListAssociate call a static newBusinessAssociate on the BusinessAssociate object instead of using inheritance.

Anyone have any suggestions or comments.  After writing this out, I believe I have answered my own questions, I am leaning towards two seperate objects without inheritance.

Kos


*Edit
Hmm after further thought, yes inheritance is a waste of resources.  There is not shared behavior between the two, only shared properties.  So ignore my above post, I am using two different classes with a shared interface.

malloc1024 replied on Friday, February 09, 2007

Bowman74,

 

Ajj3085 provided a good response and pretty much took the words out of my mouth; however, I must respond.  I happen to agree with most of which you said.  Yes, using interfaces creates coupling, but the coupling is not a tight when using inheritance.  I idea is to reduce coupling.  I am not saying that you should never use inheritance, but it must be used responsibly and be based on behavior.  Yes, the article is extreme.  I don’t follow what the article suggests to that extreme; however, I believe it is a good idea to listen to the ideas from authority to see if it works for you.  This doesn’t mean that they are correct and you should blindly follow the advice.  It means take the advice, think about it and see if it works for you.

Bowman74 replied on Friday, February 09, 2007

Fair Enough.  I sometimes like to stir the pot a little when I think it needs to be stirred.  The thing that caught my eye here was the probability of younger programmers reading Rocky's post and coming to the conclusion that any inheritance that contains persisted attribute members is verboten.  Then they realize that most business behaviors work on persisted attributes and end up using interfaces exclusively. 

I know that's not what Rocky intended but I have seen it happen time and time again where people (I don't mean to solely pick on younger programmers here) will take a good practice guideline out to the extreme of being a cast in stone edict.  It is particularly problematic when someone with a high level of respect like Rocky mentions a good practice guideline.

So my intent here is to point out that hey maybe sometimes it is OK when the situation really calls for it.  That is what I was trying to get at when I stated that your only tool shouldn't be a hammer and you shouldn't view every problem as a nail.  In the end I try to look at every problem as pragmatically as possible.

Thanks,

Kevin

RockfordLhotka replied on Friday, February 09, 2007

I do use absolute statements for shock value - and should perhaps be more careful about that.

But the fact is that inheriting to get properties/fields is a very expensive thing to do, and it should be avoided unless you can justify paying that high cost.

And the fact is that most OO classes still use stupid examples like Mammal<-Canine<-Dog or Person<-Contact<-Employee - which are all about inheriting data, not behavior. So people are trained to do exactly the wrong thing, and they aren't educated about the high cost they'll pay in real applications if they do what they were trained to do.

Very sad.

If a little shock value can jump-start a conversation that reveals the true nature of the costs and benefits, then I feel I've done my job Big Smile [:D]

Bowman74 replied on Friday, February 09, 2007

<quote>
If a little shock value can jump-start a conversation that reveals the true nature of the costs and benefits, then I feel I've done my job
</quote>

Well seems to have worked in this case.  ;)

So is that Minnesota weather getting to you yet?  You guys need to take a vacation somewhere warmer.

Thanks,

Kevin

ajj3085 replied on Friday, February 09, 2007

RockfordLhotka:
And the fact is that most OO classes still use stupid examples like Mammal<-Canine<-Dog or Person<-Contact<-Employee - which are all about inheriting data, not behavior. So people are trained to do exactly the wrong thing, and they aren't educated about the high cost they'll pay in real applications if they do what they were trained to do.

Very sad.

Rocky, that's EXACTLY how my Comp Sci. courses were taught when I was at college, and thus I was paying a high cost at first (well, not at first, since I didn't get to do alot of OOP until .Net came out).

Since I've switched my focus, I think my programs have gotten much easier to maintain and much more reliable for my users, so I want to thank you for getting me onto the right path.

pelinville replied on Friday, February 09, 2007

I love these arguments because both sides are correct! 

 

Well, correct as long as they are aware and accept the limitations of their approach.

 

For example I would venture to say we all limit ourselves automatically by using Properties in the first place.  David West suggested simply using a collection to store the properties (ie data) in a class. I suggest you try this.  It really makes clearer this debate. I think it also makes the classes much easier to design and understand.

 

Most people would look at a member of type ArrayList simply called "Data" and think "Wow, that is so usefull, I think I will inherit from that!".  Now you might need that data but seeing as it is just a collection I think you would be more inclined to use composition.

 

Alas I don't do it because I like the intellisense Properties provide and because databinding is reliant on Properties. So I give up a very good design idea for the sake of convenience.

 

It is amazing how the subtle things have such a huge impact.

 

Such is life.

Copyright (c) Marimer LLC