Disclaimer:
Even voor de duidelijkheid: ik wil geen discussie starten over hoe je het beste een URL kan parsen.
Ik weet dat er 1001 bestaande oplossingen zijn, maar dit gaat puur over architectonische keuzes maken met value objects in value objects.
Een URL heeft meerdere fragmenten/componenten:
scheme, user, password, lld, sld, tld, port, path, query en fragment.
Deze componenten zijn opgeslagen in een value object. Echter is de query component op zich zelf ook een value object die opgeslagen wordt in de URL value object.
Een van de eigenschappen van een value object is dat deze immuttable is. En hiermee is direct het probleem.
Even wat (versimpelde) code ter illustratie:
Voorbeeld:
So far so good. Maar wanneer de query param geset wordt, dan is er op dit moment geen mogelijkheid om deze nieuwe waarde terug te krijgen middels het "$url" object:
Dit is heel logisch maar wel een probleem. Ik ben hier over gaan nadenken en kwam met de volgende potentiële oplossingen. De één nog minder mooi dan de ander:
Even voor de duidelijkheid: ik wil geen discussie starten over hoe je het beste een URL kan parsen.
Ik weet dat er 1001 bestaande oplossingen zijn, maar dit gaat puur over architectonische keuzes maken met value objects in value objects.
Een URL heeft meerdere fragmenten/componenten:
scheme, user, password, lld, sld, tld, port, path, query en fragment.
Deze componenten zijn opgeslagen in een value object. Echter is de query component op zich zelf ook een value object die opgeslagen wordt in de URL value object.
Een van de eigenschappen van een value object is dat deze immuttable is. En hiermee is direct het probleem.
Even wat (versimpelde) code ter illustratie:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| class URL { private string $scheme; private Query $query; public function __construct(string $scheme) { $this->scheme = $scheme; $this->query = new Query(); } public function setScheme(string $scheme): self { return new self($scheme); } public function getScheme(): string { return $this->scheme; } public function getQuery(): Query { return $this->query; } } class Query { private array $query = []; public function setParam(string $key, string $value): self { $instance = new self(); $instance->query = $this->query; $instance->query[$key] = $value; return $instance; } public function getParam(string $key): ?string { return $this->query[$key] ?? null; } } |
Voorbeeld:
PHP:
1
2
3
4
| $url = new Url('http'); $url->getScheme(); //http $url = $url->setScheme('https'); $url->getScheme(); //https |
So far so good. Maar wanneer de query param geset wordt, dan is er op dit moment geen mogelijkheid om deze nieuwe waarde terug te krijgen middels het "$url" object:
PHP:
1
2
| $url= $url->getQuery()->setParam('foo', 'bar'); $url->getQuery()->getParam('foo'); //Error, want $url is nu een Query object |
PHP:
1
2
3
| $query = $url->getQuery(); $query->setParam('foo', 'bar'); $url->getQuery()->getParam('foo'); //Null |
Dit is heel logisch maar wel een probleem. Ik ben hier over gaan nadenken en kwam met de volgende potentiële oplossingen. De één nog minder mooi dan de ander:
- Zal ik in plaats van een value object, moeten werken met entities? Dit lijkt alleen geen entity naar mijn mening maar zorgt er wel voor dat deze niet immuttable is. Eventueel kan een getImmuttable method toegevoegd worden.
- Zal alle methods moeten kopiëren van de query object naar de url object ($url->setParam() ipv $url->getQuery()->setParam()) met als gevolg dat alle methods een kopie zijn en ik me begin af te vragen waarom de query object dan nog nodig is als alleen staand object (het helpt wel tegen de anti pattern genaamd train wreck)
- Moet er een extra methode komen genaamd setQuery in het url object die enkel het query object accepteert met als gevolg dat de gebruiker de query kan ophalen en opnieuw kan setten (wat erg omslachtig is)?
- Moet de parent (in dit geval url) mee gegeven worden aan het query object zodat als het query object geüpdatet wordt, deze een seintje kan geven aan de parent dat deze vernieuwd is? Hierdoor is het Query object wel direct gekoppeld aan de parent waardoor deze moeilijk los gebruikt kan worden.
- Zal ik afstappen van het idee (in dit geval) dat een value object immutable is? Vind ik persoonlijk geen mooi streven.
- Moet ik afstappen van value objects in value object?
[ Voor 3% gewijzigd door ZeroXT op 31-07-2021 13:45 ]