designates my notes. / designates important.
This is barely a book and more of a report, weighing in at only about 40 pages. Still, it manages to pack some thought provoking concepts into a small space.
There is no proselytizing of either object oriented or functional programing, but rather shows that there is quite a lot of overlap between the two, despite the animosity between the two camps.
The most interesting thing I took away, and it is obvious in hindsight, is that a some of the design patterns championed by object oriented designers are nothing more than clumsy implementations of functional programming. For example the command and strategy patterns can be greatly simplified by using lambda functions to replace the boilerplate classes needed for each ‘action’.
Treating functions as first class citizens allows you to pass them straight into the class when it is constructed instead of using an interface that takes another class to determine functionality.
The example was a compression class that would allow you to compress with zip or gzip. In a traditional strategy pattern you’d have the Compressor class, a CompressionStrategy interface, and two more classes for zip and gzip strategies. You’d instantiate the zip method class and pass it into the Compressor class.
Instead, using lambdas, you can drop the interface and simply pass in the zip or gzip method as a parameter during Compressor construction.
The same argument applies to the command class.
Further, some SOLID principles, such as Liskov substitution become a non-issue under functional programming. “No inheritance, no problem!” This is gaining popularity in the modern OO community as: “compose, don’t inherit.”
The take away is that more languages are moving toward a hybrid approach, allowing the programmer to select the right tool for the job.
Preconditions cannot be strengthened in a subtype. Where the parent worked, the child should.
Postconditions cannot be weakened in a subtype. Where the parent caused an effect, then the child should.
Invariants of the supertype must be preserved in a subtype. Where parent always stuck left or maintained something, then the child should as well.
Rule from history: don’t allow state changes that your parent didn’t. For example, a mutable point can’t subclass an immutable point.
Functional programming tends to take a different perspective to LSP. In functional programming inheritance of behavior isn’t a key trait. If you avoid inheritance hierachies then you avoid the prob‐ lems that are associated with them, which is the antipattern that the Liskov substitution principle is designed to solve. This is actually becoming increasing accepted within the object-oriented community as well through the composite reuse principle: compose, don’t inherit.
Take the command pattern. It’s called a pattern and has some different interacting components, but the essence of the pattern is the passing around and invoking of behavior. The command pattern is all about first-class functions.
The same thing with the Strategy pattern. Its really all about putting together some behavior and passing it around; again it’s a design pattern that’s mimicking first-class functions.