Polymorphism

by | General

Object Oriented Programming or OOP was the NEXT BIG THING in the software engineering world back in the late 1980s to 1990s (though it stretches back all the way back in the 1970s by Xerox Parc Labs and the Smalltalk language).

It was supposed to replace procedural programming, which from a computer language perspective, consisted of breaking down an application into a bunch of methods and functions, that dealt with whatever data your application needed to work with.

The problem with procedural programming is you tend to end up with a big monolithic mountain of code that can jump all over the place, making it difficult to follow.

The other problem with procedural programming is it can be difficult to model real world concepts. In procedural programming, you attempt to solve a problem using variables (data) and methods/functions (behavior), but not necessarily in the same place in the code.

Object oriented programming merges variables (data) and methods/function (behavior) in the SAME place, that is, inside the same “object”. The one obvious benefit behind combining data and the methods/functions that need to manipulate that data in the same object, is that everything needed for that “object” is all located in a single place … no longer do you have to hunt down the functionality of an object in different places.

An object then becomes easier to debug and enhance compared to a procedural program.

From a non technical perspective, we humans can understand “objects”. We deal with objects in real life all the time.

When I go to work, I drive a VEHICLE. My vehicle has some key attributes that make it a vehicle. Things like WHEELS. An ENGINE. BRAKES. These attributes can end up being your data for your vehicle object.

Of course your vehicle has behavior as well. My vehicle can ACCELERATE and DECELERATE. It can CHANGE DIRECTION.

As a human, it’s easier to understand a concept like a VEHICLE. And that is one of the big appeals behind Object Oriented Programming. You can now break down application requirements into OBJECTS.

So now OOP gives us the tool to break down project requirements using the power of objects.

So lets say I want to build a software application that helps the service department of a car dealership keep track of any service done for a customer.

Applying OOP techniques could help you build out your application because you can break down the components you’ll need for your application by thinking about the “objects” you would need.

For example, in real life, when you bring in your car for service, the service technician will typically start up a REPAIR ORDER. So you could create a repair order OBJECT.

Inside that REPAIR ORDER object, you typically would track things like PARTS and LABOR.

Inside a PART object, you would have attributes like the PARTNAME, the COST of a single part, the PARTID identifier, etc.

Inside a LABOR object, you would need objects like the EMPLOYEE working on the vehicle. And then attributes about the employee like their NAME, the DEPARTMENT they work for, and any other attributes you would need to calculate the labor costs such as all the TIME SPENT working on the repair order.

Then on the REPAIR ORDER object, you’d start thinking about what kind of BEHAVIOR (that is, the METHODS and FUNCTIONS) your object would need such as CALCULATE_TOTAL_COST() of the REPAIR ORDER.

Inside the CALCULATE_TOTAL_COST() method definition, you’d take the data attributes from your PARTS and LABOR objects and do whatever math calculations necessary to combine the total costs of all parts and human labor done on the repair order work to come up with a FINALCOST attribute, which would represent the total cost of the repair order for a given customer.

The reason why OOP became so popular in software engineering, is it helps us humans think about software engineering in human concepts like real world objects, instead of computer concepts of bits and bytes.

There are three main tenets of Object Oriented Programming.

  1. Encapsulation
  2. Inheritance
  3. Polymorphism

Encapsulation is the concept of “information hiding”. In the REPAIR ORDER object we mentioned before, you would divide up the DATA and BEHAVIOR of your object into two major categories, PRIVATE or PUBLIC.

Marking a piece of data or behavior inside an object as PRIVATE means they are “invisible” to other objects.

This concept of encapsulation helps keep other sections of code from accidentally changing things and causing unforeseen bugs and defects in your application.

This used to happen all the time in older based languages that did not have the concept of encapsulation and where everything was GLOBAL in scope. When data and methods are global in scope, it becomes extremely difficult to track down software defects. It suddenly becomes an Agatha Christie murder mystery where EVERYONE is a murder suspect.

Encapsulation also helps to enforce the concept of only allowing one object to interact and communicate with a different object through publicly exposed methods.

The second major tenet of object oriented programming is the concept of inheritance.

At a high level, inheritance is another concept we humans use a lot in real life.

As humans, we tend to view real world objects in terms of hierarchies and categories.

For instance, the entire field of biological sciences is all about categorizing living things. For instance, a POODLE is a TYPE of DOG which is a TYPE of MAMMAL.

In the same way, you can structure objects in a way so that they all have “parents” and “children”.

For example, say you want to model the different kinds of employees that work in your company, for an HR tracking system.

I can think of a few types of employees of the top of my head, including managers, product owners, business analysts, software engineers, quality assurance testers.

All of these types of employees share certain attributes and characteristics. For instance, every type of employee will have some sort of EMPLOYEE_ID number. They will also have a HOME ADDRESS, a WORK EMAIL ADDRESS, a PHYSICAL OFFICE LOCATION.

Using the power of object inheritance, you could create a PARENT OBJECT called EMPLOYEE that contains all these data attributes.

Now if you create a MANAGER object, you can INHERIT from the EMPLOYEE object. Because a MANAGER is a KIND of EMPLOYEE, you automatically INHERIT the attributes of an EMPLOYEE such as the EMPLOYEE_ID, HOME ADDRESS, WORK EMAIL ADDRESS and OFFICE LOCATION.

It’s a nice way of avoiding data and code duplication.

I found the the concepts of ENCAPSULATION and INHERITANCE fairly straightforward to pick up.

The last tenet of OOP, POLYMORPHISM, however, was a real toughie for me.

I find the very definition of polymorphism difficult to grasp even to this day:

“In object-oriented programming, polymorphism refers to a programming language’s ability to process objects differently depending on their data type or class. More specifically, it is the ability to redefine methods for derived classes.”

Huh?

Believe me when I say it took YEARS before I really started grasping how polymorphism worked and more importantly, WHY you need to care about it as a software engineer.

But understanding polymorphism really helps you design software in a way that’s EASY TO CHANGE and EASY TO TEST.

In general, object oriented programming was a great leap forward in helping software engineers break down software requirements in terms of objects, something humans can easily understand.

OOP isn’t a silver bullet, however. It comes with its own set of problems, including the problem of dealing with CHANGE.

There’s an old saying that the only CONSTANT in software development is CHANGE.

In object oriented programming, the problem of change rears its head when one object needs to interact with a different object.

We’re going to use a C# language example here, but the same concept can be demonstrated in many other C based languages such as Java, C++, Objective-C, etc.

Using our previous object examples about, say we have a REPAIRORDER object. In C#, we would create a new CLASS to represent a repair order.

 

public class RepairOrder {
            private sqlServerDataAccessLibrary = new SqlServerDataAccessLibrary();

            public SaveRepairOrder() {
                        sqlServerDataAccessLibrary.Save(this);
            }
}

 

We don’t have to get hung up on the specific syntax of the code here. The important thing to remember is we have a class that represents a REPAIRORDER object.

There is a public method called SaveRepairOrder() that is responsible for saving an instance of a repair order object to a Microsoft SQL database.

HOW the RepairOrder class saves itself to a database is only important within the RepairOrder class itself, so it’s marked private … no other classes have visibility to the sqlServerDataAccessLibrary class member.

This goes back to the concept of ENCAPSULATION. Keeping that class member private helps to protect it against unwanted or unintended changes by other classes.

So now the RepairOrder class can persist itself to a Microsoft database and life is good, right?

Okay, remember what we said about the only constant in software development is CHANGE?

So you come into work on a new day and life is good. But then you get an urgent call from your manager who tells you that the company Chief Information Officer read some interesting article in, well you guessed it, “CIO Magazine”, about how relational databases like Microsoft SQL Server and Oracle are going the way of the dodo bird, and now NoSQL databases like MongoDB and CouchDB are the wave of the future.

So the CIO sends an urgent e-mail message to all application development managers, including your own, that all home grown software like yours, needs to persist your data to a NoSQL database, like MongoDB.

So you, the programmer, pull up your code, and you change your RepairOrder class to look something like this:

public class RepairOrder {
            private mongoDbDataAccessLibrary = new MongoDbDataAccessLibrary();

            public SaveRepairOrder() {
                        mongoDbDataAccessLibrary.Save(this);
            }
}

You change your code, compile it, have the QA department retest your code, then redeploy it to wherever your application needs to go.

A hassle, for sure, but hey, you’re the programmer, you’re the foot soldier taking commands from the top brass of the company. Anyways, it wasn’t TOO much to change, right?

Now a week later, the CIO again sends another urgent e-mail message to all his direct report managers that there’s this new thing called “THE CLOUD”, which he read about in the new monthly issue of “CIO Magazine”, which urges all software shops should start using cloud databases like Microsoft Azure and Amazon Web Services to store all application data.

