Application is an offers wall written on PHP/Laravel/Doctrine, where we have a wall created by application user, we have offers what we need to show on the wall, and we have some end-user identifier which is not app user and it does not have own table in system, it's just a string identifier. So I divide app to accounts BC (where we have app user related things), offers BC and walls BC. In this example, we going to work with walls BC.
I have such a DB structure (simplified):
wall:
- id: int
- owner_id: int (User id from another BC)
- name: string
wall_devices:
- id: int
- name: string
- human_name: string
wall_user_device:
- id: int
- device_id: int (relation to wall_device)
- end_user_id: string
- wall_id: int (relation to wall)
wall_banned_users:
- id: int
- wall_id: int (relation to wall)
- end_user_id: string
wall_points:
- id: int
- offer: id (offer id from another BC)
- wall_id: int (relation to wall)
- end_user_id: string
So at first glance, it looks like wall
is an Aggregate Root and wall id is an aggregate identifier, right?
Let's provide an example flow, we need to open a wall for some end user (remember it's just a string), so we have a request with wall.id
and end_user_id
data. Steps:
- using
WallRepository
we getting thewall
aggregate - now we need to get all offers we want to show, but to do so I need to get devices selected by
end_user_id
previously if they exist. In such a case we need to query DB (note I'm telling query DB instead of using repository b-z in DDD repository should work only with the whole aggregate) towall_user_device
table as it's not possible to get it as a part ofwall
aggregate, right?
One more example, end user complete some offer so we need to check if wall_points
exists for end-user and if so change the point status, so again we have a request with wall.id
and end_user_id
data:
- using
WallRepository
we getting thewall
aggregate - now we need to get
wall_points
instance and update if exists. So here again we need to query DB as it's not possible to get withwall
aggregate.
So at this point, I have a feeling that wall
aggregate is not designed correctly as the only thing what he doing is manipulating only a wall
table, and to get all other data we need to make additional queries with a combination of wall_id
/end_user_id
.
So looks like more logically is to somehow create aggregate around the wall_id-end_user_id
combination as an aggregate root entity identifier and to get all the data from the repository as a single aggregate. But I guess it requires creating some workaround to combine few doctrine entities to a single DDD entity if it's even possible
Or another possible solution is to still use wall_id
as an identifier and just join all the data only by wall_id
and filter the data later on by end_user_id
, but in such case, we going to query/manipulate with the huge amount of data as the wall can have tons of end user and this will have a bad effect on app performance.
Maybe someone faced a similar issue and can help me with making a correct architectural decision here?
Also, I want to note that it's an existing/legacy app with the already pretty big database and this part of the app working, so it's not preferred to change DB structure.