Monday, 7 May 2012

The OOP/FP argument, yet again.

I like OOP when I am the one writing the software, because I can think very naturally in terms of modelling the problem domain, but my opinion rapidly turns on it's head when I need to read/debug some OOP software that somebody else has written (When I need to think about control flow and behavior).

Writing good (readable) OOP problems is hard. Debugging them is even harder. Navigating then when armed with just the source code is harder still. (Diagrams please!)

Whilst most individual objects and methods in OOP systems are small and easy to understand in isolation (this is a good thing), I find that the flow of execution and the behavior of the system in the large becomes very difficult and time-consuming to understand. It is as if the fundamental complexity of the problem has been shoveled around from the small scale to the large scale.

To be fair, the same complaint probably applies to FP as much as to OOP; the tension driving this dialectic exists between the Functional Decomposition and the DRY principle on the one hand, and readability and narrative flow on the other. (Or the battle between reader and writer, to put it more colorfully)


  1. OOP and FP are for making abstract concepts like verbs and adjectives into concrete nouns that can be transformed and remembered as well as being run.

    FP uses the "apply" abstraction to do that, while OOP uses the ADT abstraction.

    You would only ever lift abstract concepts into nouns when you want to transform or remember them.

    Perhaps the problems you encounter are due to designers getting into the habit of thinking in "patterns" (in the sense of Gamma et al.). The result being that the program is described compositionally.

    If designers think in procedures and smartly generalise into patterns (and thus OOP and FP abstractions) whenever transformation and remembering of the abstract concepts in a procedure are required they'd get better results.

    Remember you can always think of an ADT as a collection of functions (possibly with memoisation of intermediates). And vice-versa of course.

  2. ... This seems to be a similar way of thinking to the way that the Go language approaches OOP - where the ADT comes about from an (almost) ad hoc collection of functions that (together) conform to some interface. (IIRC)