Шаблон DAO и принцип открытого-закрытого

Я видел и работал с большим количеством более старого кода DAO на основе JDBC, который обычно начинается с методов CRUD. Мой вопрос относится конкретно к методам поиска или «искателям». Обычно я обнаруживаю, что DAO начинаются с двух методов:

  • найти и вернуть ВСЕ
  • получить конкретный экземпляр на основе уникального идентификатора

Чаще всего этих двух средств поиска недостаточно. Обычно я вижу, что класс DAO неоднократно изменялся для добавления таких методов поиска, как следующие:

  • найти и вернуть ВСЕ, где {условие}

Что происходит, так это то, что добавляются дополнительные методы, когда необходимо поддерживать новые {условия} или существующие методы модифицируются для добавления новых параметров в качестве флагов для изменения запроса SQL внутри метода для поддержки дополнительных условий.

Это уродливый подход и нарушает принцип открытого-закрытого. Меня всегда раздражало то, что классы DAO постоянно изменяются всякий раз, когда необходимо поддерживать какое-то новое условие поиска. Исследование этого вопроса часто указывает мне на шаблон репозитория и инкапсуляцию условий для извлечения в виде Спецификации или объектов запроса, а затем их передачу в метод поиска. Но это кажется выполнимым только в том случае, если у вас есть коллекция всего набора данных в памяти или если вы используете какой-то ORM (я работаю со старым кодом JDBC)

Я рассмотрел решение, которое лениво загружает весь набор данных, которым DAO управляет как коллекцию в памяти, затем использует шаблон спецификации в качестве запросов для извлечения. Затем я реализую какой-то наблюдатель в коллекции, который просто обновляет базу данных при вызове методов создания, обновления или удаления. Но очевидно, что производительность и масштабируемость существенно страдают.

Есть мысли по этому поводу?


Спасибо за ответы. У меня есть одна мысль - каково ваше мнение об использовании шаблона Command / Policy для инкапсуляции запросов на доступ к данным? Каждая отдельная конкретная команда может представлять определенный вид доступа и может быть передана в Invoker. Я бы получил множество классов Concrete Command, но каждый из них будет ориентирован только на один вид доступа и должен быть очень тестируемым и изолированным.

    public abstract class Command{
       public  execute();
       public void setArguments(CommandArguments args){
          //store arguments  
       }
    }

    //map based structure for storing and returning arguments
    public class CommandArguments{
         public String getAsString(String key);
         public String getAsInt(String key);
         //... others
    }

    //In some business class...
    Command command = CommandFactory.create("SearchByName");
    CommandArguments args = new CommandArguments();
    args.setValue("name", name);
    // others
    command.setArguments(args);
    List list  = command.execute();

10
задан 18 February 2011 в 07:19
поделиться