Valueオブジェクトvs連想配列PHP
-
20-09-2019 - |
質問
(この質問PHPを使として文脈がなに限定されPHPのみです。例えば言語と内蔵のハッシュするにも関連する)
見てみましょうこの例では、サポートに対するコミットメント:
function makeAFredUsingAssoc()
{
return array(
'id'=>1337,
'height'=>137,
'name'=>"Green Fred");
}
に対す:
class Fred
{
public $id;
public $height;
public $name;
public function __construct($id, $height, $name)
{
$this->id = $id;
$this->height = $height;
$this->name = $name;
}
}
function makeAFredUsingValueObject()
{
return new Fred(1337, 137, "Green Fred");
}
法#1はもちろんterserしで簡単につながるエラーなど
$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here
もちろん、という意見もあ $myFred->naem
平等につ誤りである。しかしこの公式のクラスで感じり剛性ができませんの正当化します。
池尾:そういうふうに考えていプ/連結に使用されるアプローチの場合は利用するアプローチを考えていますか。
解決
表面の下では、2つのアプローチが同等です。クラスを使用する場合ただし、標準のオブジェクト指向の利点のほとんどを得る:などのカプセル化、継承を、
。また、次の例を見てみます:
$arr['naem'] = 'John';
は完全に有効であり、困難なバグが発見することができます。
一方、
$class->setNaem('John');
働くことは決してありません。
他のヒント
単純なクラスのこのような:
class PersonalData {
protected $firstname;
protected $lastname;
// Getters/setters here
}
少ないメントでは、配列になります。
- る可能性はありませんが間違えやすい。
$data['firtsname'] = 'Chris';
作中$data->setFirtsname('Chris');
うjaエラーになります。 タイプを窺わせ:PHP配列を含むことができものを含むものが特定のクラスのみを含む指定したデータです。
public function doSth(array $personalData) { $this->doSthElse($personalData['firstname']); // What if "firstname" index doesn't exist? } public function doSth(PersonalData $personalData) { // I am guaranteed that following method exists. // In worst case it will return NULL or some default value $this->doSthElse($personalData->getFirstname()); }
当社ブログにアクセスいただきつかの余分なコードを設定または取得の操業、検証またはログイン:
public function setFirstname($firstname) { if (/* doesn't match "firstname" regular expression */) { throw new InvalidArgumentException('blah blah blah'); }
}if (/* in debbug mode */) { log('Firstname set to: ' . $firstname); } $this->firstname = $firstname;
- 使用できるすべてのOOPのように遺産を多型タイプ統一化など...。
- 前述のように、すべての当社の"構造体"に引き継ぐかの基盤を提供するクラスの実装
Countable
,Serializable
またはIterator
界面で構造体が利用可能foreach
ループなど。 - IDEです。
唯一の欠点が高速になります。創造の配列および営業しが高速化されました。しかし多くの場合のCPU時間はとてもいいのですがプログラマー。;)
は、いくつかの時間のためにそれについて考えた後、ここに私自身の答えです。
は配列の上にの値オブジェクトを好むについての主なものはあるの明快の。
この機能を考えてみます:
// Yes, you can specify parameter types in PHP
function MagicFunction(Fred $fred)
{
// ...
}
対
function MagicFunction(array $fred)
{
}
の意図は明確です。機能の作者は、彼の要件を適用することができます。
さらに重要なのは、ユーザーとして、私は簡単に有効なフレッドのを構成するもののルックアップすることができます。私はちょうどFred.php
を開き、その内部を発見する必要があります。
呼び出し元と呼び出し先の間の契約があります。値オブジェクトを使用して、この契約は、構文チェックをコードのように書くことができます:
class Fred
{
public $name;
// ...
}
私は、配列を使用した場合、私は私のユーザーがコメントやドキュメントを読んでいました願っています。
// IMPORTANT! You need to specify 'name' and 'age'
function MagicFunction(array $fred)
{
}
ユースケースに応じて、私はどちらかを使用したりすることがあります。クラスの利点は、私がタイプのようにそれを使用してメソッドまたは任意のイントロスペクションメソッドに型ヒントを使用することができるということです。私は、クエリか何かからのいくつかのランダムなデータセットの周りに渡したい場合は、私はおそらく配列を使用すると思います。だから私は、のフレッドのが私のモデルで特別な意味を持っている限り、私はクラスを使用すると思います。
推測します追記の場合:
ValueObjectsは不変であると考えられています。少なくとも、あなたは、ドメイン駆動設計でエリック・エヴァンの定義に参照のうえされている場合。ファウラーのPOEAでは、ValueObjectsは必ずしも(それが示唆されたが)不変である必要はありませんが、彼らはアイデンティティを持つべきではない、明らかにのフレッドの場合としている。
ようこう問いかけます:
何では、誤植など $myFred['naem']
や誤植など $myFred->naem
?るとともに、同誌掲載号の注目も存在する場合は、そのことはエラーになります。
私のように利用 KISS (い、愚かなってしまいました。
- まだ帰国のサブセットクエリからの方法だけを返します。
- の場合はデータを保存するとして 公的-私的-静的-保護 変数のクラスでランチタイム、アフターとしてstdClass.
- っている場合、後はすぐに埋まりそうですので他のクラスメソッドは、スタイルを好まれるかに厳しいタイピングの
Fred
いなければならないpublic function acceptsClass(Fred $fredObj)
きっと簡単に作成した標準クラスに対して配列の場合として使用するを返します。この場合が考える余厳しい文字を入力す
$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;
プロ:設計時に不明な名前と値の組み合わせを処理することができます。
。、あなたは、オブジェクトを使用する必要があります。あなただけの無関係な値のグループを返すようにしたい場合、それはそれほど明確ではありません。それはパブリックAPIの一部だ場合は、しかし、その後、宣言されたクラスはまだ行くための最良の方法です。
正直、私のようにしています。
- ハッシュ配列方法よりも早く作り、時には。
- が、JSONないようなハッシュアレイ(というようなものOOP OCD).
- ものを複数持つプロジェクトに対して、人はよく規定されたクラスの方がよいでしょう。
- ハッシュ配列がよりCPU時間およびメモリ(オブジェクトはあらかじめ定めた金額でに必ず毎シナリオ。
しかし、吸い込みという考え方である使用されます。のように言った、JSONないようなハッシュ.マットを使って配列の型になります。私変数千行のコードです。
それにしても不愉快な話だが、この授業は、より安全にかかるものと思われます。
適切な値オブジェクトの利点は、実際には無効1と(整合性と「不変性」)が存在するものを変更する方法を作成する方法はありませんということです。ゲッターとパラメータをヒンティング入力だけで、コンパイルのコードでそれを台無しにする方法は、あなたが明らかに簡単に可鍛性配列でいますが、これはありません。
別の方法としては、パブリックコンストラクタで検証し、例外をスローしますが、これは穏やかなファクトリメソッドを提供できます。
class Color
{
public static function create($name, $rgb) {
// validate both
if ($bothValid) {
return new self($name, $rgb);
} else {
return false;
}
}
public function getName() { return $this->_name; }
public function getRgb() { return $this->_rgb; }
protected function __construct($name, $rgb)
{
$this->_name = $name;
$this->_rgb = $rgb;
}
protected $_name;
protected $_rgb;
}
私は10年間でOOP言語で働いています。 あなたは、オブジェクトの仕事の進め方を理解していれば、あなたはそれを愛するだろう。 継承、ポリモーフィズム、カプセル化、オーバーロードは、OOPの重要な利点です。 一方で我々はPHPは、フル機能のオブジェクト指向言語ではないことを考慮する必要がありPHPについて話すとき。 例えば、我々は(簡単な)のオーバーロードメソッドのオーバーロードやコンストラクタを使用傾けるます。
PHPでの連想配列非常に素晴らしい機能ですが、私は害のPHPのエンタープライズアプリケーションと思います。 あなたがコードを書くときに、あなたはクリーンで保守アプリケーションを取得したい。
もう一つは、あなたがインテリセンスを使用することができないということであるあなたが連想配列で失うと思います。
だから私はあなたがcleannerとより保守コードを記述したい場合は、それが与えられたときにOOPの機能を使用するために持っていると思う。
私はあなたの第二の例のようにハードコーディングされた特性を有することを好みます。それがより明確に予想されるクラス構造(およびクラス上のすべての可能性)を定義するような気がします。ただ、常に同じキー名を使用するように覚えてつまるところ最初の例とは対照的に。単にファイルの先頭を見て、プロパティのアイデアを得るために、第2を使用すると、いつでも戻ることができますし、クラスを見てみます。
あなたはより良いあなたが二番目に何かをやっている知っているだろう - あなたはecho $this->doesntExist
しようとした場合、あなたはしません一方、あなたがエラーを取得しますecho array['doesntExist']
しようとした場合、