As I started to do interviews with new candidates to our team I just realised that object oriented programming is topic which is really not clear for most of the 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 shortly tell me what is it?” I never got twice the same answer. I got a lot of good answers and a lot of answers which were not really matching 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 an other 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 can not 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 were 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 technical point of view it was implemented inside a class, so it was object oriented, on the other hand it was not following anything what 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: https://www.techopedia.com/definition/3235/object-oriented-programming-oop
*“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 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 width, high, position, colour etc. And it will have an implementation, implemented member functions, like: move, resize, 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 what 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 dog can bark. So you can define a bark method for the Dog class.
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 animal.
That’s the official theory. Let’s go further with some practical theory.
Objects and classes and the connections between them
So when you are planning an object oriented program first you always need to think about what kind of classes will you 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 in the same time). Our class can not 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 A and B means that class A has an instance of class B. Like Car has an Owner. But the owner can exist also without the car, and the car can exist without the owner, the owner can change any time.
Association between class A and 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 definition 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 practises are called SOLID. This stands for the followings:
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.
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 braking 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 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 are can change it though a setter function you can change your Logger between an XMLLogger, a 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 rectangle, circle, triangle and star.
A not really object oriented solution would be to create one Canvas class with member methods like: drawRectangle, drawCircle etc. But this solution is not nice, it is not using the features of object oriented programming and it makes difficult to extend your code (it is against open/closed principle).
Based on that my proposal would be the following:
Create a 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. Position is a class with attributes for x and y coordinates. Size has a with and a height attribute. Each specific shape (Rectangle, Triangle, Circle and Star) are child classes of shape. So that each of them has a Position, 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) of change the representation of position to other coordinate system.
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.