Словари имеют значение!
Сначала я думал как qwerty_so , за исключением того, что:
- существует квалифицированная ассоциация с
UserProfiles
: это реализовано с помощью IDictionary
, где string
используется для определения User
. - эта ассоциация ориентируется в одном направлении, поскольку вы можете легко go от
User
до UserProfile
, но гораздо труднее go наоборот (вы можете, но вы приходится перебирать все варианты использования).
Таким образом, диаграмма может выглядеть следующим образом:
Некоторые дополнительные замечания об этой диаграмме:
- Не существует стандарта UML для свойств C#, которые представляют собой смесь между свойством UML и операцией UML (через неявные методы получения и установки). Обычной практикой является использование профиля UML, который определяет стереотип
«property»
. Мой собственный предпочтительный вариант - оставить его в свойствах класса (например, здесь или здесь ), поскольку это semanti c свойства C#. Однако некоторые утверждают, что этот стереотип следует рассматривать как специализацию операции UML (например, здесь и в ответе qwerty), что также является допустимым аргументом, особенно если вы определяете пользовательские методы получения и установки. - Будьте осторожны с множественностью в квалифицированной ассоциации, так как это относится к
User
, квалифицированному со строкой. Таким образом, 0..1 UserProfile предназначен для одной конкретной c комбинации пользователя и строки. Так что в действительности это 0 .. * если бы мы рассматривали неквалифицированное User
.
Преобразование модели
Мы должны помнить, что данная реализация может соответствовать различным проектам. Реализация - это то, как вы пишете код, а дизайн - то, как вы видите вещи.
Таким образом, мы можем преобразовать эту первую обращенную модель, чтобы она соответствовала вашей модели мышления. Только вы можете сказать, как вы хотите видеть то, что привело вас к вашей текущей реализации.
Например, вас может не интересовать навигация, и вы можете сосредоточиться на множителях «многие ко многим». связь между неквалифицированными User
и UserProfile
. При таком подходе строка, использованная в качестве квалификатора, станет свойством класса ассоциации :
![enter image description here](https://i.stack.imgur.com/CB2Vc.png)
Тем не менее помните что это трансформация. Квалифицированная ассоциация и «один ко многим» не одно и то же, и эти две модели не означают одно и то же.
А вот и n-арная ассоциация!
Теперь ключевым вопросом является назначение свойства string в этом классе ассоциаций. Я сильно подозреваю, что это на самом деле id
вашего Application
(я позволю вам подтвердить в комментариях).
Если это так, у нас будет ассоциация между классом ассоциации и Application
. И мы можем удалить строковое свойство из класса ассоциации, потому что тогда оно будет избыточным.
Но ассоциативный класс, который сам связан с каким-то другим классом, показывает, что на самом деле существует n-арная ассоциация (троичный здесь). Итак, мы можем сделать это явно:
![enter image description here](https://i.stack.imgur.com/DnQVZ.png)
Теперь у вас есть n-арная ассоциация. Вы могли бы даже иметь класс ассоциации за ним, если бы были дополнительные свойства для связи с каждым триплетом (User, Application, UserProfile).
Но учтите, что эта диаграмма менее точна. Например, более сложно указывать ограничения навигационной способности в n-арной ассоциации. И это больше не полностью соответствует вашей реализации: эта модель предполагает, что вы можете найти пользователей, начиная с приложения, тогда как в вашей реализации это сложнее.
Заключение / советы
Лично мне трудно работать с n-арными ассоциациями, и я предпочитаю разбивать их на наборы классов и бинарных ассоциаций (и классов ассоциаций, когда это необходимо): это позволяет устранить много неоднозначности и дает более жесткий контроль. Я могу только рекомендовать вам такой же подход.
Рассмотрим также вашу реализацию: если реализация представляет ваш взгляд на мир, используйте квалифицированную ассоциацию, потому что это UML-эквивалент словаря.
Однако, если троичная ассоциация - это ваш взгляд на мир, вам, возможно, рано или поздно придется пересмотреть текущую реализацию. Вероятно, вы бы извлекли профили, чтобы создать собственный класс.