Composition is a technique often used to build software by creating cohesive units that interact with each other to form the overall system. At the code level these units mainly consist of functions and objects. A system can be built by composing objects with abstractions that define the rules for communication with other objects. An alternative way of building the system is by composing functions and defining the rules of communication through functional contracts (i.e. passing functions into functions). Coming from an object oriented background I feel this second approach is worth exploring further.
Using the C# GildedRose kata as an example, an object oriented way of expressing the quality adjustment in a product looks like this
Now I have a couple of issues with the code above. First there is some repetition and unnecessary noise in the code that declares constructors for various IAdjustQuality implementations. Secondly IAdjustQuality and IProduct are single-method interfaces and I am suspicious of interfaces with single methods. Interfaces are generally created for a bunch of related methods.
An alternative way to express the quality adjustment in a Product in the GildedRose example would be to compose functions rather than objects. Although C# traditionally has been perceived to be an object oriented language but with lambda expressions it is very much possible to write functional code in C#. Single-method interfaces are easy to replace with the usage of closures and "function pointers" as long as the function has a compatible signature to the method declared in the single-method interface. Lets see how we can replace IAdjustQuality with its functional equivalent.
Creating the AdjustQuality and AdjustBackstageQuality functions results in the removal of 2 classes and the interface declaration itself. Notice AdjustQuality function uses partial application i.e. it is a function that returns another function. The first function is applied partially to return the actual function. This should be more clear after looking at the Product class now.
Applying the same technique of replacing an interface with its equivalent function pointer the IProduct interface can also be removed and the resulting code looks like this.
So why compose functions rather than objects. One of the benefits as you may have noticed straight away is that functional code is pretty succinct and has less lines of code (less than half of the original object oriented approach). The noise around declaring single-method interfaces and their implementations is no more present. However the functional approach might seem confusing and less readable especially the excessive use of lambda expressions and partial application. But I guess depending on whether you come from the object oriented background or the functional one you could sway either way. There is no right or wrong here. The basic idea is how objects and functions can be used to split your overall system into manageable chunks. The flexibility of achieving that in more than one way is a powerful tool to have.