Являются ли шаблон построителя и DSL эквивалентными или более выразительными?

Предположения

  • Я ограничусь этим внутренними DSL, но если вы можете дать мне вескую причину, почему я должен рассмотреть внешние DSL - я выслушаю это.
  • Если вы хотите ответить на это в Clojure или Scala и объяснить, почему я не прав — я тоже не против.

Я слышал, как друг сказал на днях:

Вы знаете, DSL и шаблон компоновщика — по сути это одно и то же.

Мне это показалось странным, поскольку я всегда предполагал, что DSL всегда будет более выразительным, чем шаблон строителя.

Мой вопрос: Являются ли шаблон построителя и DSL эквивалентными или более выразительными?

Итак, я посмотрел — вот шаблон User Builder в Java:

public class User {
    private final String firstName; // required
    private final String lastName; // required
    private final int age; // optional
    private final String phone; // optional
    private final String address; // optional

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public static class UserBuilder {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            return new User(this);
        }

    }
}

Вот используемый выше шаблон построителя:

public User getUser() {
    return new
        User.UserBuilder("John", "Doe")
        .age(30)
        .phone("1234567")
        .address("Fake address 1234")
        .build();
}

Вот использование внутреннего DSL в Java:

 Person person = constructor().withParameterTypes(String.class)
                              .in(Person.class)
                              .newInstance("Yoda");

 method("setName").withParameterTypes(String.class)
                  .in(person)
                  .invoke("Luke");

 field("name").ofType(String.class)
              .in(person)
              .set("Anakin"); 

person hawkeye    schedule 17.08.2014    source источник


Ответы (3)


Я не думаю, что можно даже сравнивать эти 2 разные концепции.

DSL — это язык для определенного домена, т. е. он имеет примитивы и правила композиции, которые позволяют вам говорить о конкретном домене.

Шаблон построителя — это шаблон, то есть шаблон решения, который вы применяете к проблеме, чтобы найти решение, а затем используете это решение. В вашем примере кода класс UserBuilder выходит из применения шаблона построителя, а сам по себе не является шаблоном построителя.

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

Вы можете реализовать DSL, используя шаблон построителя, ИЛИ вы также можете реализовать DSL, используя другие шаблоны. Шаблон — это шаблон решения для набора проблем, шаблон построителя — один из таких шаблонов для проблемы реализации DSL, но он не единственный.

person Ankur    schedule 17.08.2014
comment
Спасибо @Ankur - это действительно полезно. (Это то, о чем я тоже подумал). Могу ли я попросить пример того, где DSL более выразительна? - person hawkeye; 18.08.2014
comment
@hawkeye: Понятие выразительности очень трудно выразить ;). Допустим, вы создаете финансовое приложение и хотите, чтобы пользователь приложения создавал собственные правила, позволяющие настраивать приложение. В этом случае создание DSL для выражения пользователями своих правил приведет к большей выразительности, чем просьба к пользователю писать правила на родном языке приложения, то есть на языке, на котором приложение было написано. - person Ankur; 18.08.2014
comment
В вызове Arc (paulgraham.com/arcchallenge.html) Пол Грэм определяет выразительность как способность чтобы выразить наибольшее количество функций с наименьшим количеством инструкций — он использует «узлы»). Если мы используем «узлы», можем ли мы сказать, что DSL более выразительны, чем шаблон построителя, или они всегда будут одинаковыми? - person hawkeye; 18.08.2014
comment
DSL будет иметь набор инструкций, и, следовательно, вы можете вычислить его выразительность, используя подход PG. У шаблона построителя нет инструкций, скорее то, что вы создаете, используя шаблон построителя, будет иметь инструкции, и, следовательно, то, что вы создаете, используя шаблон построителя, имеет выразительность, а не сам шаблон построителя. - person Ankur; 18.08.2014

Конечно, DSL включают в себя множество вещей, которые не являются шаблоном построения. Так что нет, это не одно и то же.

Если вы рассматриваете каждый шаблон построителя как DSL (для области построения объектов определенного класса), то вы, очевидно, понимаете, что DSL в целом более выразительны, чем шаблоны построителя. Но a DSL не более выразителен, чем шаблон Builder; любой отдельный DSL не может делать все, что может делать шаблон Builder.

person Alexey Romanov    schedule 17.08.2014

Если бы ваш друг сказал

Вы знаете, что для создания простых старых объектов Java используется шаблон компоновщика разновидность ДСЛ.

... тогда я согласен.

Однако в Clojure вам не нужен класс построителя или DSL для краткого построения объекта.

  • POJO преобразуются в записи, которые имитируют (хешируют) карты. Существует несколько неуклюжий синтаксис для создания записи из карты.

Данный

(defrecord User [first-name last-name age phone address])

... тогда

(map->User {:first-name "John"
            :last-name "Doe"
            :address "Fake address 1234"})

... производит

{:first-name "John",
 :last-name "Doe",
 :age nil,
 :phone nil,
 :address "Fake address 1234"}

... это запись User, хотя она печатается как карта.

Итак, для этой цели Clojure убирает DS из DSL, и у вас остается только языковая конструкция.

person Thumbnail    schedule 18.08.2014