Question

I have a method that returns the percentage change of a data in a certain period. After calling that method, i need to know if in the current period the data increased, decreased or is the same when comparing with the previous period.

The problem is that in some cases, the data of the previous period is equal to zero. In that cases there's no way to determine the percentage change, because i would have a division by zero. But I need to indicate it anyway because the data increased, even though it's not possible to calculate the percentage change.

One of my approaches was to return a Number when the previous data was different from zero, and return a String when the previous data was zero, indicating that the percentage change could not be calculated, but the data increased.

if ($gender[$last_period_key] == 0) {
    $perc_change = 'There were no records in the previous period';
} else {
    $perc_change = (($gender[$current_period_key] - $gender[$last_period_key])/$gender[$last_period_key]) * 100;
}

Another approach could be to retun a specific number indicating the error, like 999999999, but in my opinion it's not a good one.

There is a pattern or best practice for returning data that can assume different data types? Or how I would indicate the error using only numbers if the percentage change can be any of them?

I would like to apologise if here is the wrong place to ask this kind of question, and if it is, i would like indications of the appropriate place.

Thanks in advance.

Was it helpful?

Solution

In this specific case, the function could return INF, as you already noticed by yourself.

However, since you asked for a "pattern or best practice", a more general approach is to use a boolean function named "try..." which returns the success of the calculation, and the calculation result itself as an output parameter (by reference):

function tryGetPercentageChange(&$perc_change)
{
     if (/* calculation not possible */)
          return False;
     $perc_change = /* some calculation*/;
     return True;
}

This is often better than throwing an exception, in case failing calculations are no real "exceptional" situations.

OTHER TIPS

Exceptions are not only for Errors. When you have a division by zero, you can throw an exception. In your case, it should be some sort of domain exception, like NoRecordsForPreviousPeriodFound extends \RuntimeException

This is a Runtime type of exceptions, that you can catch and process the way you like.

On contrary, when you have a Logic type of exceptions, that usually means that you have to go back to the code and fix something there.

http://php.net/manual/en/spl.exceptions.php

An alternative approach would be to write a class that encapsulates this business logic. Just make sure you don't have any if-else calls involving this new class, as it's usually a sign of flawed OOP design.

Finally, if you don't like any of them, you can return null, but I recommend against that as it will cause more problems than it will fix. Same for using pointers for simulating multiple return types.

You could return null rather than mix strings and numbers.

This could also be a scenario where an exception could be used to convey the information.

Both of these push handling the problem to the code calling the method - and at some point in your view, you're going to have to either put logic into the view to handle the null/exception (which is not usual practice), or call a method that returns a string or percentage.

Another option is to realise that a change from 0 in the last period to any number in the current period (or vice versa) is a 100% change. And a change from 0 to 0 is a 0% change. This means you could always return a number.

Based on the comment of the user1118321, I searched about infinities in PHP, and it solved my problem once the type of infinity is double in php. This way I am returning the same data type in both cases, and it is in agreement with @HorusKol anwser when he says to not mix strings and numbers.

Thank you for your help.

Licensed under: CC-BY-SA with attribution
scroll top