I have a set of domain objects which try to find a solution to a problem.The top level object has an algorithm which splits up the problem and delegates it to lower level objects, which in turn do the same. I want the top level algorithm to throw an exception if it did not find any solutions, giving a breakdown of possible causes.My question is, how should(n't) this be implemented?The way I was thinking of doing this:The algorithms at all levels throw an exception if it fails to find a solution. For a given level, call it the parent algorithm, it would accumulate exceptions thrown by its children, and if all attempts by its children throw an exception, the parent will itself throw an exception which contains its childrens' exceptions.My implementation is as follows:class ExceptionWithCauses extends \Exception {    private $causes = array();    public function addCause(\Exception $ex){        $this->causes[] = $ex;        $this->message .= \n.$ex->getMessage();    }}I'm using it like this:function findAnOption(){    $noOptionsException = new ExceptionWithCauses(findAnOption(): No options found);    $possibilities = array(1, 2, 3, 4);    foreach ($possibilities as $possibility)    {        try {            useOption($possibility);            return $possibility;        } catch (Exception $e) {            $noOptionsException->addCause($e);        }    }    throw $noOptionsException;}function useOption($x){    if ($x < 5){        throw new ExceptionWithCauses(useOption(): $x is too small);    }    return $x;}And when findAnOption() is called, a exception is thrown with the following message:findAnOption(): No options founduseOption(): 1 is too smalluseOption(): 2 is too smalluseOption(): 3 is too smalluseOption(): 4 is too smallI'm worried that this is bad practice. I've read that exceptions should only be used in exceptional circumstances. So with that in mind, perhaps I should only be throwing an exception at the top level. But then at that top level, how should the exception accumulate details on what was tried by lower levels? The only time that information will be needed is when the top level throws that exception, so in a way it makes sense that it's all handled by exceptions, and that I have exceptions at every level?On the one hand, this question on Programmers SE explains why using exceptions in control-flow is an anti-pattern, but at the same time, it seems like the tidiest way of accumulating a log for why a top level exception occurred?
Throw an exception which contains a nested set of previous exceptions
php;error handling;exception
I'm agreeing that it is bad practice, and that you should use exceptions to indicate error situations. Letting exceptions propagate including other levels of detailing sub exceptions, seems like something you'll loose control over quite soon.I would rather extend the different functions to return the needed information either directly through function returning result objects which could hold the detailed information needed at the top level to determine the causes. You would then collate, and keep on returning more information up the chain.Or you could implement a message queue where the delegates publishes messages regarding discrepancies onto the queue, and you have a central subscriber collating all those into some sensible report to present at the end. This would be especially useful if you are talking about higher level parallell algorithms, but might be overkill for a simpler system. It does however have the advantage that code at any level, could post a message and it's kind of separate from the code logic elsewise.