A
A
Alexey Nikolaev2019-06-02 14:33:38
Programming
Alexey Nikolaev, 2019-06-02 14:33:38

Is it possible to throw an exception in predicates?

Good day.
The question concerns the cleanliness of the code and the harmony of the architecture. It's no secret that predicates are functions that must return a boolean value in response to some question (is directory exists?). Since I started to get into a lot of exceptions a year ago (because they rule), I now rarely return false or null in cases where false or null should cause the program to terminate. I keep returning them when the situation is valid, but when it's an error, I always throw an exception.
Actually, the essence of the question is that in some cases it is convenient to put the throw of an exception into a predicate. Thus, in some cases it will only return true or throw an exception. It's better not to do that, right? And how to do in such cases, if you want to encapsulate the code that throws the exception into a function? Make an additional wrapper function over the predicate?

I'll end the question with an example.
<?php

class CheckForNewPhoto
{
    public function handle(Repositories\MosaicRepository $MosaicRepository)
    {
        if($this->isDirectoryNameCorrect()) {
            // ранее исключение выбрасывалось тут, я считаю, это некрасиво
            // do stuff
        }

        throw new Exceptions\UnexpectedError(
            'Something wrong here'
        );
    }

    /**
     * Вот это - предикат. Я сделал так, чтобы избавить entry point,
     * функцию handle, от ада выбросов исключений, когда проверяется много
     * условий и выкидывается много исключений в одном методе.
     * Когда один метод > одна проверка > строго связанные с ней исключения,
     * это красиво.
     */
    private function isDirectoryNameCorrect()
    {
        if(!config('mosaic.directory', null)) {
            throw new Exceptions\InvalidSettingsException(
                'Directory for mosaic photos is not setup properly'
            );
        }

        return true;
    }
}

Thanks in advance.

Answer the question

In order to leave comments, you need to log in

6 answer(s)
I
Ivan Shumov, 2019-06-02
@Heian

He who holds a hammer in his hand sees only nails.

It's about you. The predicate must return true/false. Exceptions are needed in order to catch errors and pass them up the stack.
Real life example: when asked if there are pies, the seller either says yes or turns around and leaves

B
BorLaze, 2019-06-02
@BorLaze

The example just perfectly illustrates the fact that exceptions are not needed here for nothing.
For the isDirectoryNameCorrect question, we only want to get "yes" or "no".
At the same time, we are not at all worried about why "no" - either the character set in the name is invalid, or the disk has fallen, or there are not enough rights - we are not interested.

R
rPman, 2019-06-02
@rPman

The problem is no longer when to throw an exception, but when to catch it! In your particular example, you will need to catch the exception, complete the file operation, and continue execution.
Do you really want to drop the application if the user has selected the wrong directory in the settings? For example, a flash drive was selected and then it was removed, your program will try to open the directory and fall.

N
nrgian, 2019-06-02
@nrgian

Exceptions is a good name. Exact. Lucky.
They should be used in unforeseen situations.
The situation you describe is typical.
It is correct to return true or false here.

L
longclaps, 2019-06-02
@longclaps

Exceptions is a bad name. Confusing. Unsuccessful.
In fact, there is an alternative flow of control behind this: there is the usual flow of program execution, and there is a way to teleport from the point where the exception is raised to the point where it is handled. And this can be very convenient: for example, you are looking for something by recursive traversal of the graph, found it - threw an exception, and picked it up with a handler outside the traversal function. This is very convenient - you don't need to return true/false when exiting the function, but check it at the call point, it turns out simply and elegantly.

A
ApeCoder, 2019-06-02
@ApeCoder

To treat a situation as exceptional or not is a matter of design. You can either do a predicate, but then this thing should return true or false and throw exceptions in other situations - for example, when there is not enough memory.
Or make a check and throw an exception, but then there is no need to return true - it will no longer be a predicate.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question