The terms “object-functional” and “object-functional programming” are heard time and again in the context of software development. But what does the object-functional approach look like and what advantages does it have? Isn’t object-orientation or the functional approach good enough all by itself? And what does Scala have to do with all of this?
Nontrivial software has to realize two types of behavior: It has to compute stuff and to effect stuff. For instance, a software system could compute what should be shown next on the display and then show it on the display. The latter can be called the production of an “effect”. Often, no distinction is made between different types of effects, calling all effects “side effects”. Yet, it is sensible to make a distinction between “essential effects” and “side effects”. Essential effects are part of the software’s requirements and can’t be eliminated: If something is to be displayed on screen, there’s no way around displaying it there. In contrast, side effects are effects that aren’t really needed, aren’t interesting or are even undesirable and only appear as an artifact of the behavior really wanted; for instance, imperative programming makes intensive use of such side effects as a means of computation.
Object-oriented programming is traditionally a rather imperative endeavor and the mutation of objects and object references, and thus side effects, are there with us all the time. Functional programming, though, emphasizes the transformation of values: Values are normally used to compute other values, but values and value references aren’t mutated in doing so.
What do we get, if the transformed values are objects? This brings us to one possible definition of object-functional programming:
Object-functional programming is a programming approach emphasizing the transformation of objects and using object-oriented as well as functional means and principles to this end. The production of effects in general as well the mutation of objects and object references in particular happen only sparingly, as transparent as possible to other parts of the code and separated as much as possible from transformational code.
With object-functional programming, object-oriented means are used to put software into a proper shape, fostering the code’s local changeability and understandability; data and behavior are brought together; access modifiers are used to allow sensible dependencies only, if at all possible. Functional features and many features traditionally provided more often by functional languages are used to forgo mutation of object and objects references as extensively as possible and for having an easy time staying modular even in the small, e. g. with functions as a lightweight alternative to the Strategy Pattern. As customary for functional programming, software is separated into code mostly free of effects and code mostly producing effects, with effects being as transparent to other parts of the code as possible; that way, large parts of the code aren’t affected at all by the disadvantages that effects involve, e. g. for local understandability and modular composability.
Unlike with object-orientation, objects are normally, at least looking from the outside, immutable; methods usually compute, but don’t produce observable effects. Unlike with functional programming, functions work less on passive data structures but often occur in the form of methods belonging to objects or object types and having access to their non-public data and behavior.
Appropriate mechanisms are used to realize essential effects, e. g. to display data on screen; these mechanisms can turn out very differently.
Software development isn’t about implementing wanted behavior in some “arbitrary” way. The software’s development and further enhancement should also be efficient and the results should be of high quality. Both object-oriented programming as well as functional programming support this goal to a certain degree, each in its own way.