Value Object

Oft haben wir es beim Programmieren mit zwei oder mehr Informationen zu tun, die eng zusammengehören. Beispiele dafür sind 8 Meter, 3 Liter, 4 Kilogramm oder 12,50 Euro. Natürlich könnten wir solche Werte jeweils mit einzelnen skalaren Variablen repräsentieren:

<?php declare(strict_types=1);

namespace spriebsch\tfd\designPatterns\valueObject;

$amount = 200;
$currency = 'EUR';

do_something($amount, $currency);

function do_something(int $amount, string $currency): void
{
    // ...
}
scalar.php

Dabei geht aber schnell was schief, weil wir zusammengehörige Information durch voneinander unabhängige Variablen repräsentieren.

<?php declare(strict_types=1);

namespace spriebsch\tfd\designPatterns\valueObject;

$amount1 = 100;
$currency1 = 'EUR';

$amount2 = 200;
$currency2 = 'GBP';

do_something($amount1, $currency2);

function do_something(int $amount, string $currency): void
{
    var_dump($amount, $currency);
}
confusion.php

So leicht können wir Unsinn produzieren:

confusion.php:15:
int(100)
confusion.php:15:
string(3) "GBP"
Ausgabe von confusion.php
confusion.php ausführen

Welche Alternativen gibt es? PHP unterstützt keine vom Entwickler definierten Datenstrukturen. Wir könnten die beiden Variablen allenfalls in einem assoziativen Array zusammenfassen. Das würde etwa so aussehen:

<?php declare(strict_types=1);

namespace spriebsch\tfd\designPatterns\valueObject;

$money = [
    'amount' => 200,
    'currency' => 'EUR'
];
array.php

Nun müssen wir bei jedem Zugriff prüfen, ob der entsprechende Schlüssel im Array überhaupt existiert. Sonst produzieren wir einen Hinweis und arbeiten unerwartet mit einem Nullwert weiter. Das ist auch nicht wirklich schön und kann schnell zur Fehlerquelle werden.

Noch schlimmer aber ist, dass jeder alle Werte jederzeit nicht nur lesen, sondern auch schreiben und damit verändern kann. Das ist ja fast so schlimm wie das Problem mit den globalen Variablen: Es gerät viel zu schnell außer Kontrolle.

Die Lösung: wir fassen beide Variablen in einem Objekt zusammen.