Tell Don't Ask
Published on

Avoid type juggling

Authors

Arrange

src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php

  /**
   * The attributes that aren't mass assignable.
   *
-  * @var array
+  * @var array|bool
   */
- protected $guarded = ['*'];
+ protected $guarded = false;

This pull request got me thinking about type juggling. Let's see what is the definition.

In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another. An example would be the conversion of an integer value into a floating-point value or its textual representation as a string, and vice versa.

Here is how it looks like.

$var = 'example';
// later somewhere in the code
$var = 123;

Or in OOP world using something like the example from the pull request.

class Model
{
  protected $guarded = false;

  public function guard()
  {
    $this->guarded = ['*'];
  }
}

I see this frequently happening in JavaScript world, especially in VueJS. Common pattern people use is:

export default {
  data() {
    posts: null,
  },
  mounted() {
    axios.get('/api/posts')
      .then(response => {
        // response.data is an array of posts
        this.posts = response.data;
      });
  },
}

Act

How can this be problematic, one might ask. Well if we have somewhere on the page the number of posts shown, the easiest way to show it would be something like following:

<p>{{ posts.length }} posts</p>

In this example we cannot do that cause until we fetch the data from the API, posts property is null and calling length on null will cause an error. So to remedy that we would have to do the following:

<p v-if="posts">{{ posts.length }} posts</p>

This way we are introducing unnecessary complexity which can be easily avoided if we stick to one type.

Assert

So better pattern would be:

export default {
  data() {
    posts: [],
  },
  mounted() {
    axios.get('/api/posts')
      .then(response => this.posts = response.data);
  },
}

Then we would not have to worry about it in our HTML. It is totally acceptable to show 0 posts until they are loaded.

Same applies to the PHP example. If we would want to loop over values of an array, we would first have to check if the property is an array. Imagine if we were using that property in multiple places, then our code would be polluted with repeating checks for that property. Now imagine if we had a bunch of properties that change type.

The best part is that PHP will evaluate an empty array to false, or if we are looping over it, it will not execute anything from the loop block.