DEV Community

yucer
yucer

Posted on • Edited on

OOP vs FP and the quest for reality

There was a past discussion topic introduced by this article that keep also my attention.

The sub-topic that I found more interesting is the descriptive power of Object Oriented Programing (OOP) and Functional Programming (FP) to represent the reality and the problem domains.

I must recognize that I am not an expert in FP, but I disagree some assertions stating that OOP was not a good paradigm to represent the reality and model the problem domain.

So I will present the way I see it, according to some authors of OOP and Semantic Computing.

OOP, the mind and the language

In the basic OOP there are classes and objects.

objects are the computer representation of real world entities.

clases are a concept used to describe a set of objects that have the same structure and behavior.

As a software engineer, and probably a team leader... your task is to divide the complexity of the software (given by its requirements), divide it, and make it flow over your team or sub-teams.

Classes fit very well to encapsulate that complexity. But the theory of complexity says that the complexity of the system is not the mere total of the complexity of the components. New complexity arises and move to the relationships between the components.

Just the fact that the complexity can divided (remember: divide and conquer) is a property inherent to the real world and a valuable gift of nature.

Now the relationships used in the OOP are taken from the theory of complex system, Gnosiology, linguistics. And that's because programming is a process of communication with the computer and allow those branches of knowledge are essential for that process.

The basic relationships in OOP are called inheritance, composition and use, but they represent real relationships from our everyday communication and reasoning like Hyponymy and hypernymy, Meronymy and Holonymy

If you check carefully, you'll find that those relationships form hierarchies from which we might barely escape, if it is possible. Everything that we can truly understand and describe falls into one of those hierarchies.

Of course those hierarchies doesn't have "methods", because methods is the OOP syntax to describe behavior and the behaviors are described at the level of set of objects (classes). Describe the same behavior object by object is impractical, and the fact that so many objects share the same behavior and structure make it easy for us to describe them.

Is OOP intuitive ?

Describing objects as sets is a natural process, if you ask a child:

  • what is this (and point to a chair)

he would answer you with the name of the concept (set, class, type or as you like):

  • it is a chair

and that is because we trend to classify everything when learning new stuff. We don't "save" in our mind the whole spec of a chair, we learn which is the difference with the nearest concept that we have learn before. The dictionaries hold definitions in that way, a chair would be in the merriam-webster's definition:

a seat typically having four legs and a back for one person

You can navigate upwards in the hierarchy through the hypernymy for a seat, and you would reach a more general concept.

The Princeton university built a database called Wordnet with the ultimate goal of relate every known concept. You can use Artha thesaurus to browse over it in your local machine.

That is normally what a person does when learning from a problem domain: use the dictionary looking for the key concepts. The OOP methodologies use to extract those concepts from the requirement texts and then promote some of them to external actors and uses cases that later become packages, module, clases, methods, ...

If you note the chair definition is also involved into one composition (holonymy) relationship:

... having four legs and a back

It was not OOP who defined that "a seat with for legs and a back" defines a new function different from its separated components, it is the reality.

Ok, it imposes new relationships with new complexity: the legs and the seat should be assembled properly, and also one state (the dimensions of the legs should hold the chair in equilibrium).

If you look carefully the definition has an extra text:

... for one person

and that is a relation of use.

So there you have... looking into the dictionary we know how intuitively how to model in OOP the basic entities of a product parts in stock inventory, or maybe a chair assembly process, etc.: three classes, three relationships (two of structure and one of behavior or use).

So it is very intuitive right ? It might be also easy to represent in FP... but what I disagree with, is the attack to OOP as wrong approach to represent the world... or the assertion that nature is not organized that way. At least our mind does it.

Hierarchies ... hierarchies...

What usually happens in the real world is that normally objects belong to more than one hierarchy with different inheritance and compositions relationships (for example the leg has both a meronym of seat and also is an hyponym of a more general concept). The Wordnet database, by example, seems a graph and that is what happens when you mix many hierarchies together.

The people gets confused in that case, and the OOP self did try many ways to express that. In the past people try to implement it using multiple inheritance and later the Mixins were used. It is true that OOP implementation in some languages allows to use it bad, but that's the reason why one should read the theory. It might also be that OOP needs to incorporate more relationships or grow in some way.

State vs Behavior: The trade-off for Applications

If I understand properly the FP itself use a lot the composition, but in the language structures itself. Compositionality is listed as one of the main traits of FP in the Comparison_of_programming_paradigms

What I mean is that one of the FP advantages seem to be the capacity to express many hierarchies in just one big hierarchy (of code). I need to learn more of the advantages of that. Nevertheless I still see a gap to fill: the state. They need to simulate it... and the tricks to do it seem to be not so pure methods.

And I can see that reflected into the listed applications in the industry. Most of them are applications where is not so important to maintain a concurrent state (transmitting messages, control a robot, process data in pipelines, statistics for BI, load a user interfaces, etc.).

Some years ago... 85% of the applications in the market were database-centric: most of them in business management (accounting, stock, purchase, sales, inventory). I have heard that some business, that provide booking mechanisms, compensate the client when they have overbooked... but in payment applications or accounting allowing the operation is not appreciated. If you have two parallel process with immutable copies of the same state... how do you guarantee the concurrency without a shared state ?

Two sides of the same coin ?

Computers have two main powers that make them valuable to appliances, because they exceed the human capacity: the capacity to remember (storage) and process big amount of data with accuracy.

Even the complexity of algorithms is estimated by a factor of the memory used and the processing speed. It is not a secret that FP implementations allows to handle better the parallelisms and hence the processing speed, but which are the precise limitations that impose that gain in terms of storage ? Specifically in the accuracy of storage ?

It seems to be a trade off between describing the behavior (FP) and the structure and state (OOP) of the problem domains. I think what F# seems to do is combine both of them. I guess one can describe the inner implementation of methods (that is in fact the message passing between the objects) and the message brokers using FP, but use the classes to incrementally specify the behavior of the set of objects.

And what about the reality ?

At the end, the victory in the battle of determining which programming paradigm is the best would be a Pyrrhic_victory. Every programming paradigm seem to be useful for specific contexts.

But it is really interesting the question about how the reality really works. It is more imperative or more declarative ? It is more like OOP or more like FP ? Does it have a shared state or immutable states ? Does it have an organized structure by itself or we human build the relationships in our mind ?

As exposed in the book Object Oriented Analysis and Design with Application and previously in this article... the complexity of the real world seems to follow the structural patterns in all kinds of organization of the matter (from the quantum particles to the big galaxies).

Our mind seems to have evolved to profit from that accidental or planned organization of the complexity and we organize and classify the concepts in our mind using that way. Given that OOP was based in the science that study the acquisition and representation of knowledge it is bulletproofed to represent Structure.

And what about the Behavior ? Is better represented by FP ?

to be continued...

Top comments (1)

Collapse
 
fabricehategekimana profile image
fabriceHategekimana

Hi, thanks for your post ! I also agree that OOP and FP make a great team !

To be honest, although OOP do a great job, FP is still way better at representing things from the real world. Because classes make only a small proportion of all the representable types (product types, sum types, union types, etc.)

For instance, one can represent things with product types (struct/class) as a "and" logic and union types (typescript union) as a "or" a "and" and "or" logic.

What is a chair ? That's for legs "and" a back so one can create a struct with those 2 fields

struct {
    legs: [Leg],
    back: Back
}
Enter fullscreen mode Exit fullscreen mode

What is a seat ? Thats a chair "or" a bench "or" a sofa etc. So "or" can be replaced by "|" to give:

type Seat = Chair | Bench | Sofa
Enter fullscreen mode Exit fullscreen mode

If you want more flexibility (but you have to work with nominal typing) you can use an abstract type (like interface in OOP) instead of an union type. If you want more safety (but you have to work with structural typing), you can throw everything and directly work with a sum type (like dart's enums)

I also fell into the trap of thinking that objects are the main focus of OOP. Alan Kay, one of the founder of OOP and Smaltalk wrote a mail about this topic. OOP is not about class or inheritance but message passing and intercommunication in a network of objects. The real power of OOP is to create dynamic/evolving/adaptative systems and protocols

I didn't know about all those linguistic concepts and I love that ! I think OOP and FP do a really nice job together !