Google published a set of tips on how to
increase the performance of
PHP a while
ago under the heading "Let's make the web faster". I recently came
across the article again, and it's been changed a lot since last summer
when it was published. At that time, a number of the tips were
massively
criticized
- a lot of
blog
posts
were written, comments made, etc. Seemingly, this has led to the article
being changed, which is good, as some of the info on it previously was
rather misleading. Most of what is left is alright, although one or two
of those that have been allowed to stay are still dubious:
Don't copy variables for no reason
Sometimes PHP novices attempt to make their code "cleaner" by copying
predefined variables to variables with shorter names before working
with them. What this actually results in is doubled memory consumption
(when the variable is altered), and therefore, slow scripts. In the
following example, if a user had inserted 512KB worth of characters
into a textarea field. This implementation would result in nearly 1MB
of memory being used.
Although the above statement is correct (due to the 'when the variable
is altered' which I'm presuming has been added later) the example that
succeeds it does not in any way double the memory used. The example
copies a variable and then echoes the copy - which doesn't amount to a
change and hence won't actually create a copy of the variable. It would
be nice to see the whole text revised instead of a bit of extra info
inserted in a parenthesis ... oh well.
However, that's not the main point that struck me as odd. No, what got
me paying attention is this bit:
Avoid writing naive setters and getters
When writing classes in PHP, you can save time and speed up your
scripts by working with object properties directly, rather than
writing naive setters and getters. In the following example, thedog
class uses the setName()
and getName()
methods for accessing
the name
property.
Then follows an example with a class with public(!) properties and
get/set methods. And of course the tip of not using getters and setters
like that. However, is that really the tip that one should give
programmers? What happened to encapsulation? Not to mention: who would
ever write getter and setter functions for public properties?
In the theoretical world that people are being taught, you're told that
keeping properties offlimits to the outside world is a good thing: it
limits the knowledge the world can possibly have of your object and
hence minimizes the chance for tight coupling due to someone figuring
out that \$obj->property is possible and easier than
\$obj->getProperty(). Why are people being told this? Because when
later down the line you realise that you have to change obj::\$property
to obj::\$some_other_property, you'll wish you never had the bright
idea of making use of public properties. Specifically, going through
code in many different places changing \$obj->property to
\$obj->some_other_property really makes you annoyed ... there are
much better ways to spend your time.
Of course, there's an alternative to fixing references to
obj::\$property. It's called __get(), it's a magic method, and it's
muchslower than setter/getter functions. In other words, using the
hint from Google - which is supposed to speed up your apps - you're
implicitly going down the road of tight coupling. Which means that:
Setting and calling the name
property directly can run up to 100%
faster, as well as cutting down on
development time.
is a typical short-term view of things. Sure, development time is
shorter if you don't have to write the ten extra lines of code for
getters and setters, but development time is massively extended when you
have to refactor your code to not use public properties any more. Not to
mention that if you the mitigate that with __get() your code suddenly
won't run up to 100% faster but more likely 100% slower (the code
dealing with these properties, that is).
What should you do? You should design your objects properly, is what you
should do. If some properties are core to the object and don't need a
check when being set, then obviously you can go without getters and
setters. However, if you're looking at an object that might change in
the future or if you're dealing with properties that should be validated
before being set (failing
early
is often better than failing late) or if you just want to minimize the
signature of the object, then use setters and getters.