Live data from Hacker News

Maybe Functions

blog.benwinding.com

61–70 of 103 posts

Re: Maybe Functions

#62
post #56
post #54

Earlier quoted context omitted.

Isn't parsing itself a maybe function?

The author has conflated two concepts into "maybe function". Parsing is "maybe" in the sense that the parser will either return your object or fail. But it doesn't have to do any hidden, surprising behaviour like the "if (!loggedIn) {" line in the article.

A better name might be “sometimes function”

Re: Maybe Functions

#63
This looks too easy, the first solution. If there is no logged on user, which User object is fetchUser going to return? Which friends? At the top level, if I were to forget to check if someone is logged in, who knows what would happen here.

I've worked on codebases where people were so allergic to the "billion dollar mistake" of nulls, that they created empty objects to return instead of returning null. This bit us in the ass a couple of times, e.g., when caller code was mistakenly passing the wrong ID variable into a fetch method, and just happily continued working and writing garbage into the DB, because it did not realize that its fetch had actually failed. It took data from the empty result object and happily continued its computation with it.

Re: Maybe Functions

#64

You do have another solution that can lower the amount of conditions: Null Objects. These don’t fit every use cases, but they can allow you to express what’s missing, or not defined, or empty, and avoid nil pointers dereference or conditions to check the state. As Sandy Metz is used to say « Nothing is Something »[0] 0: https://youtu.be/OMPfEXIlTVE?si=qmizH1OvqV7eLKNK

From the article:

> This is highly related to the "Null Object Pattern", but I thought I would explain it from the perspective of functions.

Re: Maybe Functions

#65
post #6

Another option is Exceptions. The function either does what it's supposed to, or freaks out. You can remove the null checks and the software will raise a null pointer exception. In the first example, could raise a NotLoggedInException. It's still a maybe function, but you have a mechanism for expressing the why-notness of the function run, as opposed to returning a generic null. As an aside, I prefer the "Unless" mod…

I like the philosophy that “exceptions are for exceptional circumstances.” Not being logged in is not exceptional.

What the exceptional case is depends on the what the pre- and post-conditions of the function are. If a function assumes that the user is logged in then the user not being logged in is indeed exception. Not to say that it is good design though. That function is quite fragile like this. If it must assume that a user is logged in, then it could easily require a user to be given as an argument which will remove the whole possibility.

Re: Maybe Functions

#66
I use maybe functions a lot for things like "maybeShowReminderDialog". The conditions for displaying the reminder are wrapped in this maybe function.

Surely that's simpler than specifying those conditions before every call to show this dialog, resulting in plenty of duplicated code. And if those conditions change, there is only one place I need to update it.

Of course I can make a single operation to check those conditions like "shouldShowReminder", but that too is doubling the surface area of this code.

I see the merit of the argument here but disagree with the absolutist stance against "maybe" functions.

Re: Maybe Functions

#67

I use maybe functions a lot for things like "maybeShowReminderDialog". The conditions for displaying the reminder are wrapped in this maybe function. Surely that's simpler than specifying those conditions before every call to show this dialog, resulting in plenty of duplicated code. And if those conditions change, there is only one place I need to update it. Of course I can make a single operation to check those cond…

There's that. And it also reduces the chance for race conditions:

    if ( shouldShow() ) /* state changes here where it should not show */ doShow();

Re: Maybe Functions

#68
post #48

Earlier quoted context omitted.

I like the philosophy that “exceptions are for exceptional circumstances.” Not being logged in is not exceptional.

for a function called "getUser" it is.

Not exactly. "getUser" not having a user to get is not exceptional unless you only have logged in users. If you have logged-out users, then "getUser" should gracefully handle the case of an unknown, logged-out user (either returning null or some other sentinel value).

Re: Maybe Functions

#69
You can also handle optionality when using the value.

  function maybeRenderBestFriends() {
    const user = maybeGetUser();
    if (!user) {
      return null
    }
    const friends = maybeGetFriends(user);
    const bestFriends = friends ? filterBestFriends(friends) : null;
    return bestFriends ? render(bestFriends) : null;
  }

Re: Maybe Functions

#70
post #58
post #33

Earlier quoted context omitted.

What constitues the "best" code depends on the incidental complexity of the problems you're trying to solve. Great code is when you have just enough of all those things, but have too much or too little and the code is worse.

You're right, of course — there are parts of my codebase that flagrantly disregard these rules, and did so for good reasons that I don't regret. But I've found that while "everything is relative and should be situated in the context of the problem you're trying to solve" is a useful truism, it makes for poor praxis. It's hard to improve existing code or develop newer engineers without _some_ set of compasses and heur…

I agree, I'd imagine as a senior you have a good sense of what counts as good enough. Unfortunately, there are too many would-be seniors justifying horrendous amounts of accidental complexity as "good practice".
Post reply on HN