Вы моделируете отношения многие-ко-многим: над проектом может работать много людей, а человек может работать над несколькими проектами.
Вы моделируете отношение в качестве роли проекта, которая, помимо того, что служит двунаправленной ссылкой из Person <-> Project, также записывает RoleType и начало / конец этого Person, заполняя этот RoleType в этом проекте. (Заметьте, как в английском языке работает «что» означает FK базы данных или в коде указатель / ссылка?)
Из-за этих FK мы можем в базе данных проследить график от Person через роль Project до Project:
select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where a.person_id = ?
Или мы можем следовать по нему в другом направлении, из проекта:
select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where c.project_id = ?
В идеале, мы хотели бы сделать то же самое в коде C #. Так что да, мы хотим, чтобы у Person был список, а у Project - список, а ProjectRole ссылается на Person и Project.
Да, Project::addPerson( Person& )
действительно должно быть Project::addProjectRole( ProjectRole& )
, если только мы не решим, что Project::addPerson( Person& )
- это удобный метод формы:
void Project::addPerson( Person& p ) {
this.addProjectRole( new ProjectRole( p, &this, RoleType::UNASSIGNED ) ;
}
У ProjectRole нет списка, у него есть ссылка на Person и ссылка на Project. Он также имеет в качестве значений дату начала, дату окончания и RoleType (который является либо перечислением, либо экземпляром класса, который имитирует значение перечисления, то есть существует только один объект на тип перечисления, и это не имеющие состояния, неизменные и идемпотентные, и, следовательно, разделяемые среди многих ролей Project).
Теперь это не должно означать, что получение Person из базы данных должно привести к тому, что вся база данных будет преобразована в граф объектов в коде; Ленивые прокси, которые извлекаются только при использовании, могут спасти нас от этого. Тогда, если мы в настоящее время занимаемся только Человеком, а не его Ролями (и Проектами, мы можем просто извлечь Человека. (Например, NHibernate, я думаю, делает это более или менее плавно).
В принципе, я думаю, что:
1) Это стандартный способ представления отношений «многие ко многим»;
2) Стандартно для отношения иметь дополнительные данные (когда, какого рода)
а также; 3) Вы в значительной степени поняли правильную идею и просто добросовестно получаете обратную связь здесь.