0

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.

  • Does your language support infinities? If so, you could return that since that's the correct value. Calling code could watch for that and display an appropriate message to the user. – user1118321 Feb 17 at 17:36
  • 1
    I'm not familiar with PHP, but could you use NaN for this? – Bwmat Feb 17 at 18:50
  • Is there a possibility in PHP to return 2 values: one for your number result, and one - boolean - for whether this result is valid (or whether zero division occured)? – Olha Pavliuk Feb 17 at 19:16
  • If you can write a class/object then return one. It can have some fields/properties/methods that can be interacted with to determine if there was a previous period, and what the difference with the previous period was. This way the caller of the api must handle both happy paths. – Kain0_0 Feb 18 at 2:34
1

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.

1

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.

0

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.

  • 2
    '... realise that a change from 0 in the last period to any number in the current period (or vice versa) is a 100% change ...' Not really. a change from 0 in the last period to any number is equal to infinity. And it's not an exception once this scenario is really common in the application, I just wanna know what would be the best approach to return the data when that happen, but your answer about using null and the commet of the @user1118321, helped me to figure out a solution. Thanks. – Rafael Dias Feb 18 at 6:29
  • In a purely mathematical sense, yes, it's an infinity because of the division by zero. But sometimes it's just easier to treat it as a special case and return 100%. – HorusKol Feb 18 at 20:17
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.