PODS vs OO Programming

Mar 10th 2016 (updated Apr 3rd 2023)

dev

What is essentially "Plain Old Data Structure (PODS) Programming" is often mistaken for actual "Object-Oriented Programming (OOP)". This article aims to differentiate between the two approaches and provide clarity on when to use them.

Procedural Programming in Object Oriented Languages

Using an OOP language does not necessarily mean that the code written in it will be OOP. Procedural and OOP approaches are ways to organize code, irrespective of the language used - that is you can write procedural style code in an Object-Oriented programming language .

The key difference I want to differentiate between procedural and OOP is that in procedural programming, methods operate on data structures, whereas in OOP, objects (data structures) operate on themselves via mutator methods.

In reality, a mix of approaches are typically used in an application and either approach is often fine. However, the misinterpretation of OOP can be disruptive to collaborative development (between those writing OOP code and those who think they are) as well as not getting the benefits of Object Oriented Programming.

Programming with Records

A 'Record' refers to classes that provide only a data structure and have no functionality within themselves. The main examples are classes that consist of only public members, which are the equivalent of a Struct in the procedural programming language C.

1
2
3
class Person {
    public String name;
}

PODS that are really Records

One example of code that appears to be OOP but is not is a class that has private members and public getters and setters, where they just assign and return the member. This is still not considered OOP, as the intention behind this type of class is to use it in a procedural manner.

1
2
3
4
5
6
7
8
9
10
11
class Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

Although using getters and setters is a better practice than directly accessing members as it can encapsulate behaviour, in reality, developers do not often find the need to change the method bodies to take advantage of this. Therefore, the classes remain as they were originally implemented but with a number of methods that are exposed which can make the class harder to change in the future than if it was more closed down.

There are situations where such classes are acceptable within an OOP application, such as when using a framework that requires it (e.g. an ORM), technically, you are writing procedural/functional code in those instances. Though you can write applications this way, and it will largely be OK, it would mean that the code base wouldn't be benefit as much from the advantages that come with real OOP.

Example OOP vs PODS

The below code samples show how the same functionality can be achieved in an OOP language using a procedural approach and an OOP approach.

Procedural

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Doughnut {
 private int percentLeft;

    public Doughnut(){
     percentLeft = 100;
    }

    public int getPercentLeft(){...};
    public void setPercentLeft(int percentLeft){...};
}

public static void main(String[] args){
    Doughnut Doughnut = new Doughnut();

    //Eat up the Doughnut
    while(Doughnut.getPercentLeft() > 0){
        //Take a bite
        Doughnut.setPercentLeft(Doughnut.getPercentLeft() - 10);
    }
}

Object Oriented

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Doughnut {
 private int percentLeft;

    public Doughnut(){
        percentLeft = 100;
    }

    public boolean isEatenUp(){
        return percentLeft <= 0;
    }

    public void bite(){
        if(percentLeft > 10){
            percentLeft -= 10;
        } else {
            throw new RuntimeException("All the Doughnut has been eaten");
        }
    }
}
public static void main(String[] args){
    //Eat up the Doughnut
    Doughnut Doughnut = new Doughnut();
    while(!Doughnut.isEatenUp()){
        //Take a bite
        Doughnut.bite();
    }
}

Some of the benefits of using the OO approach is that if I were to extend the 'Doughnut' functionality, say to have a 'BigDoughnut', in the procedural approach I would need to update the calling code instances to reflect what I want (which could be lot's of places), in the OO instances I would only need to update or extend the object.

With the Object Oriented approach you can change the inner workings of the Doughnut class (e.g. maybe just count the number of bites till "isEatenUp") with absolutely no impact on the calling code. If this object was used a lot in a codebase (lets say 100 different places), you could make a small performance optimisation which would then have a large impact, simply by changing a few lines of code and you would be confident in the impact of such a change. Whereas, if the procedural approach was taken then you would be changing 100 lines of calling code, plus the class itself. You would without a doubt have far less confidence in such a change.

Summary

In conclusion, generally it's best to prefer a genuine Object-Oriented approach, but whichever approach you take make sure that you understand what is and what isn't an object-oriented programming.


Related links