For a basic example, assume you have a class with a setter method:

class A
{
   private $var1 = 0; // must be non-negative integer

   public function setVar1($value)
   {
      if(cdata_digit($value))
      {
         $this->var1 = $value;
         return(TRUE);
      }
      else
      {
         // throw error or just return FALSE?
      }
   }
}

Would you recommend that the setVar1() method throw an exception if it receives an invalid argument, or just return FALSE? If you have a preference, can you also explain why? (Assume that you are only coding for PHP 5, so PHP 4 compatibility is not a valid reason for not using exceptions.)

    I would return false since the setter returns true if there are no problems. In my opinion, this makes for a more consistent interface. The caller is expected to test the return condition to see if the setter worked or failed. If the caller knows in advance that the setter will not fail, it can ignore the return value.

    On the other hand, if the setter does not return a value if there are no problems, I would throw an exception if there is a problem. Now, the caller is expected to catch the exception, unless it knows in advance that the setter will not fail.

      To play Devil's Advocate, what if the client program does not check the return value? By not throwing an exception at that point, I still might have to throw one later when the client calls a method which fails because that class variable now has an invalid value; so is it better to throw an exception as soon as something is noticeably wrong, or only when things are so wrong that it can't continue as is any more? (I'm not necessarily agreeing or disagreeing with you at this time, just trying to stimulate a discussion to help me decide how to approach this sort of thing.)

        I still might have to throw one later when the client calls a method which fails because that class variable now has an invalid value

        No, since the setter failed (i.e., the member variable still contains the "previous" value), the member variable would not have an invalid value. This is not what the client wants, but the member function's contract is that it was the client's responsibility to check the return value or otherwise guarantee that the setter succeeded.

          hi.
          Here is what I use in a class I work on.
          1. I set an Error number
          2. I return FALSE

          The output of script below will be:

          Okay!
          Error 1: Missing argument
          <?php
          
          class MyClass{
          
          public $err_no  = 0;
          public $err_msg = array(
              1=>'Error 1: Missing argument',
              2=>'Error 2: text ', 3=>'Error 3: text ', 4=>'Error 4: text ' );
          
          function MyClass(){
              return TRUE;    
          }
          
          function my_echo( $text=FALSE ){
              if( $text===FALSE ){
                  $this->err_no=1;
                  return FALSE;
              }
              echo $text . '<br>';
              return TRUE;
          }
          } // End MyClass
          ////////////
          
          $obj = new MyClass();
          $obj->my_echo('Okay!') OR exit($obj->err_msg[$obj->err_no]);
          $obj->my_echo()        OR exit($obj->err_msg[$obj->err_no]);
          exit();
          
          ?>
            laserlight wrote:

            No, since the setter failed (i.e., the member variable still contains the "previous" value), the member variable would not have an invalid value. This is not what the client wants, but the member function's contract is that it was the client's responsibility to check the return value or otherwise guarantee that the setter succeeded.

            Yes, I ignored my code logic. 🙂 In my example, if an invalid input is given then the current value will remain unchanged. At that point I can do as you suggest and return FALSE, and then say it's the client program's fault if it does not check the result and instead continues merrily along its way assuming that the change has been made. Or I can say that my end of the "contract" is to throw an exception, and it's the client's responsibility to catch any such exception. But, if it ignores the contract, then at least it will get an uncaught exception if an invalid value is given and it will be immediately obvious something is wrong. The counter-argument is that this might be overkill and could result in information being displayed in error messages that could be a security issue. But then, a production system should not be displaying errors, right?

            So I guess it sort of comes down to how much responsibility you want to delegate to the client program versus assuming it may be sloppy and taking the responsibility myself to ensure proper "contract compliance." Therefore I'm sort of leaning toward using exceptions for such things right now, but that might simply be because currently they are a new PHP "toy" for me that I've really just started "playing" with. 🙂

              It depends what level the code is operating on. PHP doesn't haves a throws argument and enforced catching on calling.

              Java's approach is to be over defensive which for some things is overkill. For example having a class that handles banners on the site. Would you want your whole site to potentially die if a bad parameter was passed to the object and not caught? Because there is no enforced catching in PHP ( no throws ) it's quite easy to imagine. Well it has bitten me anyway.

              The other extreme is when dealing with data manipulation ( financial information etc ) the die fast approach is preffered as trying to repair calculated information via data mining is a headache. Try/Catch/Finally is a thing that tries to enforce people who are using the code( high chance not written it ) to takes things into account more. An empty catch block is very obvious when doing a code review, even by someone who is not a coder.

              Unless PHP gets the throws argument I think PHP is a bit crippled with exceptions, in the visibility/usage stakes anyway.

                Write a Reply...