У меня есть диаграмма ERD электронной коммерции со следующими объектами Product
, Tag
, ProductTag
, Category
и, конечно, другими объектами.
Я попытался преобразовать его в диаграмму классов следующим образом:
1- removed the id
2- converted the foreign key into object of the type i'm refering to(product_id converted into => product: Product)
мой вопрос в том, является ли этот подход хорошим для всех моих сущностей? нравится ли это достижение принципа SOLID? У меня презентация через 2 дня, и я хочу быть очень уверенным в том, что я сделал, любого комментария или модификации будет действительно достаточно. Я также выбрал эти таблицы, потому что они представляют один ко многим и многие ко многим. заранее спасибо.
извините, но английский не мой родной язык, на что посоветуете заменить has
? , я не понимаю the AC connector is flawed
, у общей агрегации нет семантики как, я не понимаю, не могли бы вы описать свой комментарий подробнее и использовать простой язык?
В принципе ваш подход правильный. Вы ошиблись всего в нескольких спецификациях UML.
Метка в середине разъемов — это просто название разъема. Если вы не используете какое-то волшебство OCL, это имя не имеет смысла. Есть способ украсить его черным треугольником, чтобы показать направление чтения. Это иногда помогает деловым людям понять, как классы связаны друг с другом (см. рис. 11.27 на стр. 202 UML 2.5). Но обычно вы бы не использовали его.
У общей агрегации нет семантики (стр. 110 UML: Указывает, что свойство имеет общую семантику агрегации. Точная семантика общей агрегации зависит от области приложения и разработчика моделей). Так что оставьте открытый ромб подальше. Композит (закрашенный ромб) можно использовать для демонстрации ответственности (когда меня убьют, я сначала убью свои композиты). Обычно он добавляет слишком мало, чтобы быть действительно полезным, он только подогревает бесполезную композицию-дискуссию.
Неверное направление навигации. AC в середине видит оба подключенных класса, поэтому он показан без стрелок. Если у вас есть дополнительная (направленная) ассоциация, вы размещаете ее как одиночный (дополнительный) коннектор. В этом случае поместите имена ролей в любой конец. Это делает навигацию более понятной, чем простая стрелка. Я для себя использую стрелки только на черновых набросках на чертежной доске.
P.S. Просто заметив, что у вас есть операции в ваших классах, которые имеют то же имя, что и класс, и принимают один параметр, являющийся также классом. Я предполагаю, что вы намереваетесь показать здесь конструктор. В этом случае вы бы сделали это Classname():Classname
и предоставили только те параметры, которые необходимы для конструктора. В противном случае эти операции не имеют особого смысла. Точно так же операции CRUD, похоже, работают со списком «самих себя», что также, вероятно, нежелательно. У вас будет класс коллекции, который обрабатывает базовый класс, где эти операции имеют смысл. Итак, подведем итог: вы должны добавить операции получения/установки только для (частных) свойств, соответствующих столбцам из вашей таблицы.
P.P.S.: Согласно комментарию Кристофа, было бы неплохо украсить операцию создания экземпляра класса стереотипом <<create>>
, который подчеркивает ее цель. См. стр. 196 UML 2.5:
Этот стереотип является частью стандарта (см. с. 677) и таблицы на с. 678 штатов:
Указывает, что назначенный признак создает экземпляр классификатора, к которому присоединен признак.
Очень исчерпывающий ответ! Я всегда задаюсь вопросом, не должно ли формально быть «создать» перед конструктором или это необязательно.
@Christophe Я не думаю, что это обязательно, но в любом случае это хороший выбор, чтобы выделить конструктора. Добавлю эту информацию.
Если бы я мог переголосовать или суперголосовать, я бы это сделал ;-)
На часть вашего вопроса о моделировании уже есть идеальный ответ. Тем не менее, для записей я хотел бы добавить дополнительный ответ в части SOLID:
Единственная ответственность: у ваших классов есть несколько причин для изменения, потому что вы можете захотеть изменить Product
таким, какое оно есть (например, добавить больше атрибутов, связанных с продуктом), но вы также можете изменить класс, чтобы добавить новые getByXxx()
операции для поиска. продукты в базе данных на основе других критериев, независимо от того, что продукт на самом деле представляет собой. ТАК это не соответствует.
Принцип открытого-закрытого: мы не можем сказать
Принцип замещения Лисков: при отсутствии наследования это не имеет значения. Более того, вы не могли бы сказать, не имея предусловия, постусловия и инвариантных ограничений.
Принцип разделения интерфейса: вероятно, не соответствует требованиям, потому что вы навязываете неявный интерфейс, который должны предоставлять все наследующие классы, даже если они им не нужны (например, продукты, не хранящиеся в базе данных). Первым шагом в правильном направлении было бы использование интерфейса для общих операций с базой данных.
Инверсия зависимостей: мы не можем сказать, но, вероятно, это не так, потому что update(), delete(),... вероятно, зависит от какой-то базы данных, так что вы не можете переключить ее на другую базу данных. С помощью DIP вы внедрите базу данных в класс, который ее использует, чтобы вы могли в любой момент внедрить другую базу данных, предлагающую такой же интерфейс.
Вы не спрашивали, но ваш дизайн вроде бы соответствует активным записям . Если вы хотите перейти к более чистому и НАДЕЖНОМУ дизайну, вам следует исключить код, связанный с базой данных, вместо репозиториев или шлюзов табличных данных.
На беглый взгляд: выглядит не так уж и плохо. Однако
has
не имеет смысла. Разъем переменного тока неисправен. Общая агрегация излишня, поскольку не имеет семантики.