Return Null? Think Twice!
What does everyone’s code uglier? Actually, the only thing is code itself. Unnecessary code. The code that would not be written if the author of library I use thought about me, but not about his awesomeness.
Checks before foreach
What do I mean? I used to spend lots of time for writing code like this:
<?php
if ($news->hasCategories()) {
foreach ($news->getCategories() as $category) {
// Do some stuff
}
}
Okay, at least there is hasCategories
function. But wait… Why do I need this if
wrapper? Why library author does not just return empty array instead of null
if there is no category? Do not be that guy :)
Default values
Another way to uglify your code is:
{% if project.logo %}
<img src="{{ project.logo.path }}" />
{% else %}
<img src="/path/to/default.png" />
{% endif %}
Looks pretty familiar, isn’t it? What’s wrong with this piece of code? How can I make it better?
First of all, define __toString()
function for Logo
to return path and shorten this piece: {{ project.logo }}
.
The second thing will allow us to get rid of the whole construction. Martin Fowler calls this refactoring “Introduce null object”. Project::getLogo()
should return an instance of tiny class that represents default value. And this object will return /path/to/default.png
. This instance can be anonymous if it is possible in language you use (no way in PHP).
<?php // Project.php
class Project
{
/** @return LogoInterface */
public function getLogo() {
return $this->logo ?: new DefaultLogo();
}
}
<?php // DefaultLogo.php
class DefaultLogo implements LogoInterface
{
public function path() {
return '/path/to/default.png';
}
public function __toString {
return $this->path();
}
}
And now our glue code is that simple:
<img src="{{ project.logo }}" />
Yes, this refactoring creates more complex library code, but significantly reduces amount of high-level glue code. That is awesome for me, I hate glue code :)
Conclusion
When you write some code, think of a guy who will use your code in his work. Probably, this guy is you.