Использует струну ре mixins для повторного использования кода антишаблон?

Для тех из Вас, кто не знаком со струной ре mixins, они - в основном время компиляции evals. Можно взять любую строку времени компиляции (ли литерал или сгенерированный шаблонным метапрограммированием или оценкой функции времени компиляции), и скомпилируйте его как код. При использовании литерала простой строки он в основном автоматизировал компилятором вставка копии.

Вы считали бы это антишаблоном для использования строки mixins литералов как средство простого повторного использования кода, где другие методы факторинга не делают довольно пригодный? С одной стороны, это в основном автоматизировало компилятором литеральная копия-и-вставка, означая, что когда-то смешанный в экземплярах не имеют ничего вообще, чтобы сделать друг с другом. Плохие Вещи произойдут (хотя во время компиляции, не во времени выполнения), если символ в строке, смешивающейся, столкнется с символом в смешанном в объеме. Это относительно не структурировано, в котором может, например, смешивая строку в середину функции, которая будет работать, если и только если переменные в объеме называют согласно определенной конвенции. Mixins может также объявить переменные, которые могут затем использовать внешние объемы, как они считают целесообразным.

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

7
задан dsimcha 21 July 2010 в 14:40
поделиться

3 ответа

Вся критика, которую вы высказали, верна.

Тем не менее, он по-прежнему лучше ручной копировальной пасты.

На самом деле, у меня в библиотеке инструментов работает нечто подобное - расширение таблицы строк. Пример кода из реализации динамического значения трассировщика пути:

  T to(T)() {
    static if (!is(T == Scope)) {
      T value;
      if (flatType == FlatType.ScopeValue) value = sr.value().to!(T);
    }
    const string Table = `
                 | bool          | int         | string               | float   | Scope
      -----------+---------------+-------------+----------------------+---------+----------
      Boolean    | b             | b           | b?q{true}p:q{false}p | ø       | ø
      Integer    | i != 0        | i           | Format(i)            | i       | ø
      String     | s == q{true}p | atoi(s)     | s                    | atof(s) | ø
      Float      | ø             | cast(int) f | Format(f)            | f       | ø
      ScopeRef   | !!sr          | ø           | (sr?sr.fqn:q{(null:r)}p) | ø   | sr
      ScopeValue | value         | value       | value                | value   | sr`;
    mixin(ctTableUnrollColMajor(Table,
      `static if (is(T == $COL))
        switch (flatType) {
          $BODY
          default: throw new Exception(Format("Invalid type: ", flatType));
        }
      else `,
      `case FlatType.$ROW:
        static if (q{$CELL}p == "ø")
          throw new Exception(q{Cannot convert $ROW to $COL: }p~to!(string)~q{! }p);
        else return $CELL;
      `
    ).litstring_expand() ~ `static assert(false, "Unsupported type: "~T.stringof); `);
  }

Я уверен, что легко увидеть, какой ужасный, избыточный беспорядок вложенных операторов if и case был бы без примесей строк - таким образом, все безобразие сосредоточено в внизу, и фактическое поведение функции легко прочитать с первого взгляда.

11
ответ дан 6 December 2019 в 14:00
поделиться

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

Проблема со строковыми миксинами состоит в том, что ими труднее управлять, чем написанным вручную кодом, в том смысле, что он физически не выложен в вашем источнике таким же образом с номерами строк, явно прослеживаемыми до ошибок, и это может быть сложнее отлаживать. Например, возьмем hello world со строковым миксином:

import std.stdio;

void main()
{
    mixin(hello());
}

string hello()
{
    return "
    writeln(\"hello world\");
";
}

Если бы мы удалили точку с запятой после Writeln () , то мы получили бы ошибку

d.d(7): found 'EOF' when expecting ';' following statement

. Миксин выполняется в строке 5. Строка 7 - пустая строка. Итак, номер строки здесь имеет ограниченную полезность. Теперь этот миксин достаточно короткий, чтобы мы могли поместить его в одну строку и заставить его сказать, что ошибка была в той же строке, что и миксин, но с более сложными миксинами, это, очевидно, не сработает. Таким образом, использование строкового миксина ухудшает вашу способность выяснить, где находится ошибка. Если код сгенерирован с использованием CTFE, тогда будет намного сложнее выяснить, как именно выглядит код, чтобы выяснить, что с ним не так. Это очень похоже на выяснение того, в какой код превращается макрос в стиле C, за исключением того, что это могло быть хуже, потому что они могли быть сгенерированы, а не прямой заменой.Однако они не заменяют, за исключением случаев, когда вы явно указываете им на это, поэтому они намного безопаснее, чем макросы в стиле C.

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

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

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

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

3
ответ дан 6 December 2019 в 14:00
поделиться

Строковый миксин похож на goto: его следует избегать везде, где это возможно, и использовать везде, где это необходимо.

1
ответ дан 6 December 2019 в 14:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: