Can you tell a program’s paradigm by looking at it?

I attended an interesting talk the other night at the Milano XP User Group. Uberto Barbini was sharing his thoughts and experiences over using Object-Oriented and Functional Programming together.

Uberto showed us some production code, that he thought was a neat application of FP in a OOP context. The funny thing is that to my eyes it seemed that was neither FP nor OOP; it seemed procedural to me. Uberto argued that it was functional and not procedural, because there was no global state involved; it was a self-contained transformation of data.

That got me thinking. Do I like that definition of “procedural”? I don’t think so. I think that you can tell procedural code when the thinking that goes behind that code is something like:

First I do this.
Then I do that.
If Zot Then I do Blah.
Else I do Blorgh.

When you think of a recipe, or a sequence of steps, then for me it’s procedural. Essentially “procedural” is to model the solution as a process.

On the other hand, functional programming, in my humble opinion, is about mathematical models. You model the problem and the solution with functions, sets, maps, trees and all those abstract and precise mathematical concepts.

What about Object-Oriented Programming then? My thinking about OOP has been in the past that OOP is a natural consequence of writing modular programs. An object is a hidden data structure with a visible collection of operations. Then I understood that this is just one way to look at OOP, and probably it’s the wrong one :-) This point of view is heavily influenced by mathematics (the idea that the operation on an object define a sort of algebra) and by procedural thinking (the idea that programs = data + procedures, just like the title of an old favourite textbook.)

I learned from reading GOOS that OOP is mostly about the messages. There are some intesting and tantalizing quotes from Alan Kay about that. Even more recently I read Object Thinking, and I came to understand that OOP is about modeling the problem with a community of autonomous agents. The way to make OOP shine is to build a simulation of the problem. And I remembered the thrill I once had when I first read about OOP. About imagining these little software robots going about their business inside my programs. An object that can “think” for itself and has a behaviour. Now *that* is what OOP is about!

Back to the original theme, now was the code that Uberto showed to us OOP, FP or procedural? It turns out that it depends! You can’t say by just looking at the code. It depends on the thinking that goes behind the code. Uberto thinks functionally when he thinks about this code. That makes it functional code for him.

Suppose that years later I inherit his codebase. If I have no access to Uberto, it’s pretty difficult for me to reconstruct his mental process. I will probably treat the code as procedural; or maybe OO depending on my way of thinking about this code.

So this is a pretty shocking thought, isn’t it? I thought you could look at a program and tell its paradigm, functional or procedural or OO, just by looking at the code. But I now think you can’t; the three paradigms are not different ways to code; they are different ways of thinking! Procedural thinking is about recipes: follow these steps. Functional thinking is about math: functions and sets. Object-Oriented is about simulations: many independent agents. And this explains why it’s difficult to do OO well. You have to learn a different way of thinking. This is something that I heard Francesco Cirillo say many times. Now I understand it a bit better :-)

7 Responses to “Can you tell a program’s paradigm by looking at it?”

  1. Uberto Says:

    Hi Matteo, of course I don’t agree at all on the first paragraph. :)

    For example let’s take:
    4 – 8*9 + abs(12 -45)

    how do you solve it?

    first I do 8*9 = 72
    then I do 12 – 45 = -33
    if <0 then multiply for -1 = 33
    etc.

    many function have order and if nested
    see also the do-notation in Haskell
    http://en.wikibooks.org/wiki/Haskell/do_Notation

    the main point is that in functional code you take the result of one operation and you put it as input in the following (or you return early for an error). So there is a kind of immutable chain of actions.

    The if in my code where just redirecting the flow (proceed with this function or the other one or return), like the maybe monad in Haskell.

    Instead in procedural code, you read and write on persistent variables, the value of them could not be calculated in advance.

    Saying it in another way: in FP your functions are perfectly cachable, that is given the values of input parameters is always safe return the previously computed result. This is true for my code, but not for procedural code.

    Anyway I agree with you that this is hard to spot if you don't have a functional eye, and usually you need functional programming experience for that.

    I'm also happy for this post because it also helped me to clarify better the problem to myself. I'm working on a new presentation completely about code and code quality. When I'll have something half-baked I'd like to present it at xpug-mi

  2. M[_] Says:

    Secret sauces are following:

    OOP = open recursion
    FP = referential transparency
    Procedural = none of the above

  3. matteo Says:

    Hi M[_],

    I disagree heartily. While it’s true that pure FP has the property of referential transparency, can we say that it’s the essence of FP? I think it’s not, and furthermore I think it gives you very little guidance on how to write effective functional programs. Modelling with mathematical structures is much more likely to be a good guide.

    About OOP, Alan Kay wrote that “messaging” is the key thing. At some other point he wrote that “messaging, encapsulation of state and extreme late binding of all things” is the essential point of OOP. Open Recursion seems to be “late binding of some things”.

    My point here is that most people characterize programming paradigms by some inherent property of the programming languages themselves. But I think that it’s a lot more useful to characterize programming paradigms as different modes of thought.

  4. matteo Says:

    @Uberto

    Even something as simple as

    4 – 8*9 + abs(12 -45)

    can be interpreted as a mathematical immutable structure, or it can be interpreted as a procedure “first I compute 8*9 then…”. Or it can be interpreted as messages sent to objects. What do “8” and “9” represent anyway? They could be integer, rational, complex, floating point numbers… or maybe matrixes or categories. The “-” and “*” could be messages that are sent to these objects, and at some level I don’t know or care to which class they really belong.

    I must also disagree that FP is about some fixed order of operations; even in this small example you could choose to compute 12-45 first, and you could compute the subexpressions concurrently.

    Having cacheable results is a nice property; but it’s hardly a characterization. I can cache results in procedural and OO code as well. It depends on the meaning of a particular operation. If having cacheable results is all you care about, then you can do that easily with procedural C :-) I think that when you think of FP you are interested in more than just cacheable results. I think you’re more interested in writing components that can be combined with predictable results. I think you’re thinking of mathematical transformations.

    It’s not a single property of the code itself; the FP is mainly in the process that you use to arrive at the final code. You don’t see the process :-) See the similar discussion in the Italian DDD mailing list. The reason there is not much DDD code to look at is that even if you looked at it you would not see the DDD process, unless you know that process rather well to start with.

  5. Uberto Says:

    Ok Matteo, I agree on your main point “FP is what you write while thinking in an FP way” :)

    Still I believe the code itself, whatever the process used to write it, is important.

    It’s true you can write pure functions in C, but for me that would be Functional C, not Procedural C. :) You can also do OO in C (real OO I mean, not C++) if you write some code to exchange messages between instances.

    To conclude, I think there can be some metrics that can tell you: this piece of code is good FP, good OOP or crap.
    But I’m not sure if they can be automatically measured, for sure they will be much more complicated to measure than Demeter violations or LCOM4.

  6. dennis Says:

    It looks like we can not even agree on what functional and object-oriented programming is, so is there any point to being trying to be able determine the programming style by looking at the code?

    I think it is rare that you will find a (usefull) application that is pure OO or functional (especially if you ask if it has “procedural” aspects), so aren’t we better off looking for oportunities of use them at the appropriate time?

  7. matteo Says:

    Hi Dennis,

    I think there is value in analyzing and discussing code by itself. But the most interesting stuff often is (also) in the head of developers, or in the process they use to arrive at the code.

    I’m with you when it comes to using the style that betters suits your problem. But I think that often when we say “this problem is not a good match for paradigm X” we are really saying “I don’t know X well enough to be productive on this problem”. :-)

Leave a Reply