loading...

Object-Oriented Programming Strikes Back!

riccardo_cardin profile image Riccardo Cardin ・6 min read

Originally posted on: Big ball of mud

Disclaimer: the post contains some humor. If you are sensible to humorism, please, do not continue to read.

Recently I read the article Beginning to Doubt Object-Oriented Programming on DZone. It is not the first post that I find on a blog that praises functional programming with respect to object-oriented programming. For all of this posts, object-oriented programming is dead (more or less). I think that at the basis of all this posts there is a misunderstanding over what functional programming really is. Now it's time for me to give my two cents to the fight among different programming paradigms.

First of all, I want to say that I respect the opinion of the author of the above article. What I am going to say it is my personal point of view on the issue. There is no an absolute right or absolute wrong opinion on this dilemma. So, peace and love to everyone.

What is functional programming?

I think that to better understand my point of view on functional programming, it is important to first understand what I mean with this term.

In computer science, functional programming is a programming paradigm [..] that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

This is the definition given by Wikipedia. Did you read any references to lambda expression? Nope. So, abusing of lambda expression in your code does not mean you're using functional programming paradigm.

Batman does not like functional bulls!

First of all, you need referential transparency, which means that any time a function is called with the same inputs must return the same output. A precondition to implement referential transparancy correctly is the immutability of state. Once a structure (can we say a type?) is created, it cannot be subsiquently modified in any way.

Easy? Referential transparency means no side effects, no exceptions thrown, no reading from external sources and so on. How can we be productive without these capabilities?

The hard part of the story

It seems that we are stuck in a black hole, doesn't it? I cannot have side effects inside a function (not that bad), I cannot signal to function callers that something could go wrong, I cannot access to any external resources. Oh Gosh!

Have you ever heard about Monoids, Functors, Monads? These are structures coming directly from category theory, a branch of Mathematics. Describing these structures are behind the scope of this post, but let's do some examples.

I know for sure that you are using at least some Monads in your code. If you are a Scala developer, probably you used Option[T] type, or Either[T, E], or any kind of collection such as List[T], Set[T] and so on. If you are a Java developer you can take into consideration types like Optional<T>, Collection<T> and Stream<T>. All of these types are Monads.

These types have nothing in common from a behavioural point of view, which means that Monads are a mechanisms to share some properties (basically, code reuse) among different types that are not directly related to each others. What does this mean? Quoting the book Scala Design Patterns,

monads are structures that represent computation as sequences of steps. Monads are useful for building pipelines, adding operations with side effects cleanly to a language where everything is immutable.

Let's borrow the definition of Monads from the excellent book Functional Programming in Scala

A monad is an implementation of one of the minimal sets of monadic combinators (i.e. unit and flatMap), satisfying tha laws of associativity and identity.

Monadic combinators? Associativity? Identity? Unicorn? Wtf?!!? I am a simple developer: I hear about mathematics, I change programming paradigm.

Functional programming is easy :P

Where do I want to go with this dissertation? The real functional programming really deals with mathematical laws and theories. If you develop your programs following these laws, you will benefit of a bunch of good properties, such as composability, testability, thread confinment, coming directly from mathematical theory.

However you need to study and learn mathematics. Little drops of Category theory will wet your face.

Object-oriented Programming

What about Object Oriented programming? Have you ever heard about boring mathematical laws you have to follow? Have you ever heard about esoteric terms like monads or functors, or anything else? Have you ever applied some mathematic theory to your object-oriented programs?

Nope. The beautiful thing about object-oriented programming is that is almost math-free. Everyone can start to study and learn an object-oriented programming language such as Java, C++ or Kotlin. At first sight, object-oriented programming is very close to how we perceive reality.

As human beings living in the lucky part of the world, we know that every car is made by an engine, some wheels, a body and so on. We understand what a Car type means and why it owns attributes of type Engine, Wheel and Body.

Object-oriented programming is easier to learn than functional programming. Stop. This is the only truth. Both paradigms exist more or less from the beginning of Computer era (think about Lisp, for example, which is born in 1958). Have you ever heard about an operating system written in a functional programming language? Nope.

Simplicity leads to tradeoffs

Simpler means less constrained. Less constrained means less formality to respect. Less formality means that is simpler to use the programming language's features in an erroneous way.

Take the definition of monads that we gave just a moment ago. In the definition the constraints that a type must fulfill to be considered a monad are clear. Math does not lie.

Now, take any principle of object-oriented programming: For example, the Single Responsability Principle. The principle states that

A class should have only one reason to change.

What the f**ck is a reason to change? Where is all the mathematical magic that principles that apply to functional programming languages have? No trace.

Neither the definition of coupling, which is at the base of all the theories related to object-oriented programming, is defined in a formal way.

Coupling between components measures exactly their degree of dependency.

Ok, so, how can I measure the degree of dependency between components? No formal way. I tried to give a mathematical definition of such concepts in one of my past posts, Dependency, but it was only an attempt.

The lack of rigorousness in principles definitions leads to principles' interpretation. Personal interpretation often leads to errors and bad practices.

Conclusions

Having discussed the differences between functional programming and object-oriented programming paradigms we discover and understand an important concept, which is:

The more a programming language is easy to learn, the easier it is to make mistakes using it.

The following graph tries to show visually the meaning of this sentence.

Programming language curve

Finally, object-oriented programming languages are not going anywhere. We will continue to use them, because they are easy to learn. Also functional programming languages are here to stay. Everytime we need to ensure some nice properties relative to our programs, they will help us a lot.

The world is full of tradeoff. So, stop this war among programming paradigms and start to get the best from both sides of the force.

