Robin C. Martin's "Clean Code" features a section on Procedural Programming vs Objected Oriented Programming which makes a few statements that I was not able to wrap my head around. Could someone care to explain in further detail the thought process behind the statements?
The statements are the following:
Procedural code (code using data structures) makes it easy to add new functions without changing the existing data structures. OO code, on the other hand, makes it easy to add new classes without changing existing functions.
The complement is also true:
Procedural code makes it hard to add new data structures because all the functions must change. OO code makes it hard to add new functions because all the classes must change.
The code example used to justify this statement is the following.
Example of Procedural Code:
public class Square {
public Point topLeft;
public double side;
}
public class Rectangle {
public Point topLeft;
public double height;
public double width;
}
public class Circle {
public Point center;
public double radius;
}
public class Geometry {
public final double PI = 3.14;
public double area(Object shape) throws NoSuchShapeException {
if (shape instanceof Square) {
Square s = (Square) shape;
return s.side * s.side;
}
else if (shape instanceof Rectangle) {
Rectangle r = (Rectangle) shape;
return s.height * s.width;
}
else if (shape instanceof Circle) {
Circle c = (Circle) shape;
return PI * c.radius * c.radius;
}
throw new NoSuchShapeException();
}
}
Now, let's pause for a second here. Let's assume that Geometry doesn't calculate just areas, but also perimeters. Taking the above example as is, it is obvious that:
- Adding a new Shape will force all the functions (area, perimiter, etc) in geometry to change. No existing data structures need changes though, they are just containers of data.
- Adding a new function (such as perimeter) to Geometry is easy instead.
Thus, Procedural makes it easy to add new functions, but hard to add new data structures.
But let's consider the above example written in the quintessential procedural language of all, C. With C we could not write a function such as Geometry's area taking an abstract data type. We instead would have the following method signatures:
int geometry_area(square s)
int geometry_area(rectangle r)
int geometry_area(circle c)
int geometry_perimeter(square s)
int geometry_perimeter(rectangle r)
int geometry_perimeter(circle c)
Considering this, adding a new shape does not force any function to change, contradicting what the author has mentioned. Instead, we will have to implement all behaviours for the new shape each in its isolated function.
Adding a new behaviour instead, will force us to write functions for all existing shapes.
So, overall, I'm a bit confused about the logic behind the author's reasoning.
The author concludes with the following:
In any complex system there are going to be times when we want to add new data types rather than new functions. For these cases objected and OO are most appropriate. On the other hand, there will also be times when we'll want to add new functions as opposed to data types. In that case procedural code and data structures will be more appropriate.