December 2023
Thank you for this.
Once, I was alerted to the “perhaps your collected validation rules suggest a Policy class”, and extracted such a thing in RubyGems, to try it. (Oh, that was six years ago.)
By poking around the codebase for the longest class, I found it, and then recalled that microtechnique. Now, you’ve made me see guard clauses in that light.
January 2024
Inspiring post! The functional and value type stuff is new to me, but I think it’s pretty neat. What are your thoughts on switching over types like this?
Summary
(click for more details)
1 reply
January 2024
▶ Shed0582
Your Barcode
type effectively reimplements a small part of Maybe
using the “OO way” to design Sum/Union types. Your switch
statement reimplements Maybe.map()
(the Valid branch) and Maybe.withDefault()
(the Empty branch). I’m reminded of the joke that every program eventually contains a partial and buggy implementation of Lisp.
Your code contains a partial (but not buggy!) implementation of Maybe
.
I think some people intend that as an insult, but I don’t. Your code sample here seems clear to me, and already moving in the direction of Maybe
, so it wouldn’t be difficult at all to apply the refactoring of renaming Barcode
to Maybe
and then renaming ValidBarcode
to Barcode
. Then parse()
would return Maybe<Barcode>
and the switch
statement would be transformed into Barcode.parse(text).map(handleValidBarcode).orElse(() -> println("Barcode is empty"))
.
The only complication in Java (and specifically the Vavr library) is that map()
wants a function and not a consumer (void
function), but there are at least two ways to handle that problem.
Meantime, I really like the clarity of the pattern matching while we wait for a signal that we need heavier FP machinery.
Very nice!