1

I am designing an application, which will store sports statistics, show them in different diagrams and do few more operations on them. Allow user to do some mock drafts etc.

I choose to build a domain first, and then create a database via code-fist approach. So I have my entities:
- Player (name, teamId, list of stats)
- Team (name, list of players)
- Stats (beginDate, endDate, playerId, <...different stats in separate columns>...........)

How should I divide them into aggregates? I know Player is an aggregate. I know that List should be in Player aggregate. But what about the Team? Is the team part of Player aggregate or separate one?

I'm confused, cause Player definitely has to have foreign key to the Team. But the Team makes totally sense without a Player (not like Stats, which without a Player doesn't make sense at all - that's why they are part of Player aggregate). I could show statistics for Teams only.

Should the Team be separate aggregate?

EDIT: This is how my domain looks like:

public class Stats
{
    // Stats...
}

public class Player
{
    public Team Team { get; private set; }
    public List<Stats> Stats { get; private set; }
}

public class Team
{
    public string Name { get; private set; }
    public string FullName { get; private set; }
}
5
  • You aren't asking the right questions. Pay attention to the behaviors of your domain and these will help you to design the right aggregate boundaries. What rules have to be protected while performing these behaviors?
    – plalx
    Commented May 31, 2016 at 17:00
  • @plalx Can you direct me a little bit more? "Pay attention to the behaviors", I'm trying, believe me. My situation is: I have rdbms db, 3 tables, I have constraint between Player, Stats (1:many) and Team/Player (1:many). Stats cannot change, can be only appended, Players can change the name and Team, Team can change it's name. But after change it's name it's still the same team (with the same roster). That's all I know for now, I don't know how my team table behaves other than that. What should be my thinking process?
    – Sara
    Commented May 31, 2016 at 22:06
  • Stop thinking about tables and relationships and just think about business use cases. Players can change their names. Is there any rules that governs this process? Is it an important event for the business? What behaviors does exist to manage teams and their players? What rules should be enforced? Do the same exercice for stats. Is there any invariants to protect when recording statistics?
    – plalx
    Commented Jun 1, 2016 at 0:53
  • Does it mean that implementing aggregate pattern means, using nosql db? using event sourcing?
    – Sara
    Commented Jun 1, 2016 at 3:47
  • 1
    Not at all, but it means you should first design your domain model and then figure out how to save it later on. Do not let the relationnal db model get in the way... don't even think about it.
    – plalx
    Commented Jun 1, 2016 at 4:24

1 Answer 1

2

The important question to ask, when designing aggregates, is how does the data change?

For team to be an aggregate implies that it has some state, and even after that state changes it is still the same team. (ie, for team to be an aggregate, it must be an entity -- not merely a value type).

So in your model, do teams change in any interesting ways? By which I mean, in a way that your model cares about? Or are they simply an attribute of a player.

If teams are an entity, and you really care about things that team do (releasing players, acquiring players, and so on), then team should probably be an aggregate, and its state includes a collection of playerIds. (Note, in this model, you probably wouldn't include a teamId within the player aggregate).

On the other hand, if teams are just a property, then they can be a value type within the player aggregate.

That said, I've played in similar domains before -- here's what I do.

Player is an aggregate; but the state of a player is primarily biographical information. When it turns out that some player has been using a false birth certificate, the player aggregate is updated, but that doesn't change any of the relationships with the rest of the model.

Team is an aggregate. I'm currently using team as a collection of players, but that isn't quite right for what I am doing. In my world, the relationship between team and player has some time dependence. So there's some entity like "Contract", that defines the relationship between a player and a team over some time period (start date, end date). The contract is an entity in my model, because the end date of the players "current" contract isn't fixed.

The GameLog in my model is where stats appear. I don't need to worry about specific in game events; I just aggregate a player's performance at the end of a game to create a log entry.

So to get Team stats, I need to look at the contracts to figure out when each Player was playing for them, and use that information to find the appropriate game logs to pull, and then roll up the lot.

Also too: there's a little bit of care to be had, because the sporting events in the real world are not constrained by your domain model. You don't want to be rejecting "real world" data just because your model says that wasn't supposed to happen!

Don't over simplify -- part of the point of domain driven design is to listen carefully to what the ubiquitous language is telling you, and make sure that you are accurately modeling those concepts.

7
  • Well, the team is unchangeable, I think. The team can change the name, but it would not change the roster (like in NBA Supersonic became Thunder? technically it's the same team). The only thing that can change is the roster. But, in such scenario, what actually has changed? The team or the player? I always thought it's the player who has changed (cause player holds teamId). So having said that, my Team shouldn't be an aggregate, rather than just an entity within Players aggregate. Would you agree?
    – Sara
    Commented May 30, 2016 at 23:34
  • @VoiceOfUnreason Why would you have a GameLog AR? Is there any invariants to check across all stats?
    – plalx
    Commented May 31, 2016 at 0:44
  • Two aggregates won't ever share an entity. If you think two players share a team, then Player.team must be a value type. If they reference the same team entity, then that entity must be an aggregate in its own right, and your model looks like Player.teamId. Commented May 31, 2016 at 1:33
  • I'm not the book of record for stats; the GameLog is analogous to an event stream from another bounded context. Commented May 31, 2016 at 1:37
  • @VoiceOfUnreason I'm not sure I understood. So, you said that: If two players share a team, then Player.team must be value. If two players reference the same team entity, that entity must be aggregate. What's the difference? Are you saying that, I'm choosing between Team as a value type and reference type? Because if yes, how come Team can be a value type? An Enum? String? Right now Team is a class (has name, fullname, will have logo, shortcut name etc.. so it's hard to make Team a value type..
    – Sara
    Commented May 31, 2016 at 3:53

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.