DEV Community

Jesse Warden
Jesse Warden

Posted on • Originally published at jessewarden.com

Domain Driven Design Translated to Functional Programming

Attempting again to learn Domain Driven Design, and it’s clear if you’re an Object Oriented Programmer trying to learn Functional Programming, no wonder you’re confused. Here’s a paragraph summary of the 500 page book I’ve translated each sentence into typed FP.

OOP: You model your business using Entities (the ID matters) and Value Objects (the values matter).

FP: You model your business using Types, Aliases, and Unions. Everything is immutable so has an implied ID, but you can add if you wish.

OOP: You use Repositories to retrieve and store them.

FP: You use functions to retrieve them. You can’t store them as there is no state.

OOP: You create them with the help of Factories.

FP: You create them with with functions.

OOP: If an object is too complex for a single class, you’ll create Aggregates that will bind Entities & Value Objects under the same root.

FP: There are no classes, only functions that return immutable Types and Unions. Complexity just grows into more functions.

OOP: If a business logic doesn’t belong to a given object, you’ll define Services that will manipulate the involved elements.

FP: Objects don’t have state or methods; you just create new functions return that return new values.

OOP: Eventually, when the state of the business changes (a change that matters to business experts), you’ll publish Domain Events to communicate the change.

FP: A function will get an input and return a value.

Caveat with the above is F# and Scala do have classes and you can map your mental model of DDD around the boundaries. However, if you’re doing Event Sourcing or CQRS, hopefully you can see how your life just got a lot simpler. (OOP people are thinking “dangerous”)

Also, while “there is no state” in FP, there is always someone who stores your state. The Database on the back-end, the Step Function in your infrastructure, the “Model” in Elm front-ends.

A lot of what I’m learning from researching DDD is the same thing the Agile crew uses Behavior Driven Design: learning the Business language, and modeling it into your code. Understanding the different types of users, the words they use, and making that strong types.

Learning business language is good. But if you remove stateful objects, then you’re just left with functions. That means Aggregate, Service, Repository, and Factory are now just functions you compose together in a bigger function (that’s a good thing, it’s called railway or pipeline programming).

Bounded context isn’t an OOP/FP thing, that’s a monolith vs. microservice problem. If you’re in an Elm front-end monolith, put in separate files. Back-end? Put in different Lambdas. Need to communicate? Use JSON schema/protobuff.

I’m glad my career with OOP ended before DDD became a thing. Yet here I am diving head first into learning this because 90% of what I read around Event Sourcing & CQRS assumes OOP, which isn’t what I’m finding out in practice. The Akka Scala examples are these weird hybrids.

@jdegoes has a more hands on example here for how you’d design in Functional coding, where 90% of it is what you’d expect in typed FP and “class” is just because Scala is based on Java which has that as the core type despite being heavily typed FP.

https://degoes.net/articles/functional-design

Caveat around dynamic languages like Python & JavaScript that support both OOP and FP styles; you can do the above, you just have less guarantee’s at runtime, and the problems of bounded contexts bleeding into each other is the same as all monoliths: becoming a ball of mud. … but man, it’s so fast to learn your domain in the beginning…

It is extremely difficult reading these articles with my FP bias coming from OOP. Powering through anyway.

Top comments (0)