Yoda do it better!

References

Posted on by:

Discussion

markdown guide
 

The funny thing about this

| At first sight, object-oriented programming is very close to how we perceive reality.

is that we don't actually perceive reality as a set of objects.

| It misunderstands the fundamental fact about evolution, which is that it’s about fitness functions—mathematical functions that describe how well a given strategy achieves the goals of survival and reproduction. The mathematical physicist Chetan Prakash proved a theorem that I devised that says: According to evolution by natural selection, an organism that sees reality as it is will never be more fit than an organism of equal complexity that sees none of reality but is just tuned to fitness.

We actually perceive reality using a set of functions! :D

 

Not really understanding what you're saying here.

 

It's easy to think that we perceive a world of objects, but we don't.

We perceive a world of tools and obstacles and add a layer of object definition on top of that. So fundamentally, we see things in terms of their functional use: ie, we actually interpret the world as a functional place rather than an object-oriented place.

theatlantic.com/science/archive/20...

And furthermore, it seems that our consciousness is also composed of lots of functional streams in our brains.

I partially agree with you. I think you're really describing how we behave, and not how we perceive reality. You said that we peceive "tools" and "obstacles": these are objects. ;)

Anyway, interesting point of view. Many thanks.

It's not a point of view, it's how neuroscience is working out our interpretation of the world.

A tool is something that has utility (this input gives this output). An obstacle is something in the way. An object is a layer of interpretation on top of those properties.

In other words, you can sit on a chair without needing to know that it's a chair. Say that you were blindfolded and someone put your hands on a flat place. You would be able to turn around and sit on it without needing to know anything else about it - it's a sitting place. That's the utility. Functionally you input your butt and output your body at rest.

Take off the blindfold and you could see that it's a chair, or a stool, or a stump, or a cliff's edge. Doesn't matter, they are all sitting places. You perceive the object after you perceive the utility, but the natural (and completely reasonable) assumption that people had for thousands of years was that we perceived the object and then perceived the utility. Objects are results of categorization made possible by consciousness, but the systems that consciousness is built on don't require objects to operate (obviously, or the animals who use them would be unable to operate).

That's ok. My focus was not on neuroscience studies and recent goals, but on programming :)

Sure. My point is that learning to see problem-solving techniques as composable functions may actually be closer to our innate problem-solving paradigms than Object-oriented techniques are.

 

Some random thoughts:

  • some applications are definitely better suited by one style or other. Even with arrows and bananas doing UI stuff in Haskell is still quite painful.

  • if we take that Alan Kay knows about OOP, then Java, C# etc. are not really OOP. Which bring us to the conclusion that we are switching from pseudo-oop to pseudo-fp.

  • SOLID... well don't let me start about SOLID. It seemed a good idea at the time and we can leave it at that.

  • when you start seeing Catamorphisms everywhere, then you can call yourself functional programmer.

:))

 

You seem to be such a FP guru! :D

 

These are not antitheses of the other, nor are they the only "orientation" in programming, nor are they or any other methodology a panacea for effective programming. They are tools. And often the wrong ones to use.

 
 

FP is great in the right hands. Making the transition from OOPs can be a difficult one. Having written Clojure for 2 years, it took a solid year to adapt and write clean maintainable code. Once you get over the learning bump, programming in a FP paradiam is great fun. The biggest thing I got from the experience was a new way of looking at problems. Alot of these techniques can be applied in languages like Java.

 

A modern application shouldn't be written without using concepts from a variety of different paradigms. I'm trying to keep a good overview of them here.

That said, I don't think functional programming is good at modelling the state transitions of a system, and should be limited to calculation domains where it is a preferred choice. The problem with state modelling via state variables and monads is that it doesn't actually model what the system is doing anymore. It's a bad mapping from an imperative, concurrent, domain into a functional one.

The relation between learning curve and level of errors is just wrong. By such logic I could start writing my C++ using nothing but Korean language for comments and symbol names and my programming would suddenly have fewer errors. An inappropriate choice of paradigm is what leads to errors, and this is the reason why all apps generally use bits of all paradigms.

 

I'm not sure I can agree with your assertion that state transitions are less clean in FP. In OOP, we model state transitions by delegating to objects that perform an appropriate action for the current state. In FP we model state transitions by delegating to a function that performs an appropriate action for the given state. It's just two ways to skin the same cat.

 

I agree with the first part of your comment, that reflects exactly the same conclusions I came to. However, you misunderstood the graph that relates learning curves with probability of introducing an error in a program.

 

I'm really surprised there isn't some paper proving that OOP and functional are two manifestations of the same thing. For example this article on how category theory can be implemented in OOP - using Java as the example reperiendi.wordpress.com/2007/11/0...
Mostly via interfaces.

I also think it's interesting to note that Martin Odersky designed Scala as a "fusion of functional and object oriented paradigms". The reasons for that are partly to ease the learning curve and to enable compatibility with existing Java (and .NET, whatever happened to Scala.Net?) although more importantly to create a composable, modular, scalable language that benefits from the best of multiple paradigms. Essentially, Scala is not a Functional only language, by design.

 

There actually was an OS written in functional programming language: Genera OS. It was used to operate Symbolics Lisp Machines. :)

 
 

Have you ever heard about an operating system written in a functional programming language? Nope.

If you're going to kick a Junior dev around at least be correct.

House.

 

Yeah, it was a provocation. Thanks for the link :)

 

I do not agree with you. I mean, you're right when you said that both paradigms have their own use cases. However, I think that you can achieve the best of both using them in conjunction. "FP in a OOP shell".