When I switched to using an object oriented language in 2002 I did so in the belief that the facilities which it offered would enable me to produce a greater volume of reusable code and therefore increase my productivity. I have been involved in the design and building of enterprise applications since the early 1980s, first in COBOL and then UNIFACE. I created a set of reusable libraries and then a framework in COBOL which increased the productivity of my development team, and after switching to UNIFACE I redeveloped that framework and the rate of productivity increased again. According to what I read about OOP the main motivation was expressed as follows:
Object Oriented Programming is the writing of programs which are oriented around objects, thus taking advantage of Encapsulation, Inheritance and Polymorphism to increase code reuse and decrease code maintenance.
I therefore set about redeveloping my framework for a third time with the expectation that my productivity, which is directly related to the amount of reusable code which I have at my disposal, would increase yet again. As discussed in Evolution of the RADICORE framework this turned out to be the case. This lead me to believe that I had implemented the concepts of Encapsulation, Inheritance and Polymorphism correctly, so I started to publish what I had achieved in my personal blog so that other programmers could benefit from my experience. Imagine my surprise when I started reading opinions from other programmers telling me that what I had produced was all wrong, that I was not following "best practices". The backbone of my framework is the use of an abstract table class which is inherited by every concrete table class, yet I was told that inheritance was bad and that I should be using object composition instead. I looked for code samples which could both describe what this thing called "object composition" was as well as prove that it was better, but all I could see was an increase in the amount of code that needed to be written and a decrease in the amount of code that could be reused, so I considered their arguments to be totally without merit and so flushed them down the toilet. Decades later my productivity has increased even more, and my critics arguments have become more and more pathetic.
The barage of criticism began with What is/is not considered to be good OO programming, but all that it has done is force me to create a list of "best practices" which I do not follow. The rest of this paper concentrates on my objections to the mantra favour composition over inheritance which, as far as I am concerned, was created by second-rate programmers who have not yet learned how to use inheritance properly. While there are numerous articles which identify problems with inheritance when it is not used properly I cannot recall ever seeing any articles which elaborate on the benefits of inheritance when it *IS* used properly, only a few small paragraphs. This article attempts to redress that imbalance.
I develop enterprise applications which cover collections of different but integrated business areas, and had done for 20+ years before I switched to using PHP. My current ERP application deals with over 20 subsystems, 400 database tables and over 4,000 user transactions (use cases). Although the data on each table may be different, the only operations which can be performed on a table are Create, Read, Update and Delete (CRUD). Every user transaction follows the same pattern in that it performs one or more CRUD operations on one or more tables. Having identified these similarities as potential areas of code duplication, I then set about trying to use the power of encapsulation, inheritance and polymorphism to replace any duplicate code with reusable code. I came up with the following approach:
I came up with this arrangement simply by building two concrete table classes from scratch, with lots of duplicated code, then examining them looking for the similarities and the differences. I noticed immediately that all the methods were identical while it was just the data which was different, so the methods were prime candidates for moving to an abstract class. The differences in data could be expressed in just two variables - the $fieldspec array which provides the column names and their specifications (although this has been expanded to include a larger set of common table properties), and the $fieldarray array which can contain values for any number of columns from any number of rows. The existence of these two arrays then enables me to validate all input data using a standard validation object.
Because every table class shares the same set of inherited methods this provides a vast amount of polymorphism which in turn enables dependency injection. This has enabled me to create a fixed set of reusable page controllers which can operate on any table class within the application. There is a separate Controller for each of my Transaction Patterns.
Because all the data can be extracted from a Model with a single call to the getFieldArray() method this has enabled me to create a single View object which can extract that data, copy it to an XML document, then transform it into HTML using a specified XSL stylesheet. Note that I have produced over 4,000 HTML pages from a collection of just 12 reusable XSL stylesheets.
Because I am using an abstract class I can use the Template Method Pattern so that while all the invariant methods in the abstract class can handle the standard processing I am able to use "hook" methods within each concrete table class to include any custom business logic. Note that every method called by a Controller on a Model is an instance of a Template Method, so while it always executes standard code it provides the option for the developer to insert custom code.
What all this reusability boils down to is that when developing application components a developer has to spend a minimum amount of time dealing with standard boilerplate code which then leaves a maximum amount of time to deal with the important stuff, the business logic.
Not everybody thinks that inheritance is bad. In the article Object Composition vs. Inheritance I found the following:
Most designers overuse inheritance, resulting in large inheritance hierarchies that can become hard to deal with. Object composition is a different method of reusing functionality.
[....]
However, inheritance is still necessary. You cannot always get all the necessary functionality by assembling existing components.
[....]
The disadvantage of class inheritance is that the subclass becomes dependent on the parent class implementation. This makes it harder to reuse the subclass, especially if part of the inherited implementation is no longer desirable. ... One way around this problem is to only inherit from abstract classes.
In the Gang of Four book I found the following:
Class inheritance is basically just a mechanism for extending an application's functionality by reusing functionality in parent classes. It lets you define a new kind of object rapidly in terms of an old one. It lets you get new implementations almost for free, inheriting most of what you need from existing classes.
However, implementation reuse is only half the story. Inheritance's ability to define families of objects with identical interfaces (usually by inheriting from an abstract class) is also important. Why? Because polymorphism depends on it.
When inheritance is used carefully (some will say properly), all classes derived from an abstract class will share its interface. This implies that a subclass merely adds or overrides operations and does not hide operations from the parent class. All subclasses can then respond to the requests in the interface of this abstract class, making them all subtypes of the abstract class.
There are two benefits to manipulating objects solely in terms of the interface defined by abstract classes:
- Classes remain unaware of the specific types of objects they use, as long as the objects adhere to to the interface that clients expect.
- Classes remain unaware of the classes that implement these objects. Clients only know about the abstract class(es) defining the interface.
Later on it says the following:
Class inheritance has some disadvantages. First, you can't change the implementations inherited from parent classes at run-time, because inheritance is defined at compile-time. Second, and generally worse, parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of it's implementation, it's often said that "inheritance breaks encapsulation". The implementation of a subclass becomes so bound up with the implementation of its parent class that any change in the parent's implementation will force the subclass to change.
Implementation dependencies can cause problems when you are trying to reuse a subclass. Should any aspect of the inherited implementation not be appropriate for new problem domains, the parent class must be rewritten or replaced by something more appropriate. This dependency limits flexibility and ultimately reusability. One cure for this is to only inherit from abstract classes, since they usually provide little or no implementation.
In Designing Reusable Classes which was published in 1988 by Ralph E. Johnson & Brian Foote I found the following:
Object Oriented Programming
There are two features that distinguish an object-oriented language from one based on abstract data types: polymorphism caused by late-binding of procedure calls and inheritance. Polymorphism leads to the idea of using the set of messages that an object understands as its type, and inheritance leads to the idea of an abstract class. Both are important.
Protocol
The specification of an object is given by its protocol, i.e. the set of messages that can be sent to it. Objects with identical protocol are interchangeable. Thus, the interface between objects is defined by the protocols that they expect each other to understand. If several classes define the same protocol then objects in those classes are "plug compatible". Complex objects can be created by interconnecting objects from a set of compatible components. This gives rise to a style of programming called building tool kits.
Inheritance
Most object-oriented programming languages have another feature that differentiates them from other data abstraction languages; class inheritance. Each class has a superclass from which it inherits operations and internal structure. A class can add to the operations it inherits or can redefine inherited operations. However, classes cannot delete inherited operations.
Class inheritance has a number of advantages. One is that it promotes code reuse, since code shared by several classes can be placed in their common superclass, and new classes can start off having code available by being given a superclass with that code. Class inheritance supports a style of programming called programming-by-difference, where the programmer defines a new class by picking a closely related class as its superclass and describing the differences between the old and new classes. Class inheritance also provides a way to organize and classify classes, since classes with the same superclass are usually closely related.
One of the important benefits of class inheritance is that it encourages the development of the standard protocols that were earlier described as making polymorphism so useful. All the subclasses of a particular class inherit its operations, so they all share its protocol. Thus, when a programmer uses programming-by-difference to rapidly build classes, a family of classes with a standard protocol results automatically. Thus, class inheritance not only supports software reuse by programming-by-difference, it also helps develop standard protocols.
Another benefit of class inheritance is that it allows extensions to be made to a class while leaving the original code intact. Thus, changes made by one programmer are less likely to affect another. The code in the subclass defines the differences between the classes, acting as a history of the editing operations.
Abstract Classes
Standard protocols are often represented by abstract classes [Goldberg & Robson 1983].
The roots of class hierarchies are usually abstract classes, while the leaf classes are never abstract.
A class that is not abstract is concrete. In general, it is better to inherit from an abstract class than from a concrete class. A concrete class must provide a definition for its data representation, and some subclasses will need a different representation. Since an abstract class does not have to provide a data representation, future subclasses can use any representation without fear of conflicting with the one that they inherited.
Inheritance vs. decomposition
Since inheritance is so powerful, it is often overused. Frequently a class is made a subclass of another when it should have had an instance variable of that class as a component.
You should notice in these articles that it the overuse or improper use of inheritance, such as inheriting from one concrete class to create another concrete class, resulting in the creation of deep inheritances hierarchies, which causes problems. The solution, therefore, should be obvious:
You should note that the above steps match precisely the philosophy which I adopted from the start of my foray into the world of OOP with my RADICORE framework. So even though I had not read these articles I instinctively did the right thing.
It was not until a few years ago that I came across the paper called Designing Reusable Classes. I discuss this paper in more detail in The meaning of "abstraction", but it can be summarised as follows:
Abstraction is the act of separating the abstract from the concrete, the similar from the different. An abstraction is usually discovered by generalizing from a number of concrete examples. This then permits a style of programming called programming-by-difference in which the similar protocols can be moved to an abstract class and the differences can be isolated in concrete subclasses.
Not only does this paper describe an approach which I am willing to follow, it actually describes the very approach which I have been following since I started using PHP4 way back in 2002. It would seem that I instinctively went down the right path by following by own nose instead of being led astray by a bunch of pseudo-experts who are peddling different varieties of snake oil. By following such bad advice legions of novices will become nothing more than a Cargo Cult Programmers and Code Monkeys.
I knew as soon as I coded my second table class and saw that it had exactly the same set of methods (protocols) as the first one that I had the opportunity to share those methods using this wonderful new feature of OOP called inheritance, so I instinctively put those methods into a generic table class. This acted as an abstract class because at the time I was using PHP4 which did not support the abstract keyword. This abstract class also enabled me to add in empty "hook" methods which implemented the phrase the differences can be isolated in concrete subclasses
.
Note that I was not tempted to inherit from the first concrete class to create the second as I knew that there would be some parts of the first concrete class that I did not want to share, and there is no way to uninherit anything that you don't want. That is why I created a separate class which contained ONLY those things which were safe to share. Anything unique to a particular table could then be isolated in that table's subclass.
While it is very easy to find an article on the internet which says "inheritance is bad" (just click on Just click on https://www.google.com/search?q=inheritance+is+bad to see what I mean) it is quite rare to find an article which offers an opposing view. In Composition vs. Inheritance: How to Choose? I found the following:
Inheritance should only be used when:
- Both classes are in the same logical domain
- The subclass is a proper subtype of the superclass
- The superclass’s implementation is necessary or appropriate for the subclass
- The enhancements made by the subclass are primarily additive.
My use of inheritance ticks all these boxes as follows:
In Inheritance vs. Composition I found the following:
Inheritance can be applied if the following statements hold true:
- The subclass is a proper subtype of the superclass.
- The subclass follows the Liskov Substitution principle.
- The superclass’s implementation is appropriate for the subclass.
- The enhancements made by the subclass are primarily addition or change to the superclass’s behavior.
My use of inheritance ticks all these boxes as follows:
While the above articles do suggest that there is a place for inheritance, they both fail to mention the use of an abstract class, which I think is a major oversight. The use of an abstract class enables the use of the Template Method Pattern which is a fundamental technique for code reuse as it factors out common behaviour. This is an essential pattern in framework design as it implements the Hollywood Principle ("Don't call use, we'll call you")
One thing that really annoys me in software development is where a word which starts off with a single and unambiguous meaning is suddenly given a second and totally unrelated meaning. When you see that word being used it is often not clear exactly which meaning is supposed to be in play, and that leads to confusion and misunderstanding. This leads some intellectual lightweights to produce corrupt interpretations of something which is supposed to be simple and unambiguous, sometimes even merging the two descriptions into a confused hybrid which is neither one nor the other. Examples of several misunderstandings can be found at:
Believe it or not there are two totally separate and unconnected meanings for "object composition" which are as follows:
Classes should favor polymorphic behavior and code reuse by containing instances of other classes that implement the desired functionality
When I looked for an example which proved the superiority of composition over inheritance I found the following code in Inheritance vs. Composition in PHP:
class Vehicle { public function move() { // ... } } class Car extends Vehicle { public $engine; public function __construct(Engine $engine) { $this->engine = $engine; } public function move() { $this->engine->start(); // ... } } class Engine { public function start() { // ... } } $car = new Car(new Engine()); $car->move();
This to me is total nonsense as methods like $engine->start
and $car->move
simply will never appear in a database application in which you are NOT communicating with objects in the real world as all you are doing is maintaining information about those objects in a database. The objects in a database are called "tables", and the only operations which can be performed on a table are Create, Read, Update and Delete (CRUD). Because of this I will use examples from my own code, as shown below:
In the following example I have several methods in the default_table
class which I want to reuse in the product
class.
class default_table { public function insertRecord($fieldarray) { // ... return $fieldarray; } public function updateRecord($fieldarray) { // ... return $fieldarray; } public function deleteRecord($fieldarray) { // ... return $fieldarray; } public function getData($where) { // ... return $fieldarray; } } class product { public function __construct ( $this->default_table = new default_table; } public function insertRecord($fieldarray) { $fieldarray = $this->default_table->insertRecord($fieldarray); return $fieldarray; } public function updateRecord($fieldarray) { $fieldarray = $this->default_table->updateRecord($fieldarray); return $fieldarray; } public function deleteRecord($fieldarray) { $fieldarray = $this->default_table->deleteRecord($fieldarray); return $fieldarray; } public function getData($where) { $fieldarray = $this->default_table->getData($where); return $fieldarray; } }
As you can see this still requires a great deal of code in the product class as each method in the default_table
class requires a corresponding method in the product
class in order to call it.
Now look at how much code we can remove yet still produce exactly the same effect. Note the use of the keywords abstract and extends:
abstract class default_table { public function insertRecord($fieldarray) { // ... return $fieldarray; } public function updateRecord($fieldarray) { // ... return $fieldarray; } public function deleteRecord($fieldarray) { // ... return $fieldarray; } public function getData($where) { // ... return $fieldarray; } } class product extends default_table{ public function __construct ( // ... } }
The actual contents of my abstract table class are listed in more detail at common table methods.
Notice that this method requires nothing in the concrete subclass except the constructor, so that's a huge amount of code that I don't have to add to each table class. When you consider that I have written an ERP application with over 400 table classes that is a huge amount of code that I didn't have to write 400 times.
Note also that there is a significant loss of functionality when replacing inheritance with composition - the inability to use the Template Method Pattern and its "hook" methods. This pattern implements Inversion of Control (IoC) which is also known as the Hollywood Principle (Don't call us, we'll call you) which is a distinguishing factor of all frameworks. Without it the RADICORE framework would not be much of a framework, so on that fact alone object composition is not a viable alternative.
A composition relationship is where one object (often called the constituted object, or part/constituent/member object) "belongs to" (is part or member of) another object (called the composite type), and behaves according to the rules of ownership.
As is usual true OO afficionados like to make things more complicated than they really are by inventing several types of composition, but in the context of database applications I have seen only two possibilities. Figure 1 shows the idea of a single object known as an ORDER which, following the rules of data normalisation, is broken down into a group of tables which are related in such a way as to form a fixed hierarchy. In the database this is not a single object, it is a group of tables which are joined together in a series of one-to-many or parent-child relationships.
Figure 1 - an aggregate ORDER object (a fixed hierarchy)
This is explained in more detail in Object Associations are EVIL - Figure 5.
Figure 2 shows what looks like a similar structure, but it is completely different in that each of those entities - Car, Engine, Piston, Spark Plugs, Stereo, Door, et cetera - are NOT separate tables in the database, they are separate rows in a single PRODUCT table. The relationship between one product and another is maintained on a separate PRODUCT-COMPONENT table, as shown in Figure 3.
Figure 2 - an aggregate BILL-OF-MATERIALS (BOM) object (an OO view)
The idea that each of these objects is regarded as a separate entity, thereby requiring a separate class, is bonkers. They are simply separate rows in the PRODUCT table, therefore can be handled by a single PRODUCT class.
This is explained in more detail in Object Associations are EVIL - Figure 6.
Figure 3 - an aggregate BILL-OF-MATERIALS (BOM) object (a database view)
This structure shows two one-to-many relationships where the PRODUCT-COMPONENT table has two foreign keys - product_id_snr and product_id_jnr, which both point back to different entries on the PRODUCT table. The primary key of the PRODUCT-COMPONENT table is a combination of these two foreign keys. The maintenance tasks for the PRODUCT table and PRODUCT-COMPONENT table are totally separate. The complete BOM in its entirety can be viewed using a task built from one of the TREE VIEW patterns.
This is explained in more detail in Object Associations are EVIL - Figure 7.
The wikipedia page on the Composite Reuse Principle states the following:
Drawbacks
One common drawback of using composition instead of inheritance is that methods being provided by individual components may have to be implemented in the derived type, even if they are only forwarding methods. In contrast, inheritance does not require all of the base class's methods to be re-implemented within the derived class. Rather, the derived class only needs to implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.
The article Object Composition vs. Inheritance states the following:
Objects are composed to achieve more complex functionality. The disadvantage of object composition is that the behavior of the system may be harder to understand just by looking at the source code. A system using object composition may be very dynamic in nature so it may require running the system to get a deeper understanding of how the different objects cooperate.
The idea that object composition is a direct replacement for and always superior to inheritance is a completely fallacy. Each has its own set of advantages and disadvantages, so it is up to the developer to decide which one is the most appropriate for their particular circumstances, which one provides the best solution for the problem which they are trying to solve.
Since a major motivation for object-oriented programming is software reuse then those principles and practices which aid in the production of more reusable code are obviously better than those which produce less. Practices which produce code which you don't have to write are obviously better than practices that require code that you do have to write. The simple fact of the matter is that inheritance, when used properly, can provide far more reusable software than composition ever can, and it can be reused in its entirety with the use of a single extends keyword. As shown in Example of Composition it takes a lot of code to reuse the contents of the default_table
class while the Example of Inheritance takes none at all. Now imagine using the extends keyword to create hundreds of concrete table classes - this then equates to a huge amount of code that doesn't have to be written hundreds of times.
Inheritance is the primary method of providing polymorphism, particularly subtype polymorphism, which is a result of applying the "IS-A" test. which is described as follows:
IS-A is a subsumptive relationship between abstractions (e.g., types, classes), wherein one class A is a subclass of another class B (and so B is a superclass of A). In other words, type A is a subtype of type B when A's specification implies B's specification.
Each subclass extends its superclass and so inherits all its properties and methods.
As soon as I saw other programmers use "IS-A" to make statements such as "a CAR is-a VEHICLE", "a BEAGLE is-a DOG" and "a CUSTOMER is-a PERSON" (with other examples shown in Class Hierarchies and Inheritance) and so create a selection of subtypes, as shown in Figure 4 below, I knew that it was a mistake of gargantuan proportions.
Figure 4 - Hierarchy of "dog" classes
With this approach you cannot introduce a new type (breed or variety) of dog without creating a new subclass which uses the "extends" keyword to inherit from the superclass. The result is what I would call a dog's dinner.
When I am writing a database application what I see instead is "VEHICLE is a table", "DOG is a table" and "PERSON is a table". Every entity in the business/domain layer IS-A table, and every table shares a common set of characteristics. If you bother reading Designing Reusable Classes you should see that these common characteristics appear in the form of a set of common table methods and a set of common table properties. Note that the properties do not have any values until a subclass is instantiated where there is code within the constructor which loads in the details for a specific database table.
In a database the DOG entity would have its own table, and in my software each table, because it has its own business rules, would have its own class. Each table can handle multiple rows, so its class should do so as well. In a database the idea of being able to split the contents of the DOG table into different types, breeds or varieties would not involve separate tables, it would simply require an extra column called DOG-TYPE which would be just one of the attributes or properties that would be recorded for each dog. If there is no need for a separate table for each DOG-TYPE I can see no reason to have a separate subclass for each DOG-TYPE.
If there were additional attributes to go with each DOG-TYPE then I would create a separate DOG-TYPE table to record these attributes, and make the DOG-TYPE column of the DOG table a foreign key which points to the DOG-TYPE column of the DOG-TYPE table, which would be its primary key. This would produce the structure shown in Figure 5 below:
Figure 5 - hierarchy of DOG and DOG-TYPE tables
With this design all the attributes of a particular type/breed of dog are stored on the DOG-TYPE table, so instead of a separate subclass for each DOG_TYPE I would have a separate row on the DOG-TYPE table. When reading from the DOG table you can include a JOIN in the SQL query so that the result combines the data from both tables. This is how you can "inherit" attributes in a database. The introduction of a new type of dog requires no more effort than adding a record to the DOG-TYPE table. There are no changes required to the software, no new classes, no new screens, no new database tables, no nothing. From a programmer's point of view this simple 2-table structure is far easier to deal with than an unknown number of subclasses.
Extracting details for particular types of dog is just as easy as extracting details by any attribute, such as:
SELECT * FROM dog WHERE dog_type='COLLIE' SELECT * FROM dog WHERE gender='MALE' SELECT * FROM dog WHERE colour='LIGHT BROWN'
Apparently this version of polymorphism was created specifically to restrict the range of types that can be used in a particular case of polymorphism
, but I do not see the need for such a restriction. If I wish to ensure that a program only looks at entities which are dogs then I use the DOG class which will only read rows from the DOG table. If I wish to ensure that a program only looks at entities which are vehicles then I use the VEHICLE class which will only read rows from the VEHICLE table. If I accidentally have an HTML document that is filled with DOG details and I submit it to a task which uses the VEHICLE class, then that task will fail at the validation phase.
PHP is not a statically typed language, therefore I do not have to give each class a specific "type" before I can use it. Its "type" is always "database table" and its "subtype" is identified in the class name, such as "DOG" or "VEHICLE". When a Controller communicates with a Model it has absolutely no interest in what the subtype is, the only requirement is that it represents a database table. As it only ever uses the methods which have been defined in the abstract table class, if you tell it to use an object which does not support those methods then it will fail. Similarly when a View object extracts data from a Model using $fieldarray = $object->getFieldArray()
it does not care whether it is a DOG or a VEHICLE or a WHATEVER, it only cares that it supports that particular method. If it does not then the call will fail, and the programmer who wrote that code will get a smack on the back of his head for being stupid.
The idea that each table in a database is a distinctly separate "type" which therefore demands a distinctly separate class, is, to me, pure nonsense as it is missing a couple of vital points:
My experience with developing database applications prior to switching to PHP taught me that while the structure of each table is different, the data is different, and the business rules are different, the behaviour is identical - every table is subject to exactly the same set of operations/methods, and these operations are Create, Read, Update and Delete (CRUD). It should therefore be obvious to every programmer that these common operations are prime candidates for being moved to an abstract class which can be be inherited by every concrete table class.
Furthermore, every use transaction follows the same basic pattern in that it performs one or more CRUD operations on one or more tables. Anyone who has written a significant number of transactions which involves an HTML document at the front end, an SQL database at the back end, with code in the middle which moves data between the two ends and applies any business rules, should notice that the code required can be split into roughly two camps - common boilerplate code and unique code. The programmer's objective should be quite clear - put as much of this boilerplate code into sharable modules and isolate the unique code.
An advantage of using an abstract class is that it enables the use of the Template Method Pattern in which the common code can be defined in the abstract table class using invariant methods while any unique behaviour can be defined in any concrete table class using variable "hook" methods. When you have a single abstract class inherited by hundreds of concrete classes it also provides an enormous amount of polymorphism, a vital ingredient of dependency injection, which has enabled me to create a collection of reusable Controllers and reusable Views. Note the constructor in every concrete class loads data into the common table properties which identify the unique characteristics of that table.
This approach was the one which I instinctively took when switching to an OO language, and it has enabled me to produce a huge volume of reusable code. While a horde of other developers queued up to tell me that everything I did was wrong, I recently came across the paper Designing Reusable Classes (which I discuss in The meaning of "abstraction") which says that my approach was perfectly sound, so that entitles me to blow those critics a huge raspberry.
There are some people out there who think that a subtype is different from a subclass (refer to Subtyping vs. inheritance for an example). The wikipedia page Inheritance (object-oriented programming) contains the statement Inheritance should not be confused with subtyping
, but I cannot help but notice that both terms rely on the keyword extends and in both cases the results are exactly the same - the properties and methods in the superclass/supertype are shared by the subclass/subtype. So while in theory there may be a difference, in practice there is not. To me this is just another case where OO fanatics are trying to make something more complicated than it really is just to prove how clever they are, but I refuse to be taken in by their shenanigans. I may be cabbage looking but I'm not green. There is no practical difference between the two, so as far as I am concerned the theoretical difference is not worth the toilet paper on which it is written.
I am amazed at the number of clueless newbies who think inheritance is wrong. Just click on https://www.google.com/search?q=inheritance+is+bad and you will see over 60 million hits. I will now attempt to dissect some of these misplaced ideas one by one.
When I read this statement the first thought that entered my mind was What idiot came up with this idea?
Encapsulation and inheritance are supposed to be two of the primary features of OOP, so how can they said to be causing some kind of a problem? In the paper Evolution of Object Behavior using Context Relations I came across the following statement:
It has been widely acknowledged that inheritance breaks encapsulation, and it is clear that the context relation may do so in the same manner as inheritance. If a derived class is allowed to access members inherited from a base class, changes in the base class may require maintenance of the derived class as well.
Notice the words "IF" and "MAY" in those sentences. This means that inheritance does not ALWAYS break encapsulation, it only does so in certain circumstances. The objective of inheritance is to provide a mechanism for holding reusable code so that code defined once in a superclass can be shared by every subclass instead of having to be duplicated, which would otherwise violate the DRY Principle. Any changes to the superclass will automatically be shared/inherited by every subclass, which also means that any bugs inserted into the superclass will also be inherited by every subclass. The solution to this problem is not to insert bugs in the first place.
This dubious argument is not limited to inheritance as it can also be applied to every sharable function, procedure or subroutine that has ever been written. The certainty of savings made by putting a chunk of code into a subroutine which can be called many times instead of being duplicated many times far outweighs the possibility of a breaking change being introduced later by an incompetent programmer. So instead of saying Don't use inheritance because it may be screwed up by an incompetent programmer
I would prefer to say Don't employ incompetent programmers
. It is simply not possible to create a programming language which will prevent a bad programmer from writing bad code, so any programmer who writes bad code and then complains that the language let him do it is just a bad workman who blames his tools.
Every time I read this I want to reach out and give the author a smack on the back of his head for the simple reason that this is a misuse of the term coupling, which is concerned with how two modules interact, how one of those modules calls the other. Coupling introduces a dependency, so when module A calls module B we say that module A is dependent on module B as it cannot perform its function without the use of module B. Note that it requires two separate modules when there is a call from one module to the other.
With inheritance there is no interaction between two modules because if class A inherits from class B this results in a single object which merges the properties and methods of classes A and B. There is no call from A to B as all the methods inside class B are treated as if they were coded inside class A. If there is no call from object A to object B there there is no coupling whatsoever. The same cannot be said when you switch from inheritance to composition, as shown in Example of Composition, as this shows a definite case of one object calling another.
This could only become an issue if an implementation in the parent class is not a 100% fit for the child class, but as it has already been said this potential issue can be avoided by only inheriting from an abstract class. In my own case as soon as I started developing with PHP I created a class for every database table, and no sooner had I developed a class for my second table when I noticed some similarities. This prompted me to find a way to deal with those similarities using reusable instead of duplicated code.
Question: What new facility does OOP bring to the table to allow you to share code between classes?
Answer: Inheritance.
This is precisely why I created a superclass which was dedicated solely to provide the methods for dealing with an unknown database table while each subclass deals with a specific database table. I was using PHP4 at the time which did not allow the use of the word "abstract" in class definitions, which is why I called it a generic table class.
Although I started with a small set of common table methods which has greatly increased in the past 20 years, especially with the addition of "hook" methods, this abstract class contains only those methods which can be applied to a database table, any database table, therefore the chances of making a change in the superclass which is undesirable in a subclass is virtually impossible. Contrast this with the situation where there is a method in one concrete class which you start to reuse in another concrete class, yet some time later you change that method in the superclass which then makes it incompatible with the subclass. This is why I say never inherit from one concrete class to create a different concrete class. I did not wait to be told that such a thing was a bad idea, I knew instinctively that it could problems.
In this wikipedia page it says the following:
The fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered "fragile" because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.
This problem should only exist if you inherit from one concrete class to create a different concrete class. It should not exist with an abstract class which has been created for a specific problem domain, such as that for a database table. Every change made to the abstract table class should be viable for every concrete table class.
The idea that amending shared code improperly will cause all those places which share that code to malfunction is not limited to OO code. It is a fact of life that the same thing could happen in any language which allows code inside a function to be called, and therefore shared, instead of having to be duplicated. The advantages of having shared code far outweigh the possibility of a cock-up caused by bad programmer.
One possible solution is to make instance variables private to their defining class and force subclasses to use accessors to modify superclass states. A language could also make it so that subclasses can control which inherited methods are exposed publicly. These changes prevent subclasses from relying on implementation details of superclasses and allow subclasses to expose only those superclass methods that are applicable to themselves.
I do not have to make instance variables for a table's data private as I do not use separate variables for any of a table's columns. Instead I keep all application data in its original form, either the $_POST array from an HTML form, or the array returned from an SQL SELECT query, in a class property known as $fieldarray. Is is used as both an input and output argument in the common table methods which are inherited from the abstract table class,
An alternative solution is to have an interface instead of superclass.
This is a stupid idea as interfaces do not share any code as they contain nothing but abstract methods, and any competent OO programmer will tell you that abstract methods do not have any implementations, so there is zero reusability. You can only share reusable code by inheriting from a class, preferably an abstract class, which contains concrete methods. Interfaces also prevent the use of the Template Method Pattern, a valuable tool for code reuse in frameworks, as they do not provide any means of defining invariant methods which can call optional "hook" methods.
Deep inheritance trees make the codebase hard to navigate and understand. New developers on the project can find it challenging to trace and comprehend the flow of the program. This problem is caused by continually extending one concrete class to create another concrete class, as explained by Ricki Sickenger in his article Pragmatic OOP in which he said the following:
A Car and a Train and a Truck can all inherit behavior from a Vehicle object, adding their subtle differences. A Firetruck can inherit from the Truck object, and so on. Wait.. and so on? The thing about inheritance is that is so easy to create massive trees of objects. But what OO-bigots won't tell you is that these trees will mess you up big time if you let them grow too deep, or grow for the wrong reasons.
This is all down to a mis-application of the "IS-A" test as already explained in Inheritance using "IS-A". The advice given my experts is that problems with inheritance can be avoided by only ever inheriting from an abstract class, so what you need to do is to identify in your software where to have several concrete implementations of the same abstraction. For that I draw your attention to a complaint made by one of my critics against my practice of having a separate class for each database table:
The concept of a table is abstract. A given SQL table is not, it's an object in the world.
That is precisely why I have an abstract table class which contains all the protocols which apply to every database tables which can then be extended into a concrete table class for every physical table in the database. the logic which I followed is explained in The meaning of "abstraction". After extending my abstract class into a concrete class, which I do hundreds of times, I never extend any concrete class into a different concrete class, hence I never produce any complex hierarchies.
In the blog post Inheritance Is a Procedural Technique for Code Reuse written by Yegor Bugayenko I found the following statement:
We all know that inheritance is bad and that composition over inheritance is a good idea, but do we really understand why? In most all articles I've found addressing this subject, authors have said that inheritance may be harmful to your code, so it's better not to use it.
No, we don't ALL know that inheritance is bad as some of us know how to use it properly. The fact that the improper use of inheritance may be harmful to your code is no excuse to ban its use altogether. The improper use of any feature in the language could possibly produce unexpected and unwanted results, but that does not present a legitimate reason to impose a blanket ban on their use. Instead it should identify an area where more education is needed, although trying to teach a bad programmer not to be a bad programmer could be seen as an uphill task.
This "better" part is what bothers me; does it mean that sometimes inheritance makes sense? I interviewed David West (the author of Object Thinking) a few weeks ago, and he said that inheritance should not exist in object-oriented programming at all.
I watched that video interview with David West, and several things jumped out at me:
Yegor then argues that the word "inherit" is all wrong.
"Inherit," as an English verb, has a number of meanings. The form of inheritance that the inventors in Simula had in mind is more like: "Derive (a quality, characteristic, or predisposition) genetically from one's parents or ancestors."
Deriving a characteristic from another object is a great idea, and it's called subtyping. It perfectly fits into OOP and actually enables polymorphism: An object of classArticle
inherits all characteristics of objects in classManuscript
and adds its own.
What about when an object of class product_table
inherits all characteristics from abstract class default_table
? It cannot inherit from an object called default_table
as it is an abstract class which cannot be instantiated into an object. Every one of my 400 concrete table classes is a subtype of my abstract class supertype. The use of an abstract class then enables the use of the Template Method Pattern which is a fundamental technique for code reuse in frameworks as it easily implements the Hollywood Principle (Don't call us, we'll call you).
But what does copying methods and attributes from a parent class to a child one have to do with "deriving characteristics?" Implementation inheritance is exactly that - copying - and it has nothing to do with the meaning of the word "inherit" I quoted above.
It is a well known fact that in the English language sometimes a single word can have several different meanings, and sometimes a single meaning can be expressed in several different words. "inherit" can either mean obtaining something from a dead person's estate, or it could mean inheriting (copying) characteristics from a parent via their DNA. If you choose to work with the wrong meaning of inheritance then that is your problem. The rest of us are not so intellectually challenged.
Implementation inheritance is much closer to a different meaning: "Receive (money, property, or a title) as an heir at the death of the previous holder." Who is dead, you ask? An object is dead if it allows other objects to inherit its encapsulated code and data.
You cannot describe an object as being either dead or alive as it is not an organism, it is just a collection of zeros and ones in a computer. You are guilty of Zoomorphism.
Implementation inheritance was created as a mechanism for code reuse, and it doesn't fit into OOP at all. Yes, it may look convenient in the beginning, but it is absolutely wrong in terms of object thinking.
Implementation inheritance is the mechanism whereby a subclass re-uses code in a superclass, so how is that different from creating a subtype from a supertype? If they are both created in the same way and have the same effect then how can one be right and the other wrong? The main motivation for using OOP is supposed to be code reuse (read Designing Reusable Classes if you don't believe me), and I use inheritance to share all the methods in my abstract table class with all 400 of my concrete table classes. That is a HUGE amount of code that I am able to share instead of duplicate. Yet you say it doesn't fit into OOP at all
and it is absolutely wrong in terms of object thinking
.
Just like getters and setters, implementation inheritance turns objects into containers with data and procedures.
That is what Encapsulation is supposed to be all about, you numpty! In case you haven't read the memo yet - getters and setters are EVIL
Of course, it's convenient to copy some of those data and procedures to a new object in order to avoid code duplication. But this is not what objects are about.
OOP is about creating reusable code, and inheritance provides reusable code. In that respect they go together perfectly, like a horse and cart, so anyone who says that they are not a perfect fit is talking out of the wrong end of his alimentary canal.
They are not dead; they are alive!
Objects are not real entities, they are not living organisms, they are just models of entities in your software.
Thus, I think inheritance is bad because it is a procedural technique for code reuse. It comes as no surprise that it introduces all the problems people have been talking about for years. Because it is procedural! That's why it doesn't fit into object-oriented programming.
That statement is complete rubbish as procedural languages do not have inheritance. I should know as I used COBOL, the most famous and widely used procedural language of all time, for 16 years, and I never found any hint of anything which could be called "inheritance". All those people who claim that inheritance is bad simply do not know how to use it properly. I suggest you read Designing Reusable Classes which is one of the few papers I have which contains ideas that I regard as being sensible.
In Do Not Use Inheritance I found the following statements:
Why inheritance was inventedTo see why we can avoid inheritance, we should understand why it was invented. The simplified story goes like that:
Before inheritance, there were structural data types, like struct in C.
But developers noticed that for the same data sets they usually needed the same procedures. So they packed the data together with their procedures and called it a class.
Then they realized that the data may vary when they model real information. So that some data are the same while some can be different in different use cases. So they invented inheritance, which means that a new class can extend an existing one and add new data to the structure. (And as the keyword says it should be only an extension and not changed...)
I cannot believe that inheritance was invented to share data structures. Methods, yes, but data - definitely not. I have never seen any examples of inheritance where the superclass contains properties but no methods. In software that deals with hundreds of database tables each table shares exactly the same CRUD methods, but there are no shared data structures (except for metadata, such as my common table properties). There might be individual columns that appear in more than one table, but not entire data structures.
But that also means that the procedures packed together with the data should also be variable. And it is not enough to extend the class with new procedures because the existing ones may not correctly handle the new data. So they invented the override of existing procedures with new ones.
This person clearly does not know how to make proper use of a struct which is described as:
A struct in the C programming language (and many derivatives) is a composite data type (or record) declaration that defines a physically grouped list of variables under one name in a block of memory, allowing the different variables to be accessed via a single pointer or by the struct declared name which returns the same address. The struct data type can contain other data types so is used for mixed-data-type records such as a hard-drive directory entry (file length, name, extension, physical address, etc.), or other mixed-type records (name, address, telephone, balance, etc.).
What this means is that instead of specifying each component within a struct(ure), which can vary, you pass around the structure name as a single argument (known as a flexible array member in the C language, but as a bog standard array in PHP). So instead of:
function doSomething($data1, $data2, $data3) {}
you use the following:
function doSomething($fieldarray) {}
This is precisely how I pass many different data structures around in my common table methods. Afficionados of good programming practices should recognise this as an example of loose coupling which is supposed to be better than tight coupling.
The article goes on to say the following:
With override things started to be bad so the abstract methods have been added finally. These methods are not implemented, so the extending classes will not override any already existing implementation. Since a class with unimplemented methods cannot be instantiated, the entire class also has to be marked as abstract. In other words, abstract classes are designed for inheritance.They called all this together polymorphism and with this, Object-Oriented Programming was born.
An abstract class filled with nothing but abstract methods is as useless as an interface as it does not contain any code which can be reused. When filled with non-abstract methods it becomes much more useful as it contains code that CAN be shared. You can make it even more useful by implementing the Template Method Pattern so that it contains a mixture of invariant (fixed) methods plus a set of variable "hook" methods which are specifically designed to be overridden in concrete subclasses.
The idea that Inheritance is the most expensive way of coding is complete and utter nonsense as, when used properly, it provides a doorway to huge volumes of reusable code which can be equated to code that you don't have to write. The RADICORE framework was designed specifically for building and running database applications, so it is centered around working with large numbers of database tables which can be viewed and maintained via HTML forms. At the heart of the framework is the abstract table class which is inherited by every concrete table class. Because these concrete classes all share the same set of methods this provides huge volumes of polymorphism which can be exploited using that mechanism known as dependency injection. This has enabled me to create a library of Page Controllers and Views which can be reused with any Model in the application. The only "expense" was the investment in my time and effort in creating all that reusable code 20 years ago. Since then I have reaped the rewards of that investment by being able to add more and more subsystems to my framework at a much faster rate than any of my rivals. If you don't believe me I dare you to take this challenge.
In my humble opinion it would be more correct to say that inheritance is the most efficient way of creating reusable code in that it contributes directly to two different areas of reusability and sharability:
Composition cannot achieve that level of reusability with that small amount of effort, so as an alternative to inheritance it is dead in the water, as effective as a lead balloon.
This is also known as the Composite Reuse Principle (CRP) (or should that be CR(a)P?) which states that:
classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class
However, swapping from inheritance to composition may be just swapping one problem for another:
Drawbacks
One common drawback of using composition instead of inheritance is that methods being provided by individual components may have to be implemented in the derived type, even if they are only forwarding methods. In contrast, inheritance does not require all of the base class's methods to be re-implemented within the derived class. Rather, the derived class only needs to implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.
If you look the code at Example of Composition you will see the amount of code I have in the product
class in order to reuse the code in the default_table
class. Now look at Example of Inheritance and you will see that I can achieve exactly the same thing but with far less code. The idea that composition is better than inheritance must have come from someone who has a completely warped understanding of what the word "better" actually means.
The biggest disadvantage for me with object composition is that it makes it impossible to use the Template Method Pattern which is a vitally important ingredient in any framework. Without it I would not have the ability to insert custom code into the processing cycle using my numerous "hook" methods.
I'm afraid the the unavoidable drawbacks of using object composition are far greater than the avoidable drawbacks of inheritance, so as I have already learned how to implement inheritance properly I shall consign this useless principle to the toilet where it belongs.
In Inheritance Is Evil. Stop Using It I found the following statements:
Imagine you write a class with several methods and properties. Now imagine you or someone else extends that class. Do you realize what just happened by doing that? Coupling has been created between two concrete classes. One change in the base class could affect the behavior of the child.
The significant point here is that one concrete class has been extended to make a different concrete class, so a legitimate change to the concrete superclass may have an unwanted effect on the subclass. If this causes a problem then you should follow the advice given in Designing Reusable Classes, the Gang of Four book, and Object Composition vs. Inheritance which is - only inherit from abstract classes
.
It further compounds the error by saying:
Imagine now that the base class is extended by a second class, and this class is in turn extended by another one. Can you still handle it?
The solution to this is also simple - Don't create deep inheritance hierarchies
.
What about testing each class?
You cannot test an abstract class because it cannot be instantiated into an object, you can only test one of its concrete subclasses.
The author then goes on to make a series of statements with which I profoundly disagree:
The Nicolò Pignatelli way | The Tony Marston way |
---|---|
I do not use inheritance in 99% of my code. | I use it everywhere in my business/domain layer. Every one of the 400+ concrete table classes inherits from the same abstract table class. |
I use only two type of class-level declarations: interfaces and final classes. | I don't use interfaces, for reasons given in Object Interfaces are EVIL. I prefer to use an abstract class, for reasons given in The difference between an interface and an abstract class.
I don't use final classes as I may want to produce a subclass of a table class. This is NOT to provide a different concrete class, but to provide a different implementation in one or more "hook" methods as the number of method names is fixed, as is the place in the processing flow where they are executed. |
I inject interfaces in dependent classes' constructors. | I never inject interfaces because I never use interfaces. I never inject anything into a class constructor, although I may use it as an argument on a method call. |
I don’t allow any class dependency to be injected other than interfaces. | I inject class names into Controllers, and I inject objects into Views. I never use object interfaces. |
I use a Dependency Injection Container to handle the creation of my instances. | I never use any sort of container, either I create an instance using the new keyword, or I use my singleton class. |
When required, I split complex behavior in multiple final classes implementing the same interface | If complex behavior is used in only one class then I leave it inside that class. If it used in several classes then I create a separate object which I can call several times. |
I use inheritance only, and I mean only, when it makes sense on a semantical level and only for extension purposes, without any base behavior change; | I use inheritance to share behaviour with every object in my business/domain layer. Because I use my abstract class to implement the Template Method Pattern I never need to change the behaviour of the invariant methods, I only ever provide different implementations in the "hook" methods as and when required. |
In Inheritance vs Composition: Composition wins by knockout a person calling himself Dr Tom Butler made the following statements:
Both people who've read my book and anyone who I've taught at university will know that I cover Object-Oriented Programming in detail but never mention inheritance once and never give examples of it. There's a reason for that.
As part of my PhD research I've been collecting programmer's attitudes towards inheritance (among other programming practices) and I've yet to come across an example where it's the better option.
It may not be obvious to him, but if a teacher gives his students bad advice and then asks those students their opinion on that advice then it's no wonder that hey will agree with those opinions. It is only when you offer a series of different methods to achieve a particular result that you can then ask your students which of those methods produces the best result. But what is the best result? How can you prove that the result from method A is better than the result from method B? When you consider that a major motivation for object-oriented programming is software reuse
then the best result can be measured scientifically as the one which produces the most reusable code. Why? Because the more reusable code you have at your disposal then the less code you have to write to get the job done. The less code you have to write then the less time it will take to get the job done, and this instantly makes your more productive. This is not just my opinion, I heard if from another developer way back in 2004.
That is why I examined several ways of achieving the results that I wanted, sometimes by looking at sample code provided by others, and sometimes by experimenting with ideas of my own, looking for the method which produced the biggest bang for the buck. Fortunately I wasn't hampered by being forced to follow some inappropriate or artificial rules, mainly because I didn't know those rules existed, which is why I managed to produce a framework with exceptional amounts of reusability. This framework produces user transactions which are comprised of the components shown in Figure 6 below:
Figure 6 - MVC plus 3 Tier Architecture
The amount of pre-written and reusable code which is provided in the framework is as follows:
This directly equates to code which you DON'T have to write. For example, after creating a database table I can build this family of forms to view and maintain the contents of that table using the following steps:
All this can be done in 5 minutes without having to write a single line of code - no PHP, no SQL, no HTML. If you think that your methods are better than mine then I suggest you take this challenge and put your money where your mouth is.
I've yet to find a single case where inheritance offers any distinct advantage over composition.
Then I would say that your experience has been severely limited. I suggest you take a look at my example of inheritance which clearly shows that by using inheritance properly that I can reuse the contents of class default_table
with less code than by using object composition. By inheriting from an abstract class I am also able to use the Template Method Pattern which is an essential part of a framework as it implements the Hollywood Principle (Don't call us, we'll call you) which is an essential property of a framework.
If you need polymorphic behaviour, use interfaces ...
As explained in Object Interfaces are EVIL these were invented to allow polymorphism in statically typed languages without the need for inheritance. PHP is not statically typed, nor does it need the use of interfaces to provide polymorphism without inheritance. I never use interfaces as they do not provide any form of reusable code, which makes them a bad fit in OOP.
... and for relationships composition is always easier to implement and far more flexible.
A relationship in a database is known as an association in OO terminology. Object composition has nothing to do with relationships as an abstract class is not related to any of its subclasses. The fact that one database table may be related to another database table is an entirely unrelated topic, as discussed in Object Associations are EVIL. As I explained above composition is NOT easier to implement as it requires more code to be written than with inheritance. It is NOT more flexible as it prevents the use of the Template Method Pattern which is vital for the functioning of a framework.
Any IS-A relationship can be expressed using HAS-A. And I've yet to be shown a case where it's not possible, at least when defining relationships between your own classes.
This is absolute rubbish. That is not just my opinion, it is the opinion expressed in wikipedia which says confusing the relations has-a and is-a is a common error when designing a model (e.g., a computer program) of the real-world relationship between an object and its subordinate. The is-a relationship may also be contrasted with the instance-of relationship between objects (instances) and types (classes): Type–token distinction
. Confusion might arise from the fact that the word "composition" has two different meanings, as explained in The two faces of object composition:
Anyone who fails to recognise the two different meanings for the same word can easily be confused into merging the two meanings into a single concept. Anyone who says Any IS-A relationship can be expressed using HAS-A
is therefore confused and an unreliable source of information.
Tom Butler goes on to say:
James Gosling, the creator of Java once said:You should avoid implementation inheritance whenever possible.If it's always possible to avoid inheritance we can infer that
You should avoid implementation inheritanceis the point he is making here, and I agree.
I do not know where that statement from James Gosling was reported, but in James Gosling on Java, May 2001 I found the following statements:
Bill Venners: When asked what you might do differently if you could recreate Java, you've said you've wondered what it would be like to have a language that just does delegation.James Gosling: Yes.
Bill Venners: And we think you mean maybe throwing out class inheritance, just having interface inheritance and composition. Is that what you mean?
James Gosling: In some sense I don't know what I mean because if I knew what I meant, I would do it. There are various places where people have completed delegation-like things. Plenty of books talk about style and say delegation can be a much healthier way to do things. But specific mechanisms for how you would implement that tend to be problematic. Maybe if I was in the right mood, I'd blow away a year and just try to figure out the answer.
Bill Venners: But by delegation, you do mean this object delegating to that object without it being a subclass?
James Gosling: Yes -- without an inheritance hierarchy. Rather than subclassing, just use pure interfaces. It's not so much that class inheritance is particularly bad. It just has problems.
James Gosling goes on to say:
Bill Venners: Given that we have both class and interface inheritance in Java, do you have any guidelines you would recommend to people trying to figure out which one of these they should use? When is it appropriate to use class extension, and what is the trade-off versus interface implementation and composition? Or is that too general of a question?James Gosling: No, it's not too general of a question. I just wish I had some good rules because it always gets kind of vague for me. I personally tend to use inheritance more often than anything else.
Bill Venners: Inheritance meaning class extension?
James Gosling: Class extension. I tend to use classes a lot more than interfaces, and I'm not sure why. I'll use interfaces for things that need to be really abstract and really clean -- something runnable or printable. It's almost like if the class name ends in a-b-l-e, then maybe it ought to be an interface.
I see nothing in that interview where James Gosling says You should avoid implementation inheritance whenever possible
. On the contrary, he says I personally tend to use inheritance more often than anything else
.
I was struck by his statement I'll use interfaces for things that need to be really abstract and really clean
because it meant that he had either not read or not understood what was said in Designing Reusable Classes which can be summarised as:
Abstraction is the act of separating the abstract from the concrete, the similar from the different. An abstraction is usually discovered by generalizing from a number of concrete examples. This then permits a style of programming called programming-by-difference in which the similar protocols can be moved to an abstract class and the differences can be isolated in concrete subclasses.
I personally find abstract classes to be far superior to interfaces as interfaces don't actually do anything useful.
Tom Butler then goes on to give explanations and code samples based on statements such as:
Employee extends Person (Person is-a employee)
I would never have sperate classes for Employee and Person for the simple reason that I would never have separate tables for Person and a-person-who-is-an-employee. I deal in enterprise applications which require enterprise grade data models, and for these my "bible" is Len Silverston's Data Model Resource Book. In this he does deal with just people, he deals with Parties where a Party can be either a Person or an Organisation. The concepts of Employer and Employee are nothing by different Roles which can be attached to Parties in a many-to-many relationship such as that shown in Figure 7 below:
Figure 7 - Party, Role and Party-Role
This allows a Party to have any number of Roles. I can add new Roles and add Roles to Parties without have to make changes to any classes. Thus I can create a Role called Employer and attach it to an Organisation. The effect is the same, but it requires far less effort than doing it "the OO way", and achieving something with less effort fits the definition of "efficiency".
Person has-a job
In Len Silverston's book a Job is called a Work-Effort, and the link between a Party and a Work-Effort is another many-to-many relationship, as shown in Figure 8 below:
Figure 8 - Party, Work-Effort and Party-Work-Effort
The advantage of this data model is that each entry on Party-Work-Effort can have a start date and and end date, thus giving you the ability to track a person's job history. Just try doing THAT with a subclass and see how far you get.
Here is another example from Tom Butler's article:
Cat extends Animal
Dog extends Animal
Cow extends Animal
I have already demolished this example in Inheritance using "IS-A" wrong.
Inheritance sucksThe problems with inheritance very quickly become apparent.
The only thing which is clearly apparent to me is that Tom Butler does not know how to use inheritance properly, so all his problems are self-inflicted.
Imagine I wanted to extend the system to model a pig and a human.
Nobody writing a database application would ever do such a thing. Nobody would ever store details of humans and animals in the same table table. Remember that in a database application you are not communicating with real people and real animals, you are only communicating with data about those things in a database. The data about each "thing" is stored in a database table, and the only operations you can perform on a database table are Create, Read, Update and Delete (CRUD). The only reason to record details about animals is if you are writing a system for a veterinarian, an animal shelter or a zoo, and you certainly wouldn't have a separate table for each type of animal.
You don't need inheritance. Ever. Really.If you are coming from a background of using inheritance it can be difficult to change your frame of mind from is-a to has-a but once you start getting the hang of thinking in terms of objects with properties rather than types with subtypes it becomes incredibly easy.
If you are coming from a background where you have not been taught how to use inheritance properly the first thing you need to do is find a teacher who knows what he is talking about, someone with decades of practical experience instead of a head full of unproven theories. You should start by reading Designing Reusable Classes where it explains the technique of programming-by-difference so that you can learn how to create abstract classes from which you can inherit to create concrete classes. This is the very same technique that I used over 20 years ago to create an abstract table class from which I subsequently created over 400 concrete table classes, thus providing me with a huge amount of reusable code, a huge amount of polymorphism (without the use of stupid interfaces, I might add) which has enabled me to employ dependency injection to great effect.
As I said at the start, unless you need to override a method in a base class that you didn't write, and the adapter pattern cannot be used, you don't need inheritance, ever. In this case you're not defining a relationship, but overriding some behaviour in a class someone else wrote. And you only need to do that because the original class wasn't designed with this flexibility in mind.
Until you learn NEVER to inherit from someone else's concrete class you will keep having problems. When you learn ONLY to inherit from an abstract class to will begin to see the benefits of inheritance. That assumes that you can learn to identify where it is possible to create an abstract class, but for that you need an IQ which is greater than your shoe size.
Judging by the number of statements made in Tom Butler's article which I have identified as being without merit due to basic misunderstandings on his part, plus an obvious lack of knowledge of how to write large-scale database applications, it is safe to say that I am not one of his fans. He uses the title "Doctor", so I can only assume that he is a doctor of proctology as he is obviously talking out of the wrong end of his alimentary canal. Nothing he says is worth the toilet paper on which it is written. I certainly would never employ anyone trained by him as they would never be able to contribute anything of use, they would be more of a hindrance than a help.
Instead of calling himself a lecturer and standing at the front of the class he should be sent to the back of the class and made to face the wall while wearing a dunce's cap. Instead of being a source of wisdom he is in fact a source of pre-fossilised copralites. Instead of training the next generation of competent programmers he is in fact adding to the herd of Cargo Cult Programmers and Code Monkeys.
The motivation for using OOP is quite simple:
Object Oriented Programming means writing programs which are oriented around objects. Such programs can take advantage of Encapsulation, Inheritance and Polymorphism to increase code reuse and decrease code maintenance.
While millions of articles and books have been written which attempt to describe OOP the Right Way
with their different ideas on rules, principles and "best practices", what the vast majority of them fail to realise is that no practice can be classed as "best" unless it produces the best results, and to my pragmatic mind the best results can only be equated to the most amounts of reusable code which in turn equates to code that you don't have to write. The dogmatists out there are not results oriented, they are rules oriented, and regardless of how much reusable code is available in a piece of software the mere fact that it does not follow their rules is enough for them to brand that software as inferior, unmaintainable and the work of a heretic.
The problem with inheritance is that nobody was taught how to use it properly, so far too many programmers used it in inappropriate circumstances. While some programmers with a modicum of intelligence recognised the fact that most problems were caused by NOT inheriting from an abstract class, everybody else tried (and failed) to invent a set of rules which tried to solve the problem but which failed miserably.
I taught myself how to program with objects, and I never learned how to use inheritance improperly, so I never encountered any of those problems mentioned previously. Instead I created an environment which contains a massive amount of reusable code:
In case the picture still isn't clear to you, if I have 45 Controllers which can be reused with any of my 400 Models, this gives 45x400=18,000 (yes, EIGHTEEN THOUSAND!) opportunities for polymorphism. Can your "best practices" do better that that? Can object composition do better than that?
Just as a bad programmer will continue to write bad code in any language, a potentially good programmer who follows bad practices will also continue to write bad code. By "bad" I mean "not as good as it could be". Rather than following a set of rules without question in a dogmatic and pedantic fashion, a pragmatic programmer should be prepared to question those rules to find out why they exist and what problems they are trying to solve, and examine different viewpoints or approaches in order to find better solutions.
I was designing and building enterprise applications for 20 years before I switched to an OO language, and in order to make the switch I investigated how I could utilise these new features that OOP offered in order to continue developing the same types of application but with more reusable code, which meant less code to write and therefore greater productivity. I had already written a framework in each of my two prior languages, so I set out to redevelop that framework in the new language. My new framework ended up as a combination of the 3-Tier Architecture and the Model-View-Controller (MVC) design pattern as shown in Figure 6 above, so it should be familiar to the vast majority of programmers. The amount of reusable code which I produced proved to me that my use of encapsulation, inheritance and polymorphism was on the right track, and the fact that I have been able to maintain and enhance the same codebase for the past 20 years shows that I did not make any mistakes. Not only do I save time by not having to write vast swathes of code, I also save time by not have to design all that code which I don't have to write, as explained in How much time can be saved?
I can safely say that I did not make any mistakes because I was not taught to make any mistakes. I did not follow the rules that everybody else follows like sheep simply because I did not know they existed. When I became aware of them years later I instantly saw that if I tried to implement them it would have a detrimental effect on my code, so I did what every other pragmatic programmer would do which is ignore them, consign them to the rubbish bin, flush them down the toilet.
So why is it that I, who got it right, is branded a heretic while all those who got it wrong are hailed as "proper" OO programmers?
Here endeth the lesson. Don't applaud, just throw money.