言うまでもなく、ベストプラクティスというよりもセマンティクスの問題です。
あなたの例では、ビジネス ロジックによって、動物には常に名前が必要であると判断される場合があります。したがって、名前を付けてオブジェクトを構築することは理にかなっています。動物の名前の変更を許可したくない場合は、setter を作成しません。
すなわち
class Animal
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
動物が持っている必要のない他のプロパティを持っているかもしれません.
class Animal
{
private $name;
private $owner;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setOwner($owner)
{
$this->owner = $owner
}
}
しかし、常に所有者と一緒に動物を作成していることがわかった場合は、便宜上、それをコンストラクターの署名に入れたいと思うかもしれません。
class Animal
{
private $name;
private $owner;
public function __construct($name, $owner = null)
{
$this->name = $name;
$this->owner = $owner;
}
public function getName()
{
return $this->name;
}
public function setOwner(Owner $owner)
{
$this->owner = $owner
}
public function getOwner()
{
return $this->owner;
}
}
所有者がアプリケーション内の別のクラスである場合は、コンストラクターが特定の型 (クラス) の所有者を必要とするヒントを入力できます。これらはすべて、あなたや別の開発者がコードの背後にある要件/ロジックの一部を理解しやすくするために使用されます。また、あちこちでバグをキャッチする可能性もあります。
class Owner
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
}
class Animal
{
private $name;
private $owner;
public function __construct($name, Owner $owner = null)
{
$this->name = $name;
$this->owner = $owner;
}
public function getName()
{
return $this->name;
}
public function setOwner(Owner $owner)
{
$this->owner = $owner
}
public function getOwner()
{
return $this->owner;
}
}
// Create a new owner!
$dave = new Owner('Farmer Dave');
// a standard php empty object
$otherObj = new \stdClass();
// Create a new animal
$daisy = new Animal('Daisy');
// Farmer dave owns Daisy
$daisy->setOwner($dave);
// Throws an error, because this isn't an instance of Owner
$daisy->setOwner($otherObj);
// Set up Maude, with Dave as the owner, a bit less code than before!
$maude = new Animal('Maude', $dave);