How to Write a Really Object Oriented Program






4.65/5 (15 votes)
There's a lot of program code organised into classes, but are they really object oriented?
Introduction
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.
It says:
“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
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 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 theAnimal
base class and will override the implementation ofmove
method. Plus someanimal
s have some extra skills, like adog
canbark
. So you can define abark
method for theDog
class. - Polymorphism: This is exactly what I told about the
move
method of theanimal
s. You can have, for example, a collection ofanimal
s and you can call themove
method for each of them and you shouldn’t mind how it is implemented for theanimal
.
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 rectangle
class defines that it needs to have a size and a position and the object holds its exact size and position. There are programming languages (like JavaScript) where it is not needed to define the class of an object. In this case, objects are created based on so called prototypes.
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:
- Composition
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 calledWall
, then most likely, there will be composition between them. - Aggregation
Aggregation between class
A
andB
means that classA
has an instance of classB
. LikeCar
has anOwner
. But theowner
can exist also without thecar
, and thecar
can exist without theowner
, theowner
can change any time. -
Association
Association between class
A
andB
means classA
is using an instance of classB
. 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 aLog
function. But thisLog
function needs an instance of theLogger
class as a parameter. This is a typical example for association. -
Inheritance/Generalisation
This is the relation type already mentioned earlier. It means class
A
is a special case of classB
. 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.
SOLID
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 everythingpublic
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 yourLogger
between anXMLLogger
, aJSONLogger
or aSimpleLogger
if all these classes are derived from the sameLogger
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 it 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 width
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) to change the representation of position
to other coordinate system.
This modelled and visualised in a UML class diagram should be something similar:
Summary
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.