1

Suppose I have an aggregate, Foo. This aggregate is represented by a simple flat table in the DB...

Foo
------------------------------
| id | prop1 | prop2 | prop3 |
| 1  | a     | b     | c     |
| 2  | a     | bb    | cb    |
| 3  | ac    | bc    | cc    |
------------------------------

Now on the frontend I want to filter Foo. I have a form where the distinct properties of foo need to be displayed as a list and selected from. When a property is selected, I need to query Foo and find the subset of rows with the selected property. Then I need to select the distinct values for each property in the subset of rows selected by the search query.

For example, let's say the user picks a as the value for prop1...

SELECT DISTINCT * FROM Foo WHERE prop1 = 'a';

What's the appropriate way to model this in DDD? My first idea was to create a completely seperate aggregate for modeling the results of the above query or those like it...

class DistinctFooProperties
{
  private $prop1;
  private $prop2;
  private $prop3;
  public function __construct(
    StringCollection $prop1,
    StringCollection $prop2,
    StringCollection $prop3
  ) {
    $this->prop1 = $prop1;
    $this->prop2 = $prop2;
    $this->prop3 = $prop3;
  }
  public function getProp1Possiblities() {
    return $this->prop1;
  }
  public function getProp2Possiblities() {
    return $this->prop2;
  }
  public function getProp3Possiblities() {
    return $this->prop3;
  }
}

class DistinctFooPropertiesMySQLMapper
{
  public function findBySearchObject(FooSearchjObject $fooSearch) {
    // Search and return DistinctFooProperties
  }
}

This leads to a bit of complexity. DistinctFooProperties and FooSearchObject are going to mirror the properties of the Foo aggregate very closely, but far enough that I can't think of an interface to enforce that they all should be talking about the same properties.

Is there a standard way to approach this problem?

Allenph
  • 1,875
  • 27
  • 46

2 Answers2

1

My first idea was to create a completely seperate aggregate for modeling the results of the above query or those like it..

You don't create Aggregates if you need to just find other Aggregates or their attributes. For this you can create Domain services, with the interface defined in the Domain layer and the implementation in the Infrastructure layer. Their methods may return Value objects (like DistinctFooProperties) or even fully-loaded Aggregates, depending on their purpose.

As a side node, the query SELECT DISTINCT * FROM Foo WHERE prop1 = 'a'; will always return distinct rows, with or without DISTINCT if id is unique.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
  • So you would do this query in a layer other than the domain layer? o.O – Allenph May 23 '18 at 15:46
  • 1
    @Allenph of course. The Domain should not know about Infrastructure, and SQL is *very* Infrastructure. – Constantin Galbenu May 23 '18 at 15:47
  • I thought all services were in the application layer? I'm guessing you would have a value object representing the search parameters and a result object representing the results and then a "service" that acts kind of like a mapper? Seems like an aggregate that's not called an aggregate. – Allenph May 23 '18 at 16:10
  • @Allenph Applicatin services take care of transactions and loadin/saving to persistence – Constantin Galbenu May 23 '18 at 16:24
  • I use application services for transactions, but isn't a large part of DDD bounded context of aggregates and therefore their mappers/repositories? I think I see what you mean now. Just seems like that query belongs somewhere in the infrastructure layer, and should then be called in the service layer, no? – Allenph May 23 '18 at 16:30
  • @Allenph what is the "service layer"? – Constantin Galbenu May 23 '18 at 16:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/171635/discussion-between-allenph-and-constantin-galbenu). – Allenph May 23 '18 at 16:44
0

You could use some kind of generic Specification, although depending on your context, mapping it to SQL can be more or less complex. I believe that PHP is a malleable enough language that it won't be too hard though.

guillaume31
  • 13,738
  • 1
  • 32
  • 51