Again, you get an urgent call from your direct manager that you have to change your RepairOrder class to accommodate this new directive, and again, you have to fire up your computer and make the necessary changes to your code.

public class RepairOrder {
            private amazonWebServicesDataAccessLibrary = new AmazonWebServicesDataAccessLibrary();

            public SaveRepairOrder() {
                        amazonWebServicesDataAccessLibrary.Save(this);
            }
}

 

Starting to get the picture here? Every time you get a new software requirement, you have to go back and manually change your code.

The problem is your RepairOrder class is TIGHTLY COUPLED (think crazy glued) to another class that represents your data access library, such as SqlServerDataAccessLibrary, MongoDbDataAccessLibrary or AmazonWebServicesDataAccessLibrary.

When two or more classes are TIGHTLY COUPLED in this kind of relationship, it makes software very hard to change.

This is where POLYMORPHISM comes into play. What polymorphism does is ISOLATE the parts of your code that can change, so that when that piece of code DOES have to change, you can do so

In C# (and other languages like C++ and Java), there is something call an INTERFACE.

An interface is the POLYMORPHIC element that will help isolate changes like our data access predicament.

Your interface will represent the public face of your data access library.

 

public interface IDataAccess() {
            void PersistData(RepairOrder repairOrder);
}

Notice there is no code in the interface. Also notice that the PersistData method takes in a RepairOrder class as a method argument.

So if there isn’t any code, how will IDataAccess work?

You will create new classes that handle the persistence of your repair order. Each of the classes below IMPLEMENTS (provides the actual functionality) for IDataAccess

 

public class MicrosoftSQLServerDataAccess : IDataAccess() {
            public void PersistData(RepairOrder repairOrder) {
                        // code to persist a repair order to Microsoft database
                        // goes here
            }
}
public class MongoDbDataAccess : IDataAccess() {
            public void PersistData(RepairOrder repairOrder) {
                        // code to persist a repair order to a MongoDB nosql database
                        // goes here
            }
}
public class AmazonWebServicesDataAccess : IDataAccess() {
            public void PersistData(RepairOrder repairOrder) {
                        // code to persist a repair order to an Amazon Web Services
                        // cloud database goes here
            }
}

 

Back in the main RepairOrder class, we change the class member to use IDataAccess.

public class RepairOrder {
            private IDataAccess dataAccessLibrary = new SqlServerDataAccessLibrary();

            public SaveRepairOrder() {
                        dataAccessLibrary.PersistData(this);
            }
}

 

But you’re probably going to quickly point out we’re still tightly coupling the generic IDataAccess interface to an instance of the SqlServerDataAccessLibrary, which is absolutely correct.

There’s another concept related to polymorphism called DEPENDENCY INJECTION. A dependency is any other class the RepairOrder class needs to get it’s job done, which in this case is the SqlServerDataAccessLibrary.

Using the concept of dependency injection, we will PASS IN the reference to IDataAccess into the RepairOrderClass via the class constructor.

 

public class RepairOrder {
            private IDataAccess dataAccessLibrary = new SqlServerDataAccessLibrary();

            public RepairOrder(IDataAccess dataAccessLibrary) {
                        this.dataAccessLibrary = dataAccessLibrary;
            }

            public SaveRepairOrder() {
                        dataAccessLibrary.PersistData(this);
            }
}

 

We have now removed any direct class instantiations inside of RepairOrder.

But wait, you say, you’ve only moved the class instantiation problem OUTSIDE of the RepairOrder class.

Again, there’s another concept related to polymorphism, called Inversion of Control, which will map the interface to a specific class.

In fact, there are things called Inversion of Control containers or “IoC containers” which will let you make those mappings between interfaces and the classes that must implement them, during runtime instead of compile time, via configuration files.

That way, if I need to map IDataAccess from the SqlServerDataAccessLibrary class to the AmazonWebServicesDataAccess class, I can use the IoC container to change the mapping in a config file and voila! The RepairOrder class won’t have to change, and you won’t have to recompile, test, and redeploy your application!

Polymorphism is probably the most complicated of the 3 tenets of object oriented programming to understand.

But once mastered, you have a powerful software design tool that helps you address the biggest problem in software development…the need to easily change your software.

Ready for Your Next Job?

We can help! Send us your resume today.


Need Talent?

Submit your job order in seconds.


About ProFocus

ProFocus is an IT staffing and consulting company. We strive to connect a select few of the right technology professionals to the right jobs.

We get to know our clients and candidates in detail and only carefully introduce a small number of candidates that fit the role well.