In order to get a bit of "hard data" on what accessors will actually be used for once they are introduced I wrote a small script that scans through a codebase, finds all getter and setter methods and checks them for various characteristics. (The analyze.php file in this Gist.)
Here are the results of running it on a Symfony (Standard) skeleton.
absoluteTotal => 18516 (486.6%)
total => 3805 (100.0%)
skipped => 124 ( 3.3%)
get => 2767 ( 72.7%, 100.0% of get)
getInterface => 274 ( 7.2%, 9.9% of get)
trivialGet => 928 ( 24.4%, 33.5% of get)
simpleGet => 1172 ( 30.8%, 42.4% of get)
getWithCheck => 107 ( 2.8%, 3.9% of get)
set => 914 ( 24.0%, 100.0% of set)
setInterface => 92 ( 2.4%, 10.1% of set)
trivialSet => 354 ( 9.3%, 38.7% of set)
trivialSetChaining => 77 ( 2.0%, 8.4% of set)
simpleSet => 49 ( 1.3%, 5.4% of set)
simpleSetChaining => 16 ( 0.4%, 1.8% of set)
setWithTypeHint => 289 ( 7.6%, 31.6% of set)
unclassified => 612 ( 16.1%)
The same for Zend Framework:
absoluteTotal => 9876 (242.1%)
total => 4080 (100.0%)
skipped => 45 ( 1.1%)
get => 2480 ( 60.8%, 100.0% of get)
getInterface => 264 ( 6.5%, 10.6% of get)
trivialGet => 1070 ( 26.2%, 43.1% of get)
simpleGet => 465 ( 11.4%, 18.8% of get)
getWithCheck => 266 ( 6.5%, 10.7% of get)
set => 1555 ( 38.1%, 100.0% of set)
setInterface => 138 ( 3.4%, 8.9% of set)
trivialSet => 120 ( 2.9%, 7.7% of set)
trivialSetChaining => 397 ( 9.7%, 25.5% of set)
simpleSet => 14 ( 0.3%, 0.9% of set)
simpleSetChaining => 189 ( 4.6%, 12.2% of set)
setWithTypeHint => 342 ( 8.4%, 22.0% of set)
unclassified => 1112 ( 27.3%)
An overview on what these stats mean and how I interpret them:
absoluteTotal, total:
"absoluteTotal" is the total number of methods, "total" is the number of accessors,
i.e. no-param methods starting with "get" or single-param methods starting with "set".
As you can see getseter make up a large part of the methods. For Symfony 20% for
ZF even 40%.
=> Getter and setter are a *very* common pattern, so it makes sense to do work in
this direction.
get, set:
"get" is the number of getters, "set" the number of setters. You can see that people
use a good bit more getters than setters. For Symfony there are about 3x more getters,
for ZF it's 1.6x as many.
=> It is common to have read-only data. This may either mean that there will be many
accessors with asymmetric visibility or that many properties will only define a get
accessor.
getInterface, setInterface:
Number of getters/setters defined in interfaces or as abstract methods. This is about
10% for both projects.
=> Accessor and property support in interfaces is necessary.
trivialGet, trivialSet, trivialSetChaining:
"Trivial" means that the accessors act as a direct proxy to another property. The trivial
set chaining variant also proxies to another property and additionally returns $this.
For Symfony about 35% of all accessors are trivial. ZF also has 40% trivial getters, but
seems to be rather fond of chaining, so 25% of the setters are trivially chaining.
=> A good chunk of all getters/setters don't really do anything. Once we get accessors they
can be basically replaced by public properties. Accessors give the possibility to add more
behavior lateron.
simpleGet, simpleSet, simpleSetChaining:
A simple getter contains only a return statement, a simple setter only one assignment. For
Symfony 40% of the getters are simple (this is not counting the trivial ones), for ZF it's
20%.
=> Many getter are very simple and I think that especially the simple ones will be the ones
converted to property accessors.
This category is rather vague. Here are the three main types of simple getters I've found:
1. Getters returning a constant value. This is more common than I would have thought. Good
example of such a case are getName() methods that commonly return a constant string. Others
return arrays or constants.
=> There seems to be need for read-only, constant properties.
2. Proxies to other getters ($this->foo->getBar()).
3. Getters taking some property and doing some small postprocessing, like replacing a string
or similar.
getWithCheck:
Getters which contain an if condition (containing a single statement), followed by a return.
This is a common pattern for lazy loading. Amounts to 10% in ZF and 4% in Symfony.
setWithTypeHint:
Setters where the argument is type hinted. 30% of the Symfony setters have one and 20% of
the ZF ones.
=> There should be a simple way to typehint properties.
If I have followed the discussion on the internals list correctly, using the property access would mean that performance drops down to the
__get
equivalent which is about 2 times slower than directly calling a method. I find this very discouraging from using this in any kind of project.Additionally, the property access is not consistently possible due to the differences in method calls and property access in PHP:
Personally, this looks inconsistent to me. Sometimes you can use property access, other times you have to call a method explicitly. If you take a look at how this is implemented in Scala, it feels better:
As you can see, I never need to use a method call. Scala will automatically convert it to a method call in case a method is present. It would be nice if a similar thing would be possible in PHP, but I guess due to PHP's dynamic nature that will be difficult without falling back to using
__get
and living with the added performance degradation.