As I started to do interviews with new candidates to our team, I just realised that object oriented programming is a topic which is really not clear for most people. For the question: “Do you know what is object oriented programming?” I usually got the answer: yes. For the follow up question: “Could you briefly tell me what it is?” I never got twice the same answer. I got a lot of good answers and a lot of answers which did not really match with my understanding. And at a point, I started to think about how I would answer this question and I realised that it is not easy at all.
There was another example: I needed to reuse an already existing C++ code for my component. It was basically one class with around 200 functions and 100 variables, all of them were
public and it was pretty unclear what they are standing for. After an analysis, I just figured out that I cannot reuse it as it is, because of multiple reasons:
- It was using a third party logger, which I did not want to include to my project.
- The program which was using it originally was based on TCP/IP communication. Most of the functions were throwing exceptions if the TCP communication was not set up properly even if they had nothing to do with that.
- Some of the member variables were used in multiple functions with totally different purposes. So if you wanted to call a member function from outside, first you needed to set up ca. 10 member variables to the correct values to be able to get some results from the function.
All things considered, I just decided to refactor this piece of code before reusing it and it took me a long time to figure out how to do it, because a lot of functions needed to be decoupled to a separate class and it needed to be figured out what effects are made by each variable for the different functions. It was a nightmare. As the customer asked me why this refactoring was needed, I just replied: “Because it was not implemented in an object oriented way.” At this point, he told me: “Why not, it was all implemented inside a class, so it was object oriented.”. OK, from a technical point of view, it was implemented inside a class, so it was object oriented, on the other hand, it was not following anything that means object oriented programming for me.
In this article, I’d like to show you that object oriented programming is not just about using the related programming language elements, it is something much more than that. In my view, you can also do object oriented programming in languages which are not supporting that officially (like C) and you can also work in a non object oriented way in pure OOP languages (like Java or C#). Let me show you my understanding about OOP.
Principles of Object Oriented Programming
First of all, let’s see the official definition of OOP. I found a clear definition here.
“Object-oriented programming (OOP) is a software programming model constructed around objects. This model compartmentalizes data into objects (data fields) and describes object contents and behavior through the declaration of classes (methods).
OOP features include the following:
- Encapsulation: This makes the program structure easier to manage because each object’s implementation and state are hidden behind well-defined boundaries.
- Polymorphism: This means abstract entities are implemented in multiple ways.
- Inheritance: This refers to the hierarchical arrangement of implementation fragments.
Object-oriented programming allows for simplified programming. Its benefits include reusability, refactoring, extensibility, maintenance and efficiency.”
Let’s stuck first at the features:
- Encapsulation: I think this is the most important one. Each of the objects has a state which is hidden for other objects. And on the other hand, there is an “implementation” for each object. I understand under that the member functions of the objects. And the state and the implementation together is one unit or with OOP terminology one object. So if your object is a rectangle, it will have a state with elements like
colour, etc. And it will have an implementation, implemented member functions, like:
paint, etc. And this is one object, not less, not more.
- Inheritance: I would mention it before the polymorphism, because otherwise, it is difficult to understand it. Inheritance stands for the connection between parent/child classes alias base/inherited classes. So for each class, you can define so called child classes which can do everything that the base class can to (has the same
public methods and member variables), but it can overdefine the implementation of the methods and it can extend the functionality (introduce new member functions and member variables). For example, you have a class for animals. Each animal can move itself. But how they can move themselves if different for each animal. So the different animals will be inherited from the
Animal base class and will override the implementation of
move method. Plus some
animals have some extra skills, like a
bark. So you can define a
bark method for the
- Polymorphism: This is exactly what I told about the
move method of the
animals. You can have, for example, a collection of
animals and you can call the
move method for each of them and you shouldn’t mind how it is implemented for the
That’s the official theory. Let’s go further with some practical theory.
Objects and Classes and the Connections Between Them
From the name of object oriented programming, we can see that objects are the basic units behind this paradigm. The next important feature is the class. But what is the relationship between objects and classes: class is in fact a collection, a template for similar objects, for objects with the same methods and member variables. So if you are having a
rectangle, then you will have a
rectangle object which is an instance of
Rectangle class. The
So when you are planning an object oriented program, first you always need to think about what kind of classes you will need in your program.
The other important question is: what are the connections between these classes.
There are 4 types of connections between classes:
That means that the connected class is belonging to our class. They have the same lifetime (they are created and deleted at the same time). Our class cannot work without the connected class. Like if we have a class called
House and a class called
Wall, then most likely, there will be composition between them.
Aggregation between class
B means that class
A has an instance of class
Car has an
Owner. But the
owner can exist also without the
car, and the
car can exist without the
owner can change any time.
Association between class
B means class
A is using an instance of class
B. Usually, this relation between the objects is just a short term relationship, only during the run of the specific function. For example, you have a class and it has a
Log function. But this
Log function needs an instance of the
Logger class as a parameter. This is a typical example for association.
This is the relation type already mentioned earlier. It means class
A is a special case of class
B. It’s also called as child/parent class as well.
So the next to do is to decide what kind of relations are there between your classes. It’s good to do some graphical modelling for your classes to have a better overview. For that, the class diagram of UML is a good tool. I would propose to always do a plan of your classes at least on a paper before starting to program.
There are two additional definitions I wanted to clarify:
State of the object: In fact, this built up based on the current value of all member variables. So if you are changing at least one member variable, the state of your object is also changing.
Public interface of the class: This is all the methods and variables which are
public, which are visible from outside of the class.
Based on that, you can do a plan of your needed classes, but there are still some so called “best practices” in OOP programming.
These best practices are called SOLID. This stands for the following:
- SIngle Responsibility Principle
Each of your classes should have a simple clear responsibility. You should be able to describe the purpose of the class with one sentence without using the words “and” and “or”. So yes: huge classes are most of the cases against this principle.
- Open/Closed Principle
Your code should be open for extensions, but closed for modifications.
- LIskov Substitution Principle
This is maybe a bit more complicated. But it means that each of your parent classes can be replaced with any of its child classes without breaking the functionality. This is coming from something called “Design by contract”. I plan to write a separate article about this topic.
- Interface Segregation Principle
Your interfaces shall be small and clear and having one well-specified purpose. So you should avoid having interfaces which are returning a lot of data. So the
public interface of your class needs to be well designed and easy to use. Make everything
public is not a good practise.
- Dependency Inversion Principle
You should design your classes in a way that the classes which are dependencies of your class can be set through some setter functions or constructor parameters. So that you can change them to any subtype later on. So for example, if you have a
Logger class which is used to create log files and you can change it though a setter function, you can change your
Logger between an
JSONLogger or a
SimpleLogger if all these classes are derived from the same
Logger base class. It is also helpful if at unit testing, you need to mock your dependencies.
Let me extend it with my own suggestions:
- Always try to keep all member variables (so the state of your class)
private and use setter and getter functions for more control.
- Always try to design a user friendly
public interface for your class.
- Avoid the long parameter lists at your member functions, in that case, always think about transforming some parameters to member variables if it really makes sense.
- Read about object oriented design patterns and try to use them always when it is possible.
Object Oriented Programming in Practise
Now after getting familiar with all theory, I wanted to include a short practical example. This is about implementing a
Canvas which can visualise different shapes, like
A not really object oriented solution would be to create one
Canvas class with member methods like:
drawCircle, etc. But this solution is not nice, it is not using the features of object oriented programming and it makes it difficult to extend your code (it is against open/closed principle).
Based on that, my proposal would be the following:
Canvas class. It should have a collection of shapes (aggregation with
Shape class). It should also have member methods like
addShape for adding new shapes or
deleteShape for deleting already added shapes. It should have a
drawAll function which draws all added shapes.
Shape is a base class which has a
draw method. Each shape has a (composition)
size and a
Position is a class with attributes for
Size has a
width and a
height attribute. Each specific shape (
Star) are child classes of
shape. So that each of them has a
Size and all of them should implement the
draw function. With this solution, it is pretty to easy to extend the program with new shapes (just implement new child classes) to change the representation of
position to other coordinate system.
This modelled and visualised in a UML class diagram should be something similar:
If you are an experienced software developer, maybe I did not tell you anything new, but based on my experience, a lot of programmers have a non-clear understanding about this topic, so I really hope I could help a lot of them. Based on my experience with this understanding, you can ensure a much better quality for your work.
I'm a software developer with around 5 years experience. Actually my main focuses are the following: software architecture, technical project leading, coaching, quality assurance and C++ development.
Next to that I'm blogging under: http://howtosurviveasaprogrammer.blogspot.com