4

A play arena contain a list of Machines and Amenities

playArena : 
  guid : GUID
  name : string
  location: Location
  owner: string
  amenities: Amenities
  playing_machines: PlayingMachines


Amenities is list of  Amenity -> Array<Amenity>
PlayingMachines is list of PlayingMachine ->  Array<PlayingMachine>

Initial use case there may not be filled with too much business logic that can be assigned however with increasing application use and feedback there will be. I know its YAGNI/KISS violation however the changes are predicted in near future even though the present use case may feel as simple as CRUD application.

At present the basic use cases are

  • A play arena should have at least 1 machine and amenities are optional.
  • Play arena owner can update the arena, machine and amenities.
  • Owner can add, update or remove the machines.
  • Owner can add, update or remove the amenities.
  • Owner can change other attributes for the arena.
  • **Play arena have list of machines and a machine can belong to multiple play arena. Its kind of m-n relation **

These use cases don't seem too much filled with business logic and are more or less CRUD only.

How can I still use DDD and implement these changes. Should I allow add, update and deleted for machine and amenities directly with their own repository or make arena as aggregate root and pass any changes through arena repository only.

For second case : Let's say only machine are changed do we need to still call arenaRepo.updated(arena) -> and update all the attributes even though only machine are changed.

In first case: I can call getAllMachinesByArenaId(): see which are existing machine and which are new machine and directly update the database by calling the machineRepository.save(udpatedMachines). (A kind of upsert operation)

A more practical example:

Owner wants to setup an arena (this arena may already exist or a new one) and then add machines (may exist as separate entity and associate to arena) to that arena.

Given a request DTO containing:

  • An owner id
  • A arena id (To check if the station exist)
  • Arena details if station does not exist.
  • List of machine :
  • each machine also contain
    • machine id or machine code if already exist (getMachineById/ getMachineByCode) enter code here
    • machine with machine details if does not exist, it has to create one

UseCase can be:

AddingMachine() 
PlayArenaSetup() 
InstallingMachineToArena()

First we have to create machine through machine aggregate and then arena and then mapping arena and machine. In case any one fails do we include all three command as single unit of work or

AddingMachine() is one unit of work
and PlayArenaSetup() 
InstallingMachineToArena() is another unit of work?
0

2 Answers 2

1

How can I still use DDD and implement these changes. Should I allow add, update and deleted for machine and amenities directly with their own repository or make station as aggregate root and pass any changes through station repository only.

In your domain, if machines and amenities can live without being in an play arena then yes they must be their own aggregate root (in your case it would also result in creating a repository for each to ensure persistence).

If not, then their lifetime should be managed by a play arena only (instantiated within the class, no separate repository).

As far as I understand, play arena is in any case an aggregate root.


For second case : Let's say only machine are changed do we need to still call arenaRepo.updated(arena) -> and update all the attributes even though only machine are changed.

In case machines are not aggregate roots, then yes (you won't have a machine repository anyway). Most ORMs will notice that only the machine collection has changed and will only update the necessary tables/columns.


In first case: I can call getAllMachinesByArenaId(): see which are existing machine and which are new machine and directly update the database by calling the machineRepository.save(udpatedMachines). (A kind of upsert operation)

In case machines are aggregate roots, save them after creation via their corresponding repository. A call to getAllMachinesByArenaId() is not necessary since they live without the concern of being aggregated inside a play arena.


First we have to create machine through machine aggregate and then arena and then mapping arena and machine. In case any one fails do we include all three command as single unit of work or

AddingMachine() is one unit of work and StationSetup() InstallingMachineToArena() is another unit of work?

A command should operate on only one aggregate root which means that AddMachine() is one unit of work.

Then it depends.

If it is an invariant that a play arena must have at least one machine in order to exist then a second command (one unit of work) does both the arena creation and linking the previously created machine. In an OO world this is typically done by requesting the initial machine through the arena constructor.

If an arena can exist without any machine then it is up to your use cases to decide if one or two commands are appropriate. If an arena could be created and only at some point later in time (with a different use case) a machine be associated with it, then go with two commands (one for StationSetup() and one for InstallingMachineToArena()). If the machine is linked to the arena in the same use case than the arena creation then you could use one command (StationSetupAndMachineInstallation()) with the difference being in the arena being set in two steps: arena construction (without providing the machine) and then adding the machine to the arena.

Makes sense ?

4
  • Machines can be independent as they can belong to multiple arenas. A unique kind of machines like play machines model can be fixed in various play arenas. Still we need to add machine to arena so addMachine() and installMachineToArean() are two different commands. installMachineToArena() has to make sure the addMachine() is successful to make successful transaction.
    – Mr X
    Jun 10, 2022 at 9:39
  • @MrAJ I'm not sure to understand what the difference between addMachine() and installMachineToArena() is. Is the first one persisting the entity and the second one linking it to a play arena ?
    – Spotted
    Jun 10, 2022 at 11:05
  • Yes. A machine with some code lets say MAX-003, MAX-008 has specific type of specifications and can be installed in multiple arenas. So to install it has to be persisted and similarly arena with some id ARX-002, ARX-001 has to be persisted. Once both are sure then we can associated as ARX-002, -> [MAX-003, MAX-008] and ARX-001 -> [ MAX-008 ]
    – Mr X
    Jun 10, 2022 at 11:09
  • @MrAJ Ok, I have updated my answer with these new insights
    – Spotted
    Jun 10, 2022 at 11:23
0

Deciding if an entity should be modeled as an aggregate on its own and broken out of a bigger aggregate should not so much be decided depending on being able to live on its own. From my experience, that should be rather decided based on the fact that there are use cases where you want to change that entity on its own. And there are no business rules to be adhered that always have to be considered that require checks across all other entities of that type that need to be performed by the aggregate the entity is currently modeled to be part of.

Aggregates should be optimized for write operations and the corresponding behaviour and respective business invariants that need to be adhered whenever such an aggregate is created or changed rather than thinking of a tree of objects and their relationships.

In your case, as it seems to me from your description, Machine seems to be such a case. Thus it would make sense to model it as an aggregate on its own and rather work with references to that machines in your Arena aggregate. Maybe would what you currently named PlayingMachine could rather be a custom value object containing just the id (i.e. reference) of the respective machine.

First we have to create machine through machine aggregate and then arena and then mapping arena and machine. In case any one fails do we include all three command as single unit of work or

This sounds to me like a valid approach and would also lead to a more task-based user interface and user experience as opposed to a CRUD one (with one big Arena aggregate created at once). DDD is much more suited to work with task-based user interfaces and can better provide it's strengths better with such a way of user interactions as each step is also much more explicit and usually also better reflects how humans would interact with the system if it was not a software application.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.