Functional Programming makes Domain Driven Design Easy

May 9, 2014

Until recently, I tought I didn’t like Functional Programming (FP). I like OOP and DDD. During university I was in love with Java and I hated Haskel and Prolog. This changed last year at I T.A.K.E. Unconference when Cyrille Martraire showed us that using FP can be easy with DDD and its advantages are great for the design of our applications. He has explained each notion with code and he has made me change my mind about functional programming.

FP emerges from DDD

Most applications have three layers. One for loading the data, one for processing the data and one for displaying the data. The most interesting is the middle layer. It’s where we implement the business logic by playing with domain entities. There we enjoy producing clean code with TDD. How can we do that easily? We maximize the fact that the domain layer is side-effect free. We want to build it with services that are free of side-effects. Each service can be build with side-effect free domain functions.

In Functional Programming everything is a value. In Domain Driven Design we have Value Objects. Using Value Objects as much as possible leads to “Functional-First” coding style. This approach has multiple advantages.

Simplicity

Encapsulating all details in the value objects simplifies the code and makes it more scalable.

class Temperature {
    private final double value
    private final TemperatureUnit unit

    public Temperature(double value, TemperatureUnit unit)

    public Temperature toCelsius() {...}

    public Temperature toFarenheit() {...}

    public int hashCode() {...}

    public boolean equals(Object obj) {...}

    public String toString() {...}
}

Removing duplication with style

Duplication is usually removed by extracting methods. Cyril says that we can do better. Types can be created for for primitive values and duplication extracted in Value Objects. This leads to immutable code that reduces the risk of bugs.

Easy testing

Side effect free functions are very easy to test. So easy that mocking is not necessary. How is this possible? Easy testing comes with code isolation, with separating the “pure” from the impure / stateful code. Pure functions achieve this goal. A pure function is created by extracting one single operation on a type, making the code easy to test.

Closure of operations

This prevents us from violating the Law of Demeter. How? These functions always manipulate the same type and they don’t modify external state. In this way the domain layer handles only domain types and remains free of side-effects.

class Temperature {

    public Temperature toCelsius() {...}

    public Temperature toFarenheit() {...}

    public Temperature add(Temperature) {...}

}

Infinite composability

Infinite composability can be obtained by chaining functions. Composed functions lead to easily build new programs. This is similar to the way UNIX programs work: they do simple operations in isolation, but when combined together they become very useful tools.

Comfortable extensibility

When the client asks for new features, it is easy to add them to the code. Usually the only thing to do is to enrich the types. Another case of extensibility is when processing one unit turns into processing a collection. The change is straight forward: another value object is created along with corresponding closures.

class TimeSeries {

    private int points

    public TimeSeries add(TimeSeries timeSeries) {...}

    public TimeSeries substract(TimeSeries timeSeries) {...}

}

Crafted Objected-Oriented code

I have learned that “Functional Programming influence helps craft better Object-Oriented code” through Domain Driven Design concepts like value objects, no naked primitives, no naked collections. Cyril has proved it with the kata from his talk. Now I’m starting to use functional programming in my Java code. Try it and let me know how it works. One opportunity will be during Kata Lounge or Open Space this month, at I T.A.K.E. Unconference.

Categorised in: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *