2010-02-19 3 views
3

У меня часто бывают те же проблемы, когда мне приходится создавать свой класс для веб-приложения. Требования: - поддерживаемый (например, без копирования-вставки) - слои полностью разделены (бизнес-уровень не должен знать, какой метод используется для уровня данных) - высокая производительность: не загружать бесполезные данные ,Основной вопрос о ООП

Во-первых у меня есть таблица со всеми своими клиентами и их адреса: Код:

Customer 
--Id 
--Name 
--Address 
----City 
----ZC 
----Street 

Теперь я хочу таблицу (в другой странице) со всеми своими клиентами и книги, которые они купили, у меня есть несколько возможностей:

1/создать новый класс:

Код:

CustomerWithBooks 
--Id 
--Name 
--Books[] 
----ID 
----name 

PRO: Я загружаю только полезные данные CONS: Я создаю свой класс после моего пользовательского интерфейса, и есть копия.

2/Я добавляю Книги [] в первый класс. PRO: Все находится в одном классе, его можно обслуживать CONS: Я загружаю адрес впустую. Если я не загружаю адрес, я могу: ленивая загрузка, но мне это действительно не нравится, или когда я использую свой класс, я должен знать, какой метод моего DAL я назвал, и мне это не нравится.

3/Я использую наследование: Код:

ClientBase 
--ID 
--Name 

ClientWithBooks : ClientBase 
--Books[] 

ClientWithAdress : ClientBase 
--Address 

PRO: действительно maintenable, и я не загружать данные ничего не СВОД: Что делать, если в одном интерфейсе я хочу показать книги и адрес?

4/?? Я надеюсь, что есть идеальное решение

ответ

3

Вариант 1 близок к хорошему, если я правильно его понимаю. Клиент и книга - две совершенно разные вещи. Вы хотите, чтобы эти данные/функциональность были отделены друг от друга и не должны наследоваться из какого-либо общего базового класса (который вы сделали).

Как «Кон» вы говорите: Я создаю свой класс после моего интерфейса, и есть копия-паста.

  • A. Если вы издеваться некоторый интерфейс, чтобы помочь прояснить требования, прежде чем осесть на ваш дизайн и код до классов, это хорошо, не плохо.
  • B. Хорошее расположение объектов домена помогает устранить копирование/вставку, а не вызвать ее. Если у вас есть какой-то кажущийся повторяющийся код в ваших хорошо организованных классах (часто код доступа к данным), это не волнует. Вы можете обращаться с хорошим уровнем доступа к данным/инструментом, хорошими ресурсами совместного ведения журналов и т. Д. Повторяющийся код в ваших классах означает, что у вас есть больше возможностей для улучшения дизайна, не, что наличие отдельных классов для всех реалий вашего домена плохое ,

На странице, где вам нужно иметь дело с клиентами и книгами, вы будете использовать клиенту объектов и книгу объектов, и, вероятно, книги объекта коллекции. И в зависимости от того, как настроена ваша db/object-model, вы можете иметь дело с другими объектами, чтобы получить клиента формы для книг, которые они купили. Например, клиенты, вероятно, покупают 1 или более книг одновременно, и они привязаны к объекту . Заказ, который имеет ссылку на клиента. Таким образом, вы, вероятно, перейти от

  1. Заказчика к
  2. Заказов коллекции, содержащего все, что клиенты заказы к индивидуальному
  3. ордену объектов и оттуда в соответствующем
  4. Книги коллекция, содержащая все
  5. B ook объекты, относящиеся к этому объекту Order.

Ни один из них не должен наследовать друг от друга. Теперь, скажем, получить все книги, купленные клиентом, - это то, что вы делаете много, и вы хотите оптимизировать это. Затем вы хотите иметь коллекцию книг непосредственно у Клиента, которая дает вам это, хотя sql-запросы, которые вы используете для получения этих книг, все еще проходят через Orders в db. Вы должны начать с вашей объектной модели (и таблиц за кулисами) , отражающий реальность точно. Даже если это дает вам, казалось бы, много классов, это более простой в конце. Возможно, вам удастся наследовать, возможно, нет.

1

Я бы избегал 2 и 3, потому что он блокирует вас в ограничительной иерархии, которая не отвечает вашим потребностям. Как вы указываете, может быть любая комбинация вещей, которые вы хотите, таких как клиенты и их книги, и, возможно, их адрес и, возможно, их история заказов. Или, может быть, вам понадобится книга с ее списком клиентов. Поскольку ваша основная бизнес-информация не является иерархической, вы должны стараться избегать ненужной иерархической модели объекта. В противном случае вы будете создавать ограничения, которые вызывают много головных болей позже, потому что теперь вы не можете думать обо всех сценариях.

Я думаю, что вы на правильном пути с 1. Я бы сказал, чтобы создать базовые классы для клиентов и книг, а затем создать класс ассоциации CustomerBook, который содержит экземпляр как клиента, так и книги. Затем вы можете беспокоиться о том, как загружать данные в этот список для данного scenerio.

+0

Звучит неплохо. Если я хорошо понимаю, вы говорите, что я должен избегать композиции, если нет иерархии, вместо этого я должен сделать некоторый «класс отношений». –

0

Я бы указал адрес Customer и имел отдельную коллекцию книг.

Bookshelf 
--Books[] 

Таким образом достигается Customer не имеет, но может быть, один или несколько книг, связанных с ним. Пример PHP-код, следующий:

class BookshelfFactory { 
    public static function getBookshelf(Customer $customer) { 
    // perform some fetching here 
    return $bookshelf; 
    } 
} 
0

Вы вроде проектирования назад от ООА & D точки зрения. Нормально использовать ориентированный на данные дизайн на уровне персистентности (обычно в реляционной базе данных).Но в OOA & D более нормально думать о сообщениях, которые объект будет отправлять и получать (вы моделируете методы объекта, а не его члены). Я бы подумал об этом так:

Customer 
+getBooks():List<Book> 
+getAddress():Address 
+0

Мне это не нравится: вы называете свой DAL внутри своего бизнес-класса. Они должны игнорировать друг друга. –

+0

@remi bourgarel - Я бы не стал говорить, как класс Customer выполняет эти методы в это время; просто позволяя получить адрес клиента и список книг через самого клиента. – shadit

+0

@remi bourgarel, довольно часто (и хорошо) использовать DAL в бизнес-классах. Следовательно, «3-ярус», с каждым уровнем выше другого, используя один ниже. В моем текущем решении я это делаю (хотя я ввожу свой инструмент DAL для модульного тестирования и других целей). Возможность также создавать экземпляры объектов с данными также хороша, так что (например) для вашей коллекции книг потребуется только один вызов db для создания экземпляра 20 объектов книги. –

0

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

У вас могут быть высокоэффективные запросы с помощью JOINS, которые возвращают вам клиентов, а также их книги.

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

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

+0

Проблема с JOINS заключается в том, что у меня будет 1 запрос, чтобы получить клиент + книги и 1 запрос на получение адреса клиента +. Поэтому я скопирую вставку большого количества кода sql (поля, фильтр и т. Д.) –

+0

Не обязательно, если вы видите, что будете дублировать, вы просто рефакторируете и храните его в строке const соответствующего класса или абстракции для повторного использования , Всегда продолжайте рефакторинг ... –

+0

@remi bourgarel, имея несколько запросов sql, упоминает одну и ту же таблицу, абсолютно и это неизбежно. Это все о балансе, а один из балансов - между * эффективностью * и * инкапсулированием *. Инкапсуляция - это всего лишь инструмент для достижения простоты. ** простая ** и эффективная система обычно будет включать похожие sql-запросы в нескольких местах. Прекрасно. Как говорит Вим, иногда вы можете/должны удалить часть этого дублирования, что, конечно, хорошо, но, как правило, невозможно удалить все это, и это нормально. –

Смежные вопросы