Вопрос

Краткая предыстория:Я программирую на PHP, у меня есть модель предметной области с отдельным уровнем доступа к данным (классы DAO), которые отвечают за выборку данных из базы данных и создание классов предметной области.

Допустим, у меня есть класс DAO, ответственный за создание Группа и Групповой список Объекты.Вы можете представить группы как компонент социальной сети;хотя на самом деле не имеет значения, что это такое для этого вопроса.

Мне нужно уметь просить ДАО сделать меня другим Групповой список объекты, основанные на различных критериях:

  • самые последние добавленные группы
  • самые популярные группы
  • группы, определенные администратором как "рекомендуемые"
  • группы, помеченные определенным тегом
  • группы, соответствующие определенному ключевому слову
  • группы внутри определенной категории
  • группы, созданные определенным человеком
  • группы , созданные в определенный день

Некоторые из них мне на самом деле не нужны прямо сейчас, но я могу себе представить, что они мне понадобятся до завершения проекта.Теперь я начал с приятного простого метода DAO: Создатель.Это сработало отлично.Вы можете думать о псевдокоде как:

find out how many groups
create SQL query to fetch group details
loop through results
{
   create group object
   add to group list object
}

По мере развития моего приложения я затем создал новый метод Создать список избранных.Это сработало отлично.Но на самом деле это было очень - очень похоже на Создатель, с немного другим запросом.Большая часть остальных ~ 150 строк кода были идентичны.

Итак... что мне следует делать со всеми немного отличающимися случаями, которые мне нужны? Большую часть времени я действительно просто хочу отфильтровать и отсортировать список на основе определенных критериев.Вопрос в следующем - должен ли я:

а) создавайте множество целенаправленных методов творчества, таких как:

  • Список создателей()
  • Создать список категорий ( categoryObject )
  • Создайте список пользователей ( UserObject )
  • Создать список тегов ( tag )
  • createPopularList () Создать популярный список ()

или

б) создайте один БОЛЬШОЙ метод, который может делать все:- Список создателей ( строка поиска, OrderBy, filterByCategoryObject=null, filterByUserObject=null )

Мне очень нравится идея (a), потому что мой интерфейс DAO проще и с меньшей вероятностью нуждается в изменении (например:добавление другого параметра, когда мне внезапно нужно передать в Дата для сравнения) Сложность возникает, когда у вас есть такие вещи, как ключевые слова для поиска, которые вы хотите иметь возможность комбинировать с другими параметрами;например:поиск по списку категорий, поиск по популярному списку, поиск по списку тегов и т.д...(a) - это своего рода то, с чего я начал.

У меня был флирт с рефакторингом в (b), но я вижу, что мой метод довольно быстро становится очень большим и очень сложным, много "if" и "select", чтобы иметь дело с различными случаями при построении SQL, и множество параметров, которые вводятся в метод.Но, по крайней мере, все это в одном месте.И вы можете комбинировать вещи;например:группы пользователей, помеченные бла-бла, совпадающие ключевые слова бла-бла.

Это было полезно?

Решение

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

private function _createList ( searchString, orderBy, ... )
{
    ...
}

public function createList()
{
    return $this->_createList('...', 'id');
}

public function createCategoryList()
{
    return $this->_createList('...', 'category_id');
}

Таким образом, если вашу функцию _createList потребуется изменить позже, вам нужно будет рефакторинговать только общедоступные методы в этом DAO, а не все классы, которые используют этот DAO.

Другие советы

Я не думаю, что это строго ситуация "или-или".Вариант a - это приятный удобный интерфейс для вашего DAO, поэтому я думаю, вам следует сохранить его.Мне вариант b действительно кажется логикой, специфичной для реализации.Поэтому, если БОЛЬШОЙ метод подходит для ваших целей, я бы посоветовал использовать его для выполнения фактической логики обработки при одновременном предоставлении интерфейса, как в варианте a.

Тем не менее, если БОЛЬШОЙ метод становится слишком запутанным и сложным, а повторное использование кода фактически увеличивает сложность вашего кода и снижает ремонтопригодность приложения, тогда вы можете провести рефакторинг, чтобы сохранить отдельные инструкции SQL для каждого метода интерфейса, но заставить вспомогательный метод выполнять общую логику анализа результатов.

В большой метод в варианте B почти гарантированно сокращает повторное использование кода и увеличивает сложность и время обслуживания.

Лично (и согласно Code Complete) методы должны делать что-то одно, и делать это хорошо, а не пытаться втиснуть в себя все подряд.Избегайте необходимости рефакторинга в будущем и делайте это с умом в первый раз.

Основы программирования:хорошей практикой является разбивать ваши коды на разделы или функции.

Я остановлюсь на варианте (а);Вам нужно будет поддерживать и отлаживать код.И когда у вас действительно обнаружится ошибка, вы будете очень рады, что разделили свой код на различные методы.

Кроме того, написание имени метода помогает вам понять, что вы делаете.

сравните это:

Вариант (а)

$obj->AddNewList( /* params */ );
$obj->UpdateList( /* params */ );

и это:

Вариант (b)

$obj->parse( /* first set of params */ );
$obj->parse( /* second set of params */ );

Это экономит время, поскольку люди читают слева направо.Вот почему имена функций и методов всегда находятся слева.

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

for(group in group) {
    cont = true
    for(f in functions) {
        if ! f(group) {cont = false; continue;}
    }
    if(cont) Continue
    add group to list
}

Это позволило бы вам изменять параметры фильтрации, не изменяя цикл, просто записывая или изменяя функцию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top