DSL против вызовов методов: плюсы и минусы - PullRequest
2 голосов
/ 22 апреля 2009

У меня довольно специфический источник данных, с которым мне приходится работать (на самом деле интерфейс к бухгалтерскому приложению). Несмотря на то, что он достаточно мощный, мне нужно прыгнуть через множество обручей, чтобы получить из него нужные данные. Например, если я хочу получить содержимое таблицы и указать, какие столбцы она должна возвращать, я должен выполнить итерацию по коллекции .Columns и вызвать .SetVisible () для тех, которые мне нужны.

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

Первое решение, которое пришло мне в голову, было примерно таким:

DataTable result = DataSourceWrapper.StartQuery("TableName")
    .SetVisibleColumns("Col1", "Col2", "Col3")
    .SetCriteria("CriteriaName", "Param1Name", CriteriaParam1, "Param2Name", CriteriaParam2)
    .SetFilter("Col4 = ? AND Col5 = ?", FilterParam1, FilterParam2)
    .SetReportParams("Param1Name", ReportParam1, "Param2Name", ReportParam2)
    .Execute();

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

Обратите внимание, что SetFilter() имеет выражение для разбора. Это еще одна вещь, которую DataSource затрудняет - он может довольно хорошо обрабатывать выражения, но вы должны передавать их в виде дерева специальных объектов, которое снова довольно долго писать. В предыдущем вопросе я попросил помощи при разборе таких выражений. Текущий метод-обертка имеет синтаксический анализатор выражений homebrew, который может анализировать простые выражения, но я подумал о том, чтобы сделать их поддержку более полной.

В этом вопросе был предложен проект Irony . После проверки я решил, что это действительно подходит для этой необходимости. Но через некоторое время до меня дошло, что это было даже сильнее, чем это. Почему бы не сделать свой собственный язык запросов подходящим именно для этой задачи? Выше будет выглядеть так:

DataTable result = DataSourceWrapper.Query(@"
    SELECT Col1, Col2, Col3
    FROM TableName
    WITH CRITERIA CriteriaName(Param1Name={0}, Param2Name={1})
    WITH REPORTPARAMS (Param1Name={2}, Param2Name={3}
    WHERE Col4 = {4} AND Col5 = {5}",
    CriteriaParam1, CriteriaParam2,
    ReportParam1, ReportParam2,
    FilterParam1, FilterParam2
);

Но ... не будет ли это излишним? Каковы плюсы и минусы любого подхода? То, что я вижу:

Pro DSL:

  • запрос более краткий;

Pro Методы:

  • Больше поддержки IntelliSense;
  • Имена методов / имена параметров (и комментарии) уменьшают потребность в документации (DSL нужно будет тщательно документировать);
  • Может быть быстрее создать? Я никогда не создавал свой собственный DSL, поэтому я не знаю, сколько это работы. Ирония, кажется, снимает с моих плеч большую ношу, но сколько еще там осталось?

Добавлено: Для пояснения, оба подхода будут использоваться только кодерами. Внешние люди и бизнес-аналитики не будут его использовать.

Ответы [ 2 ]

2 голосов
/ 22 апреля 2009

Вы должны быть осторожны с тем, что вы называете DSL. См. Сообщение Мартина Фаулера о Блики на DSL . Ваш пример цепочки методов очень близок к внутренней DSL. Измените это немного, и это:

DataTable result = DataSourceWrapper.Query("TableName")
    .With(new Columns("Col1", "Col2", "Col3"))
    .Where(new AndCritera("CriteriaName",
        new Criterion("Param1Name", CriteriaParam1),
        new Criterion("Param2Name", CriteriaParam2))
    .Filter(
        new Filter("Col4").Equals(FilterParam1),
        new Filter("Col5").Equals(FilterParam2))
    .With(
        new ReportParam("Param1Name", ReportParam1),
        new ReportParam("Param2Name", ReportParam2));

При этом, это все еще очень много в сфере C #, и только программисты смогут писать эти запросы. Если ваши требования подталкивают вас к тому, чтобы сделать запросы доступными для непрограммистов, вы можете рассмотреть возможность создания внешнего DSL, как вы указали во втором примере.

0 голосов
/ 22 апреля 2009

Я бы выбрал подход DSL.

причины: 1 он ближе к экспертам в предметной области, исходя из личного опыта, БА похожи на что-то в формах DSL, он преодолевает коммуникационный барьер между деловыми людьми и разработчиками и значительно облегчает написание технических спецификаций. 2 с помощью такого инструмента, как Irony, ваш DSL будет четко определен и станет хорошим кандидатом для разработки через тестирование 3 реализация DSL требует некоторого начального обучения разработчиков (я использовал javacc, который даже менее дружественен, чем Irony), но как только вы постигаете идеи, это становится простым, и ваш код становится довольно общим, потому что вы загружаете логику в DSL.

...