aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes Inheritance/ Code reuse - opinions please Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Inheritance/ Code reuse - opinions please" Watch "Inheritance/ Code reuse - opinions please" New topic
Author

Inheritance/ Code reuse - opinions please

Graham VMead
Ranch Hand

Joined: Sep 22, 2003
Posts: 154
Hi I wonder if you guys could comment on a problem I always seem to encounter irrespective of patterns. It seems to be centred around inheritence/partial inheritence and the urge for code reuse.

I start off with a business problem which implies say 2 classes which are of type Account, Current Account and Deposit Account. They share certain logical requirements so I end up with

An abstract Account class which implements the shared logic as concrete methods and the sub class specifics are listed as abstract methods.

The sub classes implement the abstract methods in there own specific way.

Everything is fine for a bit until lo and behold along comes another type of account OverSeas Account which shares say 80% of the logic and hence inherited methods from the abstract class.

Then you seem to have a choice you can
1) Inherit the new account from the abstract class and stub out the non-required methods.
2) Introduce a new abstract subclass for the original sub classes which implements the methods only they need. The new account doesn't subclass this.
3) I have even seen cases where the business logic in the abstract class has condition points in it. I.e areYouOverseas() which say the Overseas account would implement as true the others as false.

The along comes another account which again has 80% of the logic in the abstract class but not the same as the Overseas account type... aaargh!!!

1) seems to mean the more subclasses of the abstract class there are the more stubbing out and rework is involved.
2) Seems to cause large inheritence trees and you often end up where siblings replicate certain logic because they can't inherit (the tree is too deep).
3) Just seems awful!

I know you can have say strategy patterns which don't use inheritence in the same way as template patterns but you still have the base problem where along comes a new account which wants to use 80% of a current strategy but not all of it and your back into the inheritence problem I often get!

Is this a design issue which is inheritently flawed and maybe the accounts in this case aren't similar enough, is it a matter of putting up with 1,2 or 3 or is there another way?

TIA Graham
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Basically, I try to use a balanced mix of 2) and the delegation strategy, and it seems to work reasonably well. Don't be afraid of having many small classes. It doesn't hurt to be afraid of deep inheritance hierarchies, though...


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
One thing to remember is that utility methods in the superclass needn't be used by every subclass. If a new subclass only happens to use 80% of the "common methods" in the superclass, that's still fine.

That said, I use (2) if the new subclass is less related to the existing subclasses than the existing subclasses are to each other. I try to avoid (2) if that's not the case - for example, if the new subclass also shares some code with one of the existing subclasses that the other subclass doesn't share.

One thing that helps is to try to keep the inheritance hierarchy conceptually clean. Decisions on whether functions are to be in the superclass or in the subclass should be based on more than just whether the code happens to be shared. Clean functional decomposition with unitary functional purposes helps a lot.
Graham VMead
Ranch Hand

Joined: Sep 22, 2003
Posts: 154
Thanks for the replies. Glad there isn't some other "correct" approach out there that I'm missing.

I tend to opt for 2) as it is functionally cleanest and if the inherited concrete methods from the abstract class aren't "utility" but are really business oriented I'm not to keen on them being inherited/visible within a sub class that has no need for them.

Thanks again
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
One solution you haven't suggested is extending a concrete class. It's wise to avoid that choice. Overriding a concrete method is almost guaranteed to blow up the Liskov Substitution Principle and expose you to "fragile parent" disease.
[ March 04, 2005: Message edited by: Stan James ]

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Gerald Davis
Ranch Hand

Joined: May 15, 2002
Posts: 872
I have something to say when I came back from work.
Gerald Davis
Ranch Hand

Joined: May 15, 2002
Posts: 872
I wander if it is me but do most people talk about whether a method is reusable or not; Yes or NO. In reality code duplication is a less structured beast; some methods are 30% reausble, some are 75%, some even 97%.
So what do you do? You find those duplications and put them into helper methods not only you solve the problem but also you increase your helper method reusable library.

The problem you have isn�t how to represent the Classes and Interfaces in your system design, but how to maximize reuse. Do without Abstract classes for reuse just stick to the Interface Account and sub Classes Current, Oversees and Deposit. The sub Classes would use reusable helper methods whenever there is any commonality in the code.

Tis Simple; to increase reuse, use smaller methods and learn to be the master of it, there is nothing more to it then that dude; don�t think about inheritance or any class related crap unless you are designing interfaces for clients. Sometimes however in the case that a method is 97% reusable it might be better to retrofit the method to do more then one task (that are almost similar) maybe using a string to specify what task is to be performed.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Gerald Davis:
So what do you do? You find those duplications and put them into helper methods not only you solve the problem but also you increase your helper method reusable library.


I agree that you should find those duplications and put them into their own methods. I don't agree that they need to be helper methods, or even that it often is the best way.


The problem you have isn�t how to represent the Classes and Interfaces in your system design, but how to maximize reuse. Do without Abstract classes for reuse just stick to the Interface Account and sub Classes Current, Oversees and Deposit. The sub Classes would use reusable helper methods whenever there is any commonality in the code.


Why not put those "helper methods" into an abstract super class? That often gives you additional options for simplifying the design, for example by accessing fields instead of using method parameters, or by using the Template Method pattern to extract commonality that would be hard to extract using static helper methods.

Tis Simple; to increase reuse, use smaller methods and learn to be the master of it, there is nothing more to it then that dude; don�t think about inheritance or any class related crap unless you are designing interfaces for clients.


I agree that you should learn to master small methods (and small classes, while we are at it). I don't agree that inheritance or polymorphism is crap, though - in fact dismissing those tools as useless looks rather short-sighted to me.

Sometimes however in the case that a method is 97% reusable it might be better to retrofit the method to do more then one task (that are almost similar) maybe using a string to specify what task is to be performed.


I'd rather use something like the Strategy pattern. Much more reusable and maintainable.
Gerald Davis
Ranch Hand

Joined: May 15, 2002
Posts: 872
Originally posted by Ilja Preuss:

Why not put those "helper methods" into an abstract super class?
.



Because the abstract super class is what the dude is having problems with. My solution is to give the sub classes or any class or function access to those helper methods. So they can pick and choose what functionality they need to do the task at hand.

However, it might be worth the Abstract Class having access to those helper methods if the design benefits from this Abstract Class.

Mmm , I am getting more ideas.

The other day I was talking about how code should be spit into two categories Management Code and Worker code. The worker code responsibility is to execute a task, whether that is print to screen, save to disk, execute an algerithem or query a database.
It is these worker objects that have the potential for reuse, just use helper methods and old fashioned procedural programming. However the management code interacts with these helper functions to build the application. It is the management that should be object orientated not the workers code. If you achieve Object Oriented reuse then it represents interface, conceptual and design reuse not implementation reuses.
Warren Dew
blacksmith
Ranch Hand

Joined: Mar 04, 2004
Posts: 1332
    
    2
Gerald Davis:

My solution is to give the sub classes or any class or function access to those helper methods. So they can pick and choose what functionality they need to do the task at hand.

Giving the subclasses access to those methods is kind of the point of putting them in the abstract superclass. Making them public would allow reuse by unrelated code as well, though in that case it might be better to factor them out into a utility class of some sort.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Warren Dew:
Gerald Davis:
Making them public would allow reuse by unrelated code as well, though in that case it might be better to factor them out into a utility class of some sort.


Factor them out sounds good. I don't like "utility classes" very much, though. Why not "normal" classes?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Gerald Davis:

The other day I was talking about how code should be spit into two categories Management Code and Worker code. The worker code responsibility is to execute a task, whether that is print to screen, save to disk, execute an algerithem or query a database.
It is these worker objects that have the potential for reuse, just use helper methods and old fashioned procedural programming. However the management code interacts with these helper functions to build the application. It is the management that should be object orientated not the workers code. If you achieve Object Oriented reuse then it represents interface, conceptual and design reuse not implementation reuses.


I think I already replied to that post that I don't buy that distinction. Actually it totally contradicts my experience: I benefit from polymorphism in both kinds of code, as far as I am even able to distinguish between it.

Also the whole concept of frameworks based on Dependency Injection - like Spring, for example - seems to conflict with your idea violently.
[ March 08, 2005: Message edited by: Ilja Preuss ]
Gerald Davis
Ranch Hand

Joined: May 15, 2002
Posts: 872
I would consider a Relational Database to be the muscle and the workers of an application; it is procedural in design and does not worry about objects maybe a few Stored Procedures here and there.

The frond-end however uses Object Oriented features to represent tables in database object/ relational mapping; the Customer Account Class object is not really a class but a record in the database.

The Classes, Interfaces and Abstract Classes are nothing but interfaces that hide the underlying system away from the client; they should not and ought not dictate the architect of the underlying database weather it is a Relational or Object oriented or even a collection of task oriented remote servers.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
You can build database centric designs like that ... if you have a database. I've used platforms and languages that bind the whole system to the database in very productive ways.

But my system gets and puts data via MQ-Series, web services, screen scraping, proprietary protocols and several databases. We keep the differences between these stores hidden in low levels of code. Higher levels see identical business objects no matter where the data comes from. The "muscle" is in those objects while data access and the relational model (if there is one) are supporting activities in the periphery of the system.

I've done four systems like this over the last 10 or 12 years in the Easel language (not OO), PowerBuilder (about half OO) and Java on two vendor frameworks. I find the quality of my OO strongly correlates to maintainability, extensibility and quality of the product.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Gerald Davis:
I would consider a Relational Database to be the muscle and the workers of an application; it is procedural in design and does not worry about objects maybe a few Stored Procedures here and there.


There is nothing inherently procedural about RDBMS'.

I don't know how databases are implemented, but they certainly *could* be object oriented inside, and I guess some are.

SQL is neither OO nor procedural, it's declarative (you just tell it what you want it to do, not how to do it).

JDBC certainly isn't as OO as it could be, but it also isn't strictly procedural as far as I can tell.


The frond-end however uses Object Oriented features to represent tables in database object/ relational mapping; the Customer Account Class object is not really a class but a record in the database.


I'd actually want a CustomerAccount object to be an object - and wanted to have the persistence layer care about wether it maps to one, several or just part of a record in the database.

they should not and ought not dictate the architect of the underlying database weather it is a Relational or Object oriented or even a collection of task oriented remote servers.


True. I don't see how it connects to your earlier posts, though.
Gerald Davis
Ranch Hand

Joined: May 15, 2002
Posts: 872
MMm ,maybe I am saying it all wrong.

Maybe an application should be treated the same as a multi tier application and each tier in system has its own design.

�you just tell it what you want it to do, not how to do it� isn�t this what good low coupling all about.

SQL Server
Correct SQL is not specific to one ether methodology; I would consider the SQL to be a standardized interface for managing persistent data and the database server�s implementation and architectures is of no importance to the SQL server�s client. To interact with the SQL server; you pass in a string and you get back a Container Class full of primitive types � I would consider container classes to be like primitive they don�t change much from language to language they are also low coupling.

Web-servers
Webservers are responsible for the presentation tier, JSP, PHP is used for manipulating HTML . HTML is a notation much the same way SQL is.HTML does not impose any Object Oriented or Procedual methodology on its user.

These servers both use strings and or simple types to represent data. I am sure that the designers of HTML and SQL came to the conclusion that notation not Object Oriented or Procedural is required. Oow! oow! I know what they call it know they call it MetaData I think!

Domians
I believe that many specialist domains need a MetaData (if I used the term correctly) to represent the data and or structure of there system. To use Object Oriented Programming for this would be like using objects to represent persistent data when SQL does a much better job in most cases.

If I was to represent two entities in system, I could use a Min MetaData and pass it into a fa�ade function.

Build (�Create Accounts Current, Oversees, Cheque [tom,dick,harry] �
Cammand(�Debit harry account $3000�)

And let the system worry about the under laying implementation.

Or do it all in objects.

CurrentAccount Tom= new CurrentAccount()
Oversees Account Dick= new Oversees()
Cheque Account Harry= new Cheque()

Harry.debit(�$2000�)

Already you can see that the Object Oriented example take up more room and is less human readable then my mini Metadata that I have created. Also the Object Oriented example hard codes the classes into the client code.

Types of reuse
Know I can explain what I mean better. In a system, there are two kinds of reuse: Metadata reuse and code reause. These types of reuse not to be confused the Metadata is context specific and is part of the application and the server code does what the Metadata tells it to do.

Now I can ask you guys what are the implication concerning Metadata reuse and server code reuse.

What I have written has made me think about more about multi-tier web application. They could benefit more if they exchanged data using strings containing Metadata instead of classes and complex data types like with EJB. Or is this what Corba already does; I am not familiar with this technology. I know that it can communicate with different servers of many different implementations and probably does everything I am thinking of.
 
wood burning stoves
 
subject: Inheritance/ Code reuse - opinions please