Writing Functions for Parts or Wholes?

I need to write some PHP Functions which calculate percentages and ratios.

For example…


			Total Liabilities
Debt/Equity Ratio = 	--------------------
			Shareholders Equity


Is it better to just write functions which calculate the “parts” (e.g. Total Liability) and then do something like this…


$totalLiabilities = getTotalLiabilities(parameters here);

$shareholderEquity = getShareholderEquity(parameters here);

$debtToEquity = $totalLiabilities/$shareholderEquity;

echo $debtToEquity;

Or would it be better to write a PHP Function which does all of the calculations and returns a finished result like this…


$debtToEquity = getDebtToEquity(parameters here);

echo $debtToEquity;

I can see advantages and disadvantages to each approach, but am curious what you guys think!

Sincerely,

Debbie

I’d just do



$liabilities = "blah";
$equity = "more blah";

function getDebtToEquity( $liabilities, $equity ){
    return $liabilities / $equity;
}

echo getDebtToEquity( $liabilities, $equity );


Wait…just reread the question…I assume that liabilities and equity are values retrieved from the DB?

If liabililities and equity have to also be calculated from other data, then I would create three functions – two functions that calculate liabilities and equities, than pass those two functions as parameters to a third function that does the division of those two.
That way you have all of that information organized, and can pass just pieces of it around if needed.

For example, you could then display a nice message saying:


[B]Your total liabilities:[/B] < liabilities function >
[B]Your total equity:[/B] < equities function >
_________________________________

[B]Total Debt to Equity: [/B] < the third function >

Functions should be small as possible, but larger steps are comprised of smaller steps like so.


function getDebtToEquity( $params ) {
  $equity = shareholderEquity( $params );
  return $equity === 0 ? 0 : totalLiabilities( $params )/$equity;
}

A more fleshed out example of the above would divide the params up to the child functions that need them, in addition to returning 0 rather than attempting a division by 0.

You lost me…

Why would you call one function from another?

I can see passing the results of a function to a more general one, but if you start sticking one function in another, then why not just have one huge function?

Debbie

It was implied that $liabilities and $shareholderEquity need to be calculated, but since this is a contrived example, it could be either.

After posting my OP, I started thinking the same thing too…


function getLiabilities(parameterList){


}


function getShareholderEquity(parameterList){


}


function getDebtToEquity(parameterList){


}

$liabilities = getLiabilities(parameterList);

$shareholderEquity = getShareholderEquity(parameterList);

$debtToEquity = getDebtToEquity($liabilities, $shareholderEquity);


Does that look better?

Sincerely,

Debbie

That looks like a winner to me. It’s a little more work than writing one large function, but I’m sure you will need to itemize this for visitors anyway, so my as well kill two birds with one stone

What seems to be the biggest benefit is that when I need to use Liabilities somewhere else, I already have a function for it.

That promotes code re-use and avoids conflicting functions where you make updates in one place but forget to do so in another.

Thanks,

Debbie

Efficiency.

Let’s go back to basic arithmetic and refactoring. Consider the polynomial

2x[sup]2[/sup] + 4x + 2

Before factoring out this expression we can divide all terms by 2 to arrive at

2 (x[sup]2[/sup] + 2x + 1)

From here it’s a bit simply to factor out the polynomial

2(x+1)[sup]2[/sup]

So what does this have to do with computer functions? Computers are math and work much the same way. Each expression can be thought of as a function. By keeping them discreet they can operate on each other, or even on themselves which is known as a recursive function.

It is no accident that tidying up code is often called “refactoring” it, and refactoring, strictly speaking, is done with polynomial expressions. They are done for the same reason - to keep each statement about the equation in one place. It takes less time to solve f(x) = 2(x+1)[sup]2[/sup] than work through the unrefined version of f(x) = 2x[sup]2[/sup] + 4x + 2. Let’s take a look at it when x = 5.

f(5) = 2(5+1)[sup]2[/sup]
f(5) = 2(6)[sup]2[/sup]
f(5) = 2(36)
f(5) = 72

4 steps. Now without refactoring

f(5) = 2(5)[sup]2[/sup] + 4(5) + 2
f(5) = 2(25) + 4(5) + 2
f(5) = 50 + 4(5) + 2
f(5) = 50 + 20 + 2
f(5) = 70 + 2
f(5) = 72

6 steps.

The two polynomial functions are equivalent, but the later is more efficient. This is why it is crucial in high performing code to define each step of the process once. Also, it’s easier to perform a transform on f(x) = 2(x+1)[sup]2[/sup], but that’s outside the scope of my math skills (conceptually I get it, but my practice is sadly lacking).

Aside from computational performance, it’s easier to maintain a program where everything is stated only once than a program where things are restated multiple times, and often in slightly different ways. Avoiding repetition is known as DRY (Don’t Repeat Yourself) coding.

I had a nerdgasm reading this post :smiley:

My theory is, is that people tend to overthink things, and ultimately make things more complicated than needed in the process. I am certainly not implying that your post is an example of such; merely making a general observation as it pertains to the thread, and our tendencies in general.

How this post does relate though is the part about adhering to DRY principles, and indirectly, structuring the application. I proposed simply making three seperate functions, because to me, it seems that we keep ourselves DRY by having two functions that perform two unrelated (but necessary) calculations, and a third function that provides the ultimate information being seeked. With all three functions being seperate entities, and very small and simple ones at that, it lends itself very kindly to future refactoring should it ever be required, but still gives us the flexibility to display these small nuggets of information by themselves when they are needed – which can’t be done if we had just stuffed this whole operation in one function (or at least not sanely, hehe…).

It is slightly more work doing it that way, but as far as I can see, I think the benefits are worth a few extra lines of code

Both in math and computer science functions are high level operations. They are also defineable. Multiplication after all is shorthand for repeated addition. Exponentiation is shorthand for repeated multiplication. A function is therefore a shorthand for a specific sequence of operations that, once defined, can be referred to by that shorthand rather than write the process out each time it is used. The shorthand can itself be taken as an operation.

Consider f[sup]1/sup = x+3 and f[sup]2/sup = x*3. What is f[sup]1/sup when x is 5. 18. Can we simplify the functions? Yes, and the rules for doing so are the entire area of mathematics called calculus.

It sounds like we are saying essentially the same thing, just not agreeing on the actual implementation…