ゲッター/セッターの必要性がなくなるので、これは私の設計プロセスの歓迎すべき変更ですが、これを行うことで他にどのようなハードル/利点が発生する可能性がありますか?
特定のプロパティに特別な get/set ロジックを実装できなくなります。スカラー (文字列、整数、ブール値) であるプロパティの場合、これはおそらく問題ありません。しかし、遅延ロードされたクラス インスタンスであるプロパティがある場合はどうなるでしょうか。
class Document
{
protected $_createdBy;
public function getCreatedBy()
{
if (is_integer($this->_createdBy)) {
$this->_createdBy = UserFactory::loadUserById($this->_createdBy);
}
return $this->_createdBy;
}
}
そのトリックはメソッドでのみ機能します。__get
このロジックに andを使用できます__set
が、プロパティを追加すると、大きな厄介なswitch()
ブロックになります。
public function __get($name)
{
switch ($name) {
case 'createdBy':
// blah blah blah
case 'createdDate':
// more stuff
// more case statements until you scream
}
}
getter と setter の記述を避けたい、または先延ばしにしたい場合は、マジック メソッドを使用して、命名規則__call
に従うメソッド呼び出しをトラップします。デフォルトの get/set ロジックをすべて入れて、二度と触れないようにすることができます。getProperty()
setProperty()
__call
abstract class Object
{
public function __call($method, $args)
{
$key = '_' . strtolower(substr($method, 3, 1)) . substr($method, 4);
$value = isset($args[0]) ? $args[0] : null;
switch (substr($method, 0, 3)) {
case 'get':
if (property_exists($this, $key)) {
return $this->$key;
}
break;
case 'set':
if (property_exists($this, $key)) {
$this->$key = $value;
return $this;
}
break;
case 'has':
return property_exists($this, $key);
break;
}
throw new Exception('Method "' . $method . '" does not exist and was not trapped in __call()');
}
}
Object クラスを拡張し、いくつかのプロパティを定義するだけでレースに参加できるため、このアプローチは開発の観点から非常に高速です。
class Foo extends Object
{
protected $_bar = 12345;
}
$foo = new Foo();
echo $foo->getBar(); // outputs '12345'
$foo->setBar(67890); // next call to getBar() returns 67890
$foo->getBaz(); // oops! 'baz' doesn't exist, exception for you
魔法のメソッドは非常に遅いため、実行の観点からは遅いですが、後で明示的なメソッドgetBar()
とsetBar()
メソッドを定義することで軽減できます (__call
定義されていないメソッドを呼び出したときにのみ呼び出されるため)。しかし、特定のプロパティがあまり頻繁にアクセスされない場合、それがどれほど遅いかは気にしないかもしれません。ポイントは、後で特別な get/set メソッドを追加するのは簡単で、コードの残りの部分はその違いを決して認識しないということです。
私はこのアプローチを Magento から引用しましたが、開発者にとって非常に使いやすいことがわかりました。存在しないプロパティの get/set を呼び出すときに例外をスローすると、タイプミスによる幻のバグを回避するのに役立ちます。プロパティ固有のロジックを独自の get/set メソッドに保持すると、コードの保守が容易になります。ただし、最初にすべてのアクセサー メソッドを記述する必要はありません。他のすべてのコードをリファクタリングすることなく、簡単に戻ってそれらを追加できます。
問題は、何を最適化しようとしているのかということです。開発時間またはコード速度? コード速度を最適化したい場合は、ボトルネックを回避するようにコードを作成する前に、ボトルネックがどこにあるかを確認してください。時期尚早の最適化は諸悪の根源です。