Может ли два объекта иметь несколько типов отношений?

Скажем, у меня есть много-много отношений в базе данных:

CREATE TABLE Person (ID int, name varchar(100), dateofbirth datetime, Gender char(1), primary key (ID))
CREATE TABLE Sport (ID int, description varchar(30), primary key (ID))
CREATE TABLE PersonCanPlaySport (Person ID int references Person(ID), SportID int references Sport(ID), PRIMARY KEY (SportID, PersonID))

В таблицах показано, какие спортивные состязания может принять человек. Теперь посмотрите класс ниже:

public class Person
{
   public List<Sport> Sports;
   public int FitnessLevel;
   public datetime DateOfBirth;
   public string Gender; //M or F

   public Person()
   {
     Sports = new List<Sport>();
   }

   //allSports contains all the sports from the database i.e. allSports contains about 100 sports.  AddSports determines what sports (out of the 100) that the user can participate in based on: Gender, age, Fitness Level etc
   public void AddSports(List<Sports> allSports)
   {
      Sports.Clear();
      ((List<Sport>)Sports).AddRange(allSports
      .Where(sport => sport.CanPlay(this)));
   }

}

Похоже, что отношения между Ассоциацией и отношениями между человеком и спортом связаны между собой. Вот почему:

1) Человек создает экземпляр списка видов спорта в конструкторе, поэтому контролирует жизненный цикл спорта 2) Лицо использует список видов спорта в AddSports, который, я считаю, делает его Ассоциацией

Это запах кода? Какая связь существует между этими двумя объектами? Как это будет отображаться на объектной диаграмме?

Обновление

Следуя полезному ответу и комментариям от @Neil; Я считаю, что он предлагает сделать это:

//Application Service Layer
List<Sport> sports = Repository.GetAllOffers();
foreach sport As Sport in sports
{
   person.AddSports(sport);
}

//Domain class
public class Person
{
   public List<Sport> Sports;
   public int FitnessLevel;
   public datetime DateOfBirth;
   public string Gender; //M or F

   public Person()
   {
     Sports = new List<Sport>();
   }

   public void AddSport(Sport sport)
   {
      if(sport.CanPlay(this))
      {
         Sports.Add(sport);
      }
   }

}

Я не уверен, нравится ли мне идея, что слой Application Service должен пересекать Sports.

3 голоса | спросил w0051977 21 22017vEurope/Moscow11bEurope/MoscowTue, 21 Nov 2017 12:15:11 +0300 2017, 12:15:11

1 ответ


3

Связь базы данных между Person и Sport, как я понимаю, это много-ко-многим, с промежуточной таблицей PersonCanPlaySport, которая соединяет эти два. Это означает, что Person может быть связан со многими Sports и Sport могут быть связаны со многими Persons

Теперь, когда мы понимаем отношение к базе данных, отношения, используемые в коде, не должны отличаться. Потенциально экземпляр Person имел бы список Sport и Sport будет иметь список Person.

Я думаю, поэтому было бы неправильно поставить логику того, должен ли иметь Person конкретный Sport непосредственно внутри Person или наоборот. Рассмотрим использование объекта PersonSportDao, который задает Person, может вернуть все Sports и указать Sport может вернуть все Persons. Вызывающий вызов AddSports сделает вызов PersonSportDao, или еще лучше, Person сам загружает свой Sports при запросе, вызывая PersonSportDao с помощью this.

Если вы хотите проверить данные о возрасте или полом, вы можете создать другой класс PersonSportManager. Другими словами, Person не является владельцем Sport, и поэтому он не должен видеть ни одну логику, как Sport не является владельцем Person, и поэтому он не должен видеть никакой логики Person.

Если Person до Sport отношения «один ко многим», я бы поспорил иначе, но я думаю, что код должен отражать симметрию отношения к базе данных.

Изменить: Отвечая на ваш вопрос:

  

Это запах кода? Какая связь существует между этими двумя   объекты? Как это будет отображаться на объектной диаграмме?

Отношение композиции подразумевает, что Sports составляет Person, который похож на отношение «один ко многим» между Person и Sport. В вашем случае это неверно, будучи многими ко многим.

Отношения слишком сложны, чтобы просто нарисовать линию между двумя, что необходимо для создания среднего класса, а затем связать Person и Sport оба для этого среднего класса (например, PersonSportManager

Надеюсь, что ответит на ваш вопрос!

ответил Neil 21 22017vEurope/Moscow11bEurope/MoscowTue, 21 Nov 2017 12:38:53 +0300 2017, 12:38:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132