views:

116

answers:

4

Hi, i'm not sure how to model this relationship...

A classroom contains many seats, every student studies in a classroom and have a favorite seat within it.

The way i see it, i have two aggregate roots: classroom and student, seats a are entities aggregatged by classroom...

And for a student to have a fovorite seat, it must hold a reference to it (seat isn't an aggregate root).

Any suggestions? Thanks in advance, Erik.

A: 

Hmm, it depends... I'd maybe have classroom aggregate with seats like you. Students could be entities, but seats look more like value objects to me. However, all that depends on your context. I am not sure what is important for you, if my suggestion doesn't make sense, please explain your context.

Gabriel Ščerbák
Hi, thanks for the reply, seat probably isn't a value object...i can have a seat with exacly the same data in two separate classroms...The requirements are:A. The user can choose the classroom in which he would like to study.B. After choosing a classroom, the user can choose a favorite seat in the classroom.I didn't find a way to model those use cases without student referencing seat (which isn't an aggregate root, and is an entity whithin classroom).Thanks in advance,Erik.
Erik Ashepa
If the data in the seat are the same, and when you are accessing the seat, you use particular classroom aggregate root, you probably know everything about the seat and you spared much data (Flyweight design pattern). This could also simplify the favourite seat association, which would contain classroom reference and seat value.
Gabriel Ščerbák
sorry, but i didn't understand... are you suggesting seat is a value object? would the student be referencing the seat class directly?The is a one to many relationship between classroom and seats.. how is that possible?
Erik Ashepa
Honestly, I did some thinking and I am not so sure anymore what is the right approach to your problem in DDD, so I will do some reading and if I get on something real, I will answer.
Gabriel Ščerbák
Thanks :)) i'll do some reading too!
Erik Ashepa
A: 

A possible option would for each seat have a list of the students that the seat is favorite of. The Classroom aggregate root would be responsible for maintaining the constraint that a student can not have more than one favorite seat in the classroom. With this option seat is an entity (not a value object) aggregated by classroom with references to the students.

zesc
Thanks for the suggestion, I've thought about this approach, but it has it's flaws...1. Seats know about students... Probably with a method like: seat.MakeFavoriteByStudent(Student student).2. There could be integrity and consistency problems when deleting a student.Overall this is pretty good because when deleting a door it would delete the favorite seats assignments for the students referencing it...
Erik Ashepa
Are seats value object or entities? What makes on seat in on class different from another seat in the same class? Do seats only have row, column attribute? If they are value objects it could mean that the same seat (example: row=1, col=1) is referenced by N classrooms. In this case I would make the seat aggregate root and add a reference from student. If the user can choose diff seats per classroom I may add a FavSeatClassroom entity aggregated by Student with refernce to Classroom and seat.
zesc
I guess that it depends... the way i see it, seat is an entity (it has local identity), two classrooms may both have a seat at row=1 and col=1, but it isn't the same seat... i can delete that classroom and the seat would be deleted too...that is why seat probably isn't an aggregate root...I've thought about this some more, and i guess that seat should be referenced by student... breaking the referencing law... this would add integrity validation (you can't delete a classroom if a student is referencing a seat and the other way around)...
Erik Ashepa
A: 

It sounds like you need to introduce a value object, Location, which describes a spot in a classroom, and you can then model them like this in the student class:

public IDictionary<Classroom, Location> FavoriteSeats;

Classrooms can reference Seat entities by their locations.

(If they really are entities in the first place - you may even discover that you don't need to model seats as entities (e.g., "The blue plastic chair that smells like hamburger).)

Jeff Sternal
A: 

Months after the OP, but just in case it's useful.

@Jeff Sternal is on the right track. The problem is fundamentally about managing a 3 way (ternary) relation among students, classrooms and seats. Since it's a relational problem, let's stay with relational concepts for now and call it FavouriteSeat(Student, Classroom, Seat).

As described, the problem doesn't require any knowledge about any of them other than a unique identifier. Let's use a pseudo type 'ID' for now (doesn't really matter, as long as each is unique).

In pseudo-sql, we have:

create table FavouriteSeat(
   StudentID ID not null,
   ClassroomID ID not null,
   SeatID ID not null)

Standard CRUD (create/read/update/delete) ops on that table provide all the operations required. However, it's missing some constraints. Right now, a student could have 2 or more favourite seats in a classroom. Although not explicitly stated, the OP implies that a student should have at most one (0 or 1) favourite seat in any given classroom.

We can fix that by adding a unique key on the table. Again using pseudo-sql:

alter table FavouriteSeat add unique key (StudentID, ClassroomID) 

Now a student can only have one favourite seat for any given classroom. There's still a remaining question. The solution doesn't currently support defining what seats are available in what classrooms. We can solve that by:

  1. Adding a new table that lists the valid seats in each classroom:

    create table ClassroomSeat ( ClassroomID ID not null, SeatID ID not null)

    alter table ClassroomSeat add unique key (ClassroomID, SeatID)

  2. Adding a foreign key to the FavouriteSeat table so it can only reference valid ClassroomSeats:

    alter table FavouriteSeat add Foreign Key FK_Seat (ClassroomID, SeatID references FavouriteSeat (ClassroomID, SeatID).

That's it. 2 relations, 3 keys and standard CRUD operations cover all the requirements as stated.

The relational model can be translated in OO/DDD pretty easily. It needs an Entity for FavouriteSeat and ClassroomSeat with methods for the CRUD ops. The methods would have to enforce the unique & foreign key constraints above.

To meet just the requirements stated, Customer, Classroom and Seat could be value types (although there may be wider unstated reqs that may change that). Either way they need a unique identifier property that can be checked in the FavouriteSeat methods.

sfinnie