PurelyFunctional.tv Newsletter 447: Domain model fit
Design Idea 💡
Domain model fit
This essay continues the series about Domain Modeling.
Have you ever felt you held an idea in your hand that somehow had escaped everyone's notice? That's how I thought about the concept of Actions, Calculations, and Data. Every functional programmer I talked to thought it was fundamental, but for whatever reason, they didn't include it in their functional programming tutorials. As I refined the idea over discussions, then a blog post, then a conference talk, then a podcast, it became increasingly clear I had something valuable that other people needed. And that value drove me to write Grokking Simplicity.
I feel like I'm on a similar journey with domain modeling. I don't have the core yet, but it's emerging as I organize my disparate notes. And when I look back, I've been working on this for years! I've lamented that "software design" has focused so much on the "cleanliness" of your code. Cleanliness is good. But something is missing.
That something is a reference back to reality. It seems weird to say it, but if you go systematically through the influential books in software design, there is minimal reference to the domain it models. Instead, the problems they solve are "too many classes," "long methods," or "hard to maintain code." These are problems worth solving. But the solutions solve just those things without checking if they make any sense in the domain. For instance, "too many classes" might be solved by using the Decorator Pattern, even if the new implementation can represent many more states than the domain contains. To be clear, I'm a fan of the decorator pattern when it models the problem well.
What does it mean to model a problem well? One measure of a good model is what I call fit, as in "How well does the model fit the domain?" One objective measure of fit is to count the number of states possible in the domain and compare it to the number of states possible in the model. Perfect fit means the numbers of states are equal, and there is a precise mapping from domain to model and vice-versa.
Of course, sometimes we cannot achieve perfect fit. We could start cataloging the ways our model doesn't fit. Just imagine the Venn diagram. Types of misfit:
- The model contains states that can't occur in the domain.
- The model excludes states from our domain.
- There is an imperfect mapping back and forth.
These are all very likely to occur, and we need ways to mitigate the downsides. The primary way we encounter the downsides is through corner cases and the explosion of code trying to handle them.
There's another measure of the quality of a model, which is the convenience. We'll address that next time.
Book update 📘
Grokking Simplicity has been selling well. I'm not doing much to promote it now, so that means word of mouth, which means people like it enough to recommend it! Thank you if you have bought it and/or recommended it. If you're a superfan, please leave a review on Amazon! It really helps people find the book.
Pandemic update 😷
I know a lot of people are going through tougher times than I am. If you, for any reason, can't afford my courses, and you think the courses will help you, please hit reply and I will set you up. It's a small gesture I can make, but it might help.
I don't want to shame you or anybody that we should be using this time to work on our skills. The number one priority is your health and safety. I know I haven't been able to work very much, let alone learn some new skill. But if learning Clojure is important to you, and you can't afford it, just hit reply and I'll set you up. Keeping busy can keep us sane.
Stay healthy. Wash your hands. Wear a mask. Get vaccinated if you can. Take care of loved ones.
Clojure Challenge 🤔
Last issue's challenge
- Longest Alternating Substring - Submissions
This week's challenge
Product of digits of sum
Write a function that takes one or more numbers as arguments. It should sum them, then multiply the digits. If the answer is one digit long, it's done. If it's more than one digit, repeat and multiply the digits again.
(sum-prod 4) ;=> 4 (sum-prod 10) ;=> 0 (since the sum is two digits, then 1 * 0) (sum-prod 11 12) ;=> 6 (sum-prod 12 16 223) ;=> 0 (work it out!)
Thanks to this site for the problem idea, where it is rated Very Hard in Java. The problem has been modified.
Please submit your solutions as comments on this gist.