When coming from an object oriented background to functional programming you might be wondering if and/or how functional programming allows for modeling abstractions in our domain and how we go from an abstract model to working code.
Here is my attempt to provide a path so you can update your thought processes to aid in the transition from OO to FP.
We will start by revisiting what a domain is in the first place, which I will just define simply as the scope of the problem space we are interested in. For example, an online flight booking system might include the following considerations:
-
flight routes
-
number of seats available on aircraft used on each leg of the route
-
flight times/schedules
-
costs associated with each leg
-
frequent flyer qualification and redemption
It would probably not be concerned with:
-
passenger luggage policy
-
real-time gate information
-
flight crew schedules
-
flight crew legal work restrictions
When we are building an online flight booking service we would not need to model this last list of concerns as none of them inform how to effectively build such a service. An application that monitors real-time gate information such that it can provide more seamless connections for frequent flyers or passengers requiring additional assistance to make tight connections may need to query bookings from the ticketing system which our online flight reservation system will eventually feed into as well as real-time gate information but that is a separate application with a distinct domain and scope.
Now to define domain model. A definition I like used to like is from Fowler’s Patterns of Enterprise Application Architecture book for it’s simplicity:
An object model of the domain that incorporates both behavior and data.
The purpose of a domain model is to allow you to think through the problem space (or domain) and define semantics for a consistent view of the problem space. It allows you to communicate this shared understanding across the team and it can also help guide you toward better designs and find inconsistencies in your terminology usage or understanding on the team.
One component that seems missing from Fowler’s definition above is that in addition to behavior and data (structure) we should also be defining constraints (preconditions, postconditions, and/or invariants) on both behaviors and our data (structures). This gives us a richer understanding of what should and should not be possible in our domain which gives us a way to validate the values in our application more neatly.
In summary, a domain model let’s us define:
-
behavior
-
data structure (or types)
-
constraints or rules
Now we will see how we can map these ideas to the modeling environment and language functional programmers tend to use: mathematics.
Wait. Don’t run in fear, at least hear me out first.
We saw in the previous subsection that in richer OO domain models we end up with three basic kinds of definitions: behavior, data (structure), and constraints/rules.
In the FP world we translate these components as so:
-
beahvior ⇒ functions
-
data ⇒ types
-
constraints/rules ⇒ laws (or informally "properties")
In typed FP we typically approximate the notion of types to the concept of sets in the context of abstract algebra. For example, the set of natural numbers is the type and the elements of that set are the possible values of that type.
Algebra allows us to be more precise in our definitions and the act of abstraction means we focus on just the important parts to the problem space we are looking to solve directly.