4

PHP variables are dynamic in type so I can do:

$x = 'hello world!';  
$x = strlen($x);  

Sometimes this is trivial and I could save many lines of code, but it reduces clarity. I'm using a text editor, but I guess IDEs (and programmers) could be confused if a variable change type.

Less trivial case:

if (is_string($data))  
    $lines = explode(PHP_EOL,$data);  
else  
    $lines = $data;  

versus:

if (is_string($data))  
    $data = explode(PHP_EOL,$data);  

Of course I could do something like:

$lines = is_string($data) ? explode(PHP_EOL,$data) : $data;  

But that's not the point.

BTW: I'm assuming $data is string or array and this should be documented as such.

1 Answer 1

9

It is best to keep code as simple as possible. This means different things for different people, but in my experience I have found that:

  • Variables should always keep the same type. Changing something that conceptually holds a string to an array is highly confusing, especially if the type is only converted in one code path.

  • Variables should only be assigned once. Now, variables always refer to one object which makes the rest of the code simpler to understand.

  • Variables should not be shadowed. This doesn't really apply to PHP, but in languages where variables have to be declared, we shouldn't re-declare a variable when a var with the same name is already in scope.

  • Values should not be changed. Instead, we can generate a new value and store it in a new variable. Now, each variable always points to the same data. Whenever I do something with a variable, I'll get the same value. This makes debugging much easier, but has less to do with variables than with designing suitable objects.

The consequence of these points is that I'll end up with single-assignment form, which makes code fairly “reasonable” (as in, can be reasoned about). Some (functional) languages enforce this, but good code may use this concept even when it's not enforced by a language.

There are of course many counter-examples where this is not a good idea. I frequently don't cling to immutability when…

  • … I'm coercing arguments to some type. Often, I'll have a function that is fairly lax with the input. I then write the (pseudo-code)

    if (!has_expected_type($var)) {
      $var = coerce($var);
    }
    

    This violates the point about never changing the type of a variable. But since validation is done at the top of the function, before any main logic, this seems to be a reasonable tradeoff. On the other hand, explicitly named variables wouldn't be difficult either:

    $var = has_expected_type($coercible_var) ? $coercible_var : coerce($coercible_var);
    
  • … I'm appending to a data structure, e.g. building a string or an array. A bit of mutability is OK. I usually name these variables $out or $buf. I see nothing wrong with code like

    $buf = "Hello, $name\n\n";
    if ($idiot) {
       $buf .= "Use this one weird trick to lose 10lbs, doctors hate it!\n";
    } else {
       $buf .= "10/10 studies show: our snake oil is the best snake oil!\n";
    }
    $buf .= "Buy now!";
    return $buf;
    

    Any other approaches to building this string would be even more painful (aside from using a proper template system, of course).

1
  • 2
    I agree with all of this. Re: the paragraph on coercion: in many languages, the names of formal parameters become part of the public API, e.g. via an automatic documentation extraction tool, or even, like in Scala or C♯, via language-integrated support for keyword arguments. Because of this, the "best" name is often already taken, and instead of settling for the "second-best" name, re-assigning the name is sometimes the better trade-off. Mar 29, 2016 at 22:09

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.