Idea is one thing, implementation is another.
OOP is an idea. Its implementation through programming language is another.
For an OOP language like Java, it prefers, oh let me rephrase that, Java dictates that nouns are first-class citizens of Javaland (see the great post Execution in the Kingdom of Nouns). Add to that Java’s verbosity and it’s no wonder, not everyone loves Java. The implementation after all is the culprit.
But let’s dissect OOP from a pure abstract view (courtesy of The JOT Blog):
1. What is the paradigm of OOP? Procedural, Logic, Functional? Well, it’s none of the above. OOP tends to focus first on the taxonomy and relationships between classes (see Class-based vs Prototype-based languages).
In contrast, prototype-based programming is seen as encouraging the programmer to focus on the behavior of some set of examples and only later worry about classifying these objects into archetypal objects that are later used in a fashion similar to classes.
In essence, it’s the classic philosophical debate of Plato’s abstract forms + Aristotle’s taxonomy VERSUS Paul Feyerabend’s anything goes. In prototype-based programming, there are no classes.
Or to quote Zaemis blog:
OOP focuses primarily on the object and expresses actions in terms of the object’s abilities. A airplane object can be flown (Airplane.fly()). A door object can be opened (Door.open()). But we really don’t view the world in terms of objects and what actions can be done to them. It’s backwards. We view the world in terms of ourselves and our abilities. We are the ultimate object. (And no, I don’t mean a God object.)
Classes drive me crazy. That might seem strange, so let me explain why.
Clearly classes should be great. Our brain excels at classifying everything around us. So it seems natural to classify everything in OO programs too.
However, in the real world, there are only objects. Classes exist only in our minds. Can you give me a single real-world example of class that is a true, physical entity? No, I didn’t think so.
Now, here’s the problem. Have you ever considered why it is so much harder to understand OO programs than procedural ones?
Well, in procedural programs procedures call other procedures. Procedural source code shows us … procedures calling other procedures. That’s nice and easy, isn’t it?
In OO programs, objects send messages to other objects. OO source code shows us … classes inheriting from classes. Oops. There is a complete disconnect in OOP between the source code and the runtime entities. Our tools don’t help us because our IDEs show us classes, not objects.
In other words, OOP can be restricting our organic process of modeling the problem, since the world is more complex and dynamic than what our minds conceive.
3. Nouns and Verbs
OOP is basically about nouns, functional programming is about verbs. Wouldn’t it be more straightforward to just call procedures instead of wrestling your way studying the methods wrapped up in objects? No more lost productivity in class-based OOP traps. You attack the problem as you gain more understanding of it, then when your solution gets relatively stable, maybe that’s the time you can refactor it into an object-oriented model.
4. Joel Spolsky wrote about OOP
But JavaSchools also fail to train the brains of kids to be adept, agile, and flexible enough to do good software design (and I don’t mean OO “design”, where you spend countless hours rewriting your code to rejiggle your object hierarchy, or you fret about faux “problems” like has-a vs. is-a). You need training to think of things at multiple levels of abstraction simultaneously, and that kind of thinking is exactly what you need to design great software architecture.
You may be wondering if teaching object oriented programming (OOP) is a good weed-out substitute for pointers and recursion. The quick answer: no. Without debating OOP on the merits, it is just not hard enough to weed out mediocre programmers. OOP in school consists mostly of memorizing a bunch of vocabulary terms like “encapsulation” and “inheritance” and taking multiple-choice quizzicles on the difference between polymorphism and overloading. Not much harder than memorizing famous dates and names in a history class, OOP poses inadequate mental challenges to scare away first-year students. When you struggle with an OOP problem, your program still works, it’s just sort of hard to maintain. Allegedly.
Which brings us to the concept of programming paradigm.
Imperative or procedural programming tends to be natural for newbie programmers. It is chaotic but you can make your code modular.
On the other hand, OOP tends to fit certain scenarios where your code is sculpted (so to speak), meaning it is relatively static and doesn’t change that much often compared with dynamic business applications.
Case in point: Delphi IDE (an example of STATIC APPLICATION).
The class hierarchy built into the IDE speaks volumes about the effectiveness of OOP. Why? Because the classes themselves are well-defined and have clear-cut functionality. For static projects like this, OOP is a better fit.
However, for business apps that require dynamic changes due to business directives and other competitive factors, OOP with classes is a pain during design and development.
Case in point: the classic disconnect between relational databases and OOP classes for DYNAMIC APPLICATIONS
In other words, there is a disconnect between classes and objects.
Here’s the rationale behind prototype-based languages:
Traditional class-based OO languages are based on a deep-rooted duality:
- Classes define the basic qualities and behaviours of objects.
- Object instances are particular manifestations of a class.
For example, suppose objects of the
Vehicleclass have a name and the ability to perform various actions, such as drive to work and deliver construction materials.
Bob's caris a particular object (instance) of the class
Vehicle, with the name “Bob’s car”. In theory one can then send a message to
Bob's car, telling it to deliver construction materials.
This example shows one of the problems with this approach: Bob’s car, which happens to be a sports car, is not able to carry and deliver construction materials (in any meaningful sense), but this is a capability that
Vehicles are modelled to have. A more useful model arises from the use of subclassing to create specializations of
Vehicle; for example
Flatbed Truck. Only objects of the class
Flatbed Truckneed provide a mechanism to deliver construction materials; sports cars, which are ill suited to that sort of work, need only drive fast. However, this deeper model requires more insight during design, insight that may only come to light as problems arise.
This issue is one of the motivating factors behind prototypes. Unless one can predict with certainty what qualities a set of objects and classes will have in the distant future, one cannot design a class hierarchy properly. All too often the program would eventually need added behaviours, and sections of the system would need to be re-designed (or refactored) to break out the objects in a different way.
The lesson here is not that Java is bad. Java the programming language may be bad, but not JVM, the Java Virtual Machine. JVM is great and it is considered a platform. There is a reason why there are many languages that target the JVM.
The gist is that you have to know what you are going into when you program in OOP with classes. Sure, it has its advantages and you will get your work done, but there are pitfalls. If you don’t know the theory behind programming paradigms, technical debt will certainly haunt your projects.