Классы моделирования на основе дизайнов таблиц - PullRequest
2 голосов
/ 04 апреля 2009

Так обычно конструируют классы? Один класс = 1 Таблица. Как насчет таблиц, которые содержат внешний ключ для другой таблицы?

Предположим, у меня есть следующее:

PersonTable
---------------
person_id
name

PersonMapTable
---------------
map_id
type_id (fk)
person_id

PersonTypeTable
-------------------
type_id
description
parent_type_id

AddressTable
-------------------
address_id
address1
address2
city
state
zip

AddressMapTable
-----------
address_map_id
address_id
person_id

Будет ли хорошая практика состоять в создании класса для каждой таблицы? Если да, то каковы лучшие практики для загрузки / сохранения таких классов обратно в базу данных без orm? Простой пример кода был бы очень полезен

Ответы [ 8 ]

10 голосов
/ 04 апреля 2009

Я бы рекомендовал прочитать Шаблоны архитектуры корпоративных приложений Мартина Фаулера, в которых есть несколько шаблонов отображения между классами и таблицами.

3 голосов
/ 04 апреля 2009

Я не думаю, что один объект на таблицу обязательно является хорошим дизайном. Трудно дать один размер, подходящий для всех правил, но объекты могут быть богаче и более мелкозернистыми. База данных может быть денормализована по причинам, которые не относятся к объектам. В этом случае у вас будет больше объектов, чем таблиц.

Ваш случай будет включать отношения 1: 1 и 1: m:

public class Person
{
    // 1:m
    private List<your.namespace.Map> maps; 
}

public class Map
{
    // 1:1
    private your.namespace.Type;
}
2 голосов
/ 15 июля 2009

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

То, что я никогда не делаю (за исключением очень специфических запланированных случаев, когда зависимые данные ВСЕГДА необходимо извлекать с помощью объекта), устанавливает объект или набор объектов в качестве свойства другого объекта. Вместо этого эта сущность может быть обнаружена с помощью ее идентификатора, который будет либо свойством родительской сущности, либо обнаруживаемым через связанный репозиторий по отношению к родительской сущности.

В тех случаях, когда мне нужно связать дочернюю сущность или сущности другой сущности, я буду использовать вспомогательный класс "info", чтобы собрать все необходимые данные. Например, если у меня есть класс сущностей Widget, и у него есть коллекция дочерних Part объектов, я бы создал класс WidgetInfo, который бы содержал экземпляр Widget в качестве свойства и коллекцию Part объекты как другое свойство.

Таким образом, все классы сущностей остаются настолько легковесными, насколько они могут, и никогда не предполагают, что зависимые данные должны быть загружены. Кроме того, он поддерживает чистоту модели хранилища, не вынуждая вас запутаться в территории ORM, что обычно имеет место при создании коллекций дочерних объектов в классе сущностей. Если вы сделаете это без ORM, то у вас возникнет беспорядочная проблема, когда загружать дочерние элементы или нет, а когда предполагать, что дочерние элементы загружены или не были загружены.

1 голос
/ 15 июля 2009

Если ваши пользователи не являются клерками ввода данных, обычно считается, что лучше проектировать классы из вариантов использования / пользовательских историй. Даже если база данных уже существует.

Причина? Для пользователей слишком легко в конечном итоге предположить, что их задача - использовать программное обеспечение, а не ожидать, что оно поможет им выполнять свою работу.

Очевидно, что они должны пересекаться в какой-то момент. Я согласен, что книга Фаулера - отличное место для начала. Но я думаю, что он укрепит эту точку зрения.

Если вам нужна перспектива моделирования, которая поможет вам правильно определить классы и базу данных, рассмотрите моделирование ролей объектов.

1 голос
/ 04 апреля 2009

Я бы не сказал, что у меня всегда есть класс на стол, особенно когда у вас много-много отношений. Исходя из приведенной выше таблицы, у меня будет 2 класса ... Я не уверен, почему у вас есть и id, и id, и person_type_id, для меня это будет одно и то же, но вот классы.

Person
{
   public int Id { get; set; }

   public string Name { get; set; }

   public List<PersonType> { get; set; }
}

PersonType
{
   // I would discourage from using Type as property name as it is a keyword...
   public string [Type] { get; set; }
}
0 голосов
/ 21 июля 2009

Этот подход с точки зрения Базы данных к классу, скорее всего, приведет к тому, что вы довольно быстро начнете создавать множество кода. Тем не менее, хороший кусок этого кода, скорее всего, будет бесполезен или потребует серьезной мутации. Другими словами, вы, вероятно, создадите определенные классы, которые не соответствуют вашим дисплеям и рабочему процессу.

Во-первых, рассмотрите ваши приложения, потребности ваших пользователей, общий рабочий процесс и т. Д. На самом деле придумайте что-то, что выглядит работоспособным (то есть издевайтесь над дисплеями).

Сконцентрируйтесь на классах, которые вам нужны, чтобы использовать дисплеи и смоделируйте хранилище (дизайн БД) после этих потребностей. Скорее всего, у вас будет только несколько классов с прямыми столами, так как большинство ваших классов будут естественным образом обеспечивать решение для ваших дисплеев.

Удачи.

0 голосов
/ 17 июля 2009

Будет ли хорошая практика состоять из создать класс для каждой таблицы? Если Итак, каковы лучшие практики для загрузка / сохранение таких классов обратно в база данных без орма?

Вы используете ORM. Вы отображаете объекты в реляционные таблицы. Используете ли вы готовую библиотеку для этого или нет - ваш вызов. Если вы этого не сделаете, вы по существу будете реализовывать его самостоятельно, хотя, вероятно, безо всяких наворотов существующих ORM.

Два наиболее распространенных способа сделать это - шаблон ActiveRecord и шаблон Data Mapper. У каждого есть свои преимущества и недостатки.

С помощью шаблона ActiveRecord вы определяете классы, атрибуты которых определяют столбцы таблицы для вас. Каждый экземпляр этого класса соответствует строке в базе данных, и, создав (и сохранив) новый экземпляр, вы создадите новую строку в базе данных. Более подробная информация об этом доступна здесь: http://en.wikipedia.org/wiki/Active_record_pattern

В шаблоне Data Mapper вы определяете объекты таблицы для каждой таблицы и пишете функции отображения, которые присваивают столбцы таблицы существующим классам. SQLAlchemy использует этот шаблон по умолчанию (хотя существуют модули расширения типа ActiveRecord, которые адаптируют функциональность SQLAlchemy к другому интерфейсу. Краткое введение в этот шаблон можно найти в документации по SQLAlchemy здесь: http://www.sqlalchemy.org/docs/05/ormtutorial.html (прочитано с самого начала) к разделу, озаглавленному «Декларативное создание таблицы, класса и сопоставителя одновременно, но не включающему этот раздел» (в этом разделе описывается ActiveRecord с использованием SQLAlchemy).

Шаблон ActiveRecord проще в настройке и работе, и он дает вам классы, которые четко представляют вашу базу данных, что имеет преимущества с точки зрения читабельности. Дополнительным преимуществом является то, что декларативный характер классов ActiveRecord эффективно выступает в качестве четкой и понятной документации для вашей схемы базы данных.

Шаблон Data Mapper дает вам гораздо больше гибкости в том, как ваши данные отображаются в ваши классы, поэтому вы не привязаны к более или менее однозначному отношению между таблицами и классами. Он также отделяет ваш уровень персистентности от вашего бизнес-кода, что означает, что вы можете при необходимости заменить другие механизмы персистентности позже. Это также означает, что вы можете легче тестировать свои классы без необходимости создавать базу данных для их поддержки.

Для более подробного обсуждения конфигурации картографа в SQLAlchemy, посмотрите http://www.sqlalchemy.org/docs/05/mappers.html. Даже если вы не планируете использовать такую ​​библиотеку, как SQLAlchemy, документация должна помочь вам увидеть некоторые параметры, которые вы можете рассмотреть в отображении ваших классов в таблицы базы данных.

0 голосов
/ 17 июля 2009

Если вы планируете использовать объектно-реляционное сопоставление (ORM), это может повлиять на дизайн вашей таблицы. Например, Hibernate не любит стратегии смешанного отображения наследования в одном и том же дереве.

Поскольку вы специально указали, что не будете использовать ORM, вы можете следовать традиционным принципам проектирования баз данных. Обычно это означает, что нужно начинать с одной таблицы на класс, нормализовать ее до третьей нормальной формы ( читать о нормализации базы данных здесь ), а затем денормализовать для соответствия ограничениям производительности ( читать о денормализации здесь ).

Что касается вашего вопроса о том, как загружать и сохранять объекты без использования ORM, распространенной стратегией является использование объектов доступа к данным ( DAO s). Вот простой пример:

public interface ICustomerDao
{
  public void insert(Customer customer) throws CustomerDaoException;
  public void update(long id, Customer customer) throws CustomerDaoException;
  public void delete(long id) throws CustomerDaoException;
  public Customer[] findAll() throws CustomerDaoException;
  public Customer findByPrimaryKey(long id) throws CustomerDaoException;
  public Customer[] findByCompany(int companyId) throws CustomerDaoException;
}

Вы не указали, какой язык вы используете, но независимо от того, что вы можете найти , этот пример с использованием обобщений Java для DAO полезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...