Skip to content

Commit 9b9ae9f

Browse files
authored
Merge pull request #755 from patchlevel/remove-child-aggregates
remove experimental child aggregates
2 parents b300cc2 + 913bda2 commit 9b9ae9f

32 files changed

Lines changed: 20 additions & 1066 deletions

docs/pages/UPGRADE-4.0.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Upgrade 4.0
22

3+
## Aggregates
4+
5+
### Child Aggregate
6+
7+
We removed our experimental feature of child aggregates.
8+
This was our first attempt to split aggregates into smaller parts,
9+
but we found a better way to do this with the `Micro Aggregate` feature.
10+
311
## Subscription
412

513
The constructor of the `DefaultSubscriptionEngine` class has been changed.

docs/pages/aggregate.md

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ Or for test purposes the `FrozenClock`, which always returns the same time.
653653

654654
In some cases, it makes sense to split an aggregate into several smaller aggregates.
655655
This can be the case if the aggregate becomes too large or if the aggregate is used in different contexts.
656-
We currently support two patterns for this: Micro Aggregates and Child Aggregates (experimental).
656+
For these cases you can use Micro Aggregates.
657657

658658
### Micro Aggregates
659659

@@ -740,96 +740,7 @@ final class Shipping extends BasicAggregateRoot
740740
}
741741
}
742742
```
743-
### Child Aggregates
744743

745-
??? example "Experimental"
746-
747-
This feature is still experimental and may change in the future.
748-
Use it with caution.
749-
750-
Another way to split an aggregate is to use child aggregates.
751-
The difference to Micro Aggregates, child aggregates can only be accessed by the root aggregate
752-
and are not separate aggregates.
753-
754-
In the following example, we have an `Order` aggregate that has a `Shipping` child aggregate.
755-
756-
```php
757-
use Patchlevel\EventSourcing\Aggregate\BasicChildAggregate;
758-
use Patchlevel\EventSourcing\Attribute\Apply;
759-
760-
final class Shipping extends BasicChildAggregate
761-
{
762-
private bool $arrived = false;
763-
764-
public function __construct(
765-
private string $trackingId,
766-
) {
767-
}
768-
769-
public function arrive(): void
770-
{
771-
$this->recordThat(new Arrived());
772-
}
773-
774-
#[Apply]
775-
public function applyArrived(Arrived $event): void
776-
{
777-
$this->arrived = true;
778-
}
779-
780-
public function isArrived(): bool
781-
{
782-
return $this->arrived;
783-
}
784-
}
785-
```
786-
!!! warning
787-
788-
The apply method must be public, otherwise the root aggregate cannot call it.
789-
790-
!!! note
791-
792-
Supress missing apply methods need to be defined in the root aggregate.
793-
794-
And the `Order` aggregate root looks like this:
795-
796-
```php
797-
use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot;
798-
use Patchlevel\EventSourcing\Aggregate\Uuid;
799-
use Patchlevel\EventSourcing\Attribute\Aggregate;
800-
use Patchlevel\EventSourcing\Attribute\Apply;
801-
use Patchlevel\EventSourcing\Attribute\ChildAggregate;
802-
use Patchlevel\EventSourcing\Attribute\Id;
803-
804-
#[Aggregate('order')]
805-
final class Order extends BasicAggregateRoot
806-
{
807-
#[Id]
808-
private Uuid $id;
809-
810-
#[ChildAggregate]
811-
private Shipping $shipping;
812-
813-
public static function create(Uuid $id, string $trackingId): static
814-
{
815-
$self = new static();
816-
$self->recordThat(new OrderCreated($id, $trackingId));
817-
818-
return $self;
819-
}
820-
821-
#[Apply]
822-
public function applyOrderCreated(OrderCreated $event): void
823-
{
824-
$this->shipping = new Shipping($event->trackingId);
825-
}
826-
827-
public function arrive(): void
828-
{
829-
$this->shipping->arrive();
830-
}
831-
}
832-
```
833744
## Aggregate Root Registry
834745

835746
The library needs to know about all aggregates so that the correct aggregate class is used to load from the database.

src/Aggregate/AggregateRootAttributeBehaviour.php

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
namespace Patchlevel\EventSourcing\Aggregate;
66

77
use Patchlevel\Hydrator\Attribute\Ignore;
8-
use Patchlevel\Hydrator\Attribute\PostHydrate;
98
use ReflectionProperty;
109

1110
use function array_key_exists;
12-
use function count;
13-
use function explode;
1411

1512
trait AggregateRootAttributeBehaviour
1613
{
@@ -20,10 +17,6 @@ trait AggregateRootAttributeBehaviour
2017
#[Ignore]
2118
private AggregateRootId|null $cachedAggregateRootId = null;
2219

23-
/** @var (callable(object $event): void)|null */
24-
#[Ignore]
25-
private $recorder = null;
26-
2720
protected function apply(object $event): void
2821
{
2922
$metadata = static::metadata();
@@ -38,58 +31,7 @@ protected function apply(object $event): void
3831

3932
$method = $metadata->applyMethods[$event::class];
4033

41-
if ($metadata->childAggregates === []) {
42-
$this->$method($event);
43-
44-
return;
45-
}
46-
47-
$parts = explode('.', $method);
48-
49-
if (count($parts) === 2) {
50-
[$property, $method] = $parts;
51-
52-
$child = $this->getChildAggregateByPropertyName($property);
53-
54-
if ($child !== null) {
55-
$child->$method($event);
56-
}
57-
} else {
58-
$this->$method($event);
59-
}
60-
61-
$this->passRecorderToChildAggregates();
62-
}
63-
64-
#[PostHydrate]
65-
private function passRecorderToChildAggregates(): void
66-
{
67-
$metadata = static::metadata();
68-
$this->recorder ??= $this->recordThat(...);
69-
70-
foreach ($metadata->childAggregates as $propertyName) {
71-
$child = $this->getChildAggregateByPropertyName($propertyName);
72-
73-
if ($child === null) {
74-
continue;
75-
}
76-
77-
$child->setRecorder($this->recorder);
78-
}
79-
}
80-
81-
private function getChildAggregateByPropertyName(string $propertyName): ChildAggregate|null
82-
{
83-
$reflectionProperty = new ReflectionProperty($this::class, $propertyName);
84-
85-
if (!$reflectionProperty->isInitialized($this)) {
86-
return null;
87-
}
88-
89-
/** @var ChildAggregate|null $child */
90-
$child = $reflectionProperty->getValue($this);
91-
92-
return $child;
34+
$this->$method($event);
9335
}
9436

9537
public function aggregateRootId(): AggregateRootId

src/Aggregate/BasicChildAggregate.php

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/Aggregate/ChildAggregate.php

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/Aggregate/ChildAggregateBehaviour.php

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/Attribute/ChildAggregate.php

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/Metadata/AggregateRoot/AggregateRootMetadata.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ public function __construct(
2525
public readonly array $suppressEvents,
2626
public readonly bool $suppressAll,
2727
public readonly Snapshot|null $snapshot,
28-
/** @var list<string> */
29-
public readonly array $childAggregates = [],
3028
string|null $streamName = null,
3129
) {
3230
$this->streamName = $streamName ?? $this->name . '-{id}';

0 commit comments

Comments
 (0)