1

I have a grid of values, something like

[
    [0,3,1],
    [0,2,5],
    [1,0,3],
]

I have objects that move on that grid, so they have positions

{
    x: 1.87,
    y: 1.21
}

If we check the upper grid, then the nearest grid point to that position is {x:2,y:1}, so with the simplest algorithm the value for that position is 5 on the grid. Another algorithm would be using distance based weighted average for the nearest 4 grid points.

I update the positions and the grid regularly with 12min and 30min intervals. I get the positions from the clients and I get the grid from an external service. In both cases the values can change for an object. Each object has a different threshold for the value, and when the value reaches the threshold a notification should happen. In reality the condition for the notification is a lot more complex, but I'd like to keep it simple.

The moving objects have other aspects, that don't depend on the grid like the values do.

I thought that having a Grid aggregate root and Grid.update(values), Grid.move(objectId, position) would be a nice solution, but I am a little bit confused. As far as I remember the aggregate root has a consistency boundary, so every time I update an object or I update the grid, I have to lock all grid data and object data for updating instead of just locking the grid or the object data separately. Not sure where I read that, it was many years ago. In this case only the object values are dependent on the grid and when a position changes for a single object, then that does not affect the grid or the other objects, just the value for the actual object. So if I remember well about what an aggregate root means, this design would not be a good one. Doing the other way around and making the Object aggregate root does not seem good either, because I update the grid data independently from the object positions, values and other properties and it does not feel right to cover it with the Object. Should I make both Grid and Object aggregate roots, or what is the proper domain model for this? Should the model contain the intervals I use for updating the grid and/or the positions, or should those exist outside of the model?

2 Answers 2

2

So you require a sort of bidirectional binding between the grid and the objects.

The Grid needs to know about the objects so it can update them when something changes and the User objects need to know about the grid so they can update it when they change position (so it can know if they are affected by updates to the grid)?

I might extract this binding out into its own ObjectPositionOnGrid which could hold a constant reference to the object and the grid.

class ObjectPositionOnGrid<ObjectType, GridType> {

    final ObjectType object;
    final GridType grid;


    public ObjectPositionOnGrid(ObjectType object, GridType grid){
        this.object = object;
        this.grid = grid;
    }

    public void tryMovePositionOnGrid(int x, int y) {
        // tell the grid to move this position
    }

    public void sendGridUpdateToObject(GridUpdate update){
        // send the grid update to the object
    }
}

Or something like that..

2

As said on your other question, don't get bogged down on technicalities that much. Model your problem with the vocabulary that domain experts, or knowledgeable users would understand. That's basically what DDD is/should be about.

So let's do that now. You have a Grid and as far as I can tell its purpose is to calculate some value based on coordinates. So that would mean

public interface Grid {
   double calculateValueAt(double x, double y); // Name this better
}

You used the term "value" to describe what is being calculated, I would try to find a better word for it, if it exists. You can then make different implementations of this Grid, like NearestValueGrid, AveragingGrid, like what you've described.

I don't know what the purpose of changing the grid's values would be. I would just replace the object when values change, if there is nothing else that disallows it.

Also, I don't get why the positions of "objectid" needs to be tracked, there doesn't seem to be any behavior for that from what I understand. If you need to track positions, I would introduce a different object for that, that uses the Grid, instead of putting that into the Grid itself.

Edit

If you want to continuously track and notify (if I understood you correctly) users, there is another object. How about this:

public final class Tracking {
   private Set<User> users;
   private Grid grid;

   ...

   public void updateGrid(Grid newGrid) {
      grid = newGrid;
      users.forEach(u -> u.track(grid));
   }

   public void updateUser(User newUser) {
      users.add(newUser);
      newUser.track(grid);
   }
}

This would be essentially the root of your objects that you are looking for. The User.track(Grid) would then do whatever there needs to be done for a user, send a notification or whatever.

4
  • "I don't know what the purpose of changing the grid's values would be. I would just replace the object when values change, if there is nothing else that disallows it." - It is ok to replace the grid with a new one. Just keep in mind that we can optimize the code if we check the difference between the old and the new grid and calculate new values only for the objects which are near to grid changes.
    – inf3rno
    Dec 12, 2019 at 21:12
  • "Also, I don't get why the positions of "objectid" needs to be tracked, there doesn't seem to be any behavior for that from what I understand." - The positions need to be tracked, because when I update the grid I need to calculate the values for each object again based on the new grid and their position.
    – inf3rno
    Dec 12, 2019 at 21:13
  • The question is mostly about how to model the interaction between the grid and the objects. The grid contains the information necessary to calculate the value for a certain position and the object contains the position and maybe the previously calculated value for that position. The whole grid and the position for an object can be updated independently and in both cases the values are updated for one or more objects. If both the grid and the object are domain objects, then which one should be the aggregate root? The interface you gave just does not answer this question...
    – inf3rno
    Dec 12, 2019 at 21:19
  • This track sounds a lot better, thanks! :-)
    – inf3rno
    Dec 13, 2019 at 0:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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