How about using PHP Enums for Results?

How about using PHP Enums for Results?

ยท

3 min read

Hey guys,

Weekend post again hehe ๐Ÿ˜Ž. I'd like to share my latest approach and I actually find it really cool ๐Ÿฅน.

I've been using PHP Enums not only for options, types, etc but also for Result responses now โญ๏ธ

Lemme show you how it works and how awesome is that ๐Ÿš€.

Results over Exceptions

This is one of the practices I've been using and I love it, I also have a post for that: No throws and happier life

TL;DR:

  • Throw is slow

  • Untyped

    • E.g. if your function throws 4 exceptions => 4 untyped paths.
  • Increase production errors

    • Callers won't usually wrap the try/catch
  • It reduces the reusable purpose of your function

I really like how this package neverthrow add their reasons as well:

Throwing and catching is very similar to using goto statements - in other words; it makes reasoning about your programs harder. Secondly, by using throw you make the assumption that the caller of your function is implementing catch. This is a known source of errors. Example: One dev throws and another dev uses the function without prior knowledge that the function will throw. Thus, and edge case has been left unhandled and now you have unhappy users, bosses, cats, etc.

With all that said, there are definitely good use cases for throwing in your program. But much less than you might think.

Use PHP Enum as the Result

Yeah, here come the main dishes ๐Ÿ˜Ž

Everything looks easier with a real-life example, so let's create a Result class for creating a Vacation Leave Request.

The Result class

I will create a CreateLeaveRequestResult

enum CreateLeaveRequestResult
{
    /**
     * When the creating leave request is overlap with 
     * another leave requests
     */
    case HAS_CONFLICTED_DATES;

    /**
     * When the user doesn't have enough leave balance
     */
    case INSUFFICIENT_BALANCE;

    /**
     * All good and can create a new leave request
     */
    case SUCCESS;
}

As we can see, with some simple notes & cases, we all know the outcome of the function that we are going to trigger. It makes our life easier โœ….

Handle logic and return the Result

I have a LeaveRequestService@create method like this:

class LeaveRequestService
{
    public function create(LeaveRequestData $leave): CreateLeaveRequestResult
    {
        if ($this->hasConflictedDates($leave)) {
            return CreateLeaveRequestResult::HAS_CONFLICTED_DATES;
        }

        if (!$this->hasEnoughBalance($leave)) {
            return CreateLeaveRequestResult::INSUFFICIENT_BALANCE;
        }

        // all good
        $leaveRequest = $this->createNewLeaveRequest($leave);

        // send notifcations or do anything
        // ...

        return CreateLeaveRequestResult::SUCCESS;
    }
}

Response in Controller

public function create(
    LeaveRequestService $service
    SubmitLeaveRequestRequest $request
): JsonResponse {
    $leave = $request->getLeaveRequestData();

    $result = $service->create($leave);
    if ($result !== CreateLeaveRequestResult::SUCCESS) {
        return new JsonResponse([
            'outcome' => $result->name,
        ], 400);
    }

    return new JsonResponse([
        'outcome' => 'SUCCESS',
    ]);
}

Awesome right? ๐Ÿ˜Ž

PROs

  • Fully typed in your functions.

  • Better than string/boolean response, especially for complex business logic/flows.

  • Happier callers, we always know what we'll receive after triggering the functions.

Considerations

Include additional data when returning the result

Yes, we can, can do either:

  • Create a new class which have the Enum result & your additional data

  • Use my never-throw package (written in PHP)

    • Really want to make it as much as same as the TS's neverthrow but still haven't gotten there ๐Ÿฅน.

A bit of marketing

As you see in the above example. It relates to the PTO (personal time off) & Vacation tracker.

If your teams want a simple & awesome solution for that, try out Flamingo App ๐Ÿฆฉ.

It's lovely, gorgeous, super easy to use, and has an awesome notification system that ensures everybody is in the loop ๐Ÿ“ฃ.

Conclusions

Well, that's it guys. I really like this way - making my functions/methods become fully typed.

Happy weekend!

ย