As it is written, calling factorial( -1 )
would grow the activation chain without limit.
public int factorial( int N ) { if ( N == 0 ) return 1; else return N * factorial( N-1 ) ; }
The first activation factorial( -1 )
would activate factorial( -2 )
,
which would activate factorial( -3 )
, which would activate factorial( -4 )
, and so on.
The base case (of N == 0
) would never be reached.
Eventually the computer system would run out of resources,
and the program would stop running.
Defensive programming is when a programmer anticipates
problems and writes code to deal with them.
To avoid the disaster a negative parameter would cause,
sometimes factorial()
is written like this:
public int factorial( int N ) { if ( N <= 0 ) return 1; else return N * factorial( N-1 ) ; }
But, according to the math-like definition, this is not correct.
The value of factorial( -1 )
is undefined,
not equal to one.
Potentially, returning an incorrect value and continuing on as if nothing is
wrong might cause a greater disaster than stopping the computer system.
Sometimes the method is written to throw an exception when an illegal argument is detected. (Exceptions are discussed in a future chapter.) But this adds complication since now the caller must deal with a possible exception.
Perhaps the best idea is to write factorial()
so that it follows the math-like definition exactly.
Make it the responsibility of the caller to
make sure that the argument is within range.
Here is another idea: why not have factorial()
use
the absolute value of its argument to be sure that it is positive?