Точный контроль перестановок GWT через *.gwt.xml

Мне нужно точно указать перестановки GWT и контролировать их вариации (комбинации значений свойств, поддерживаемых каждым), но мне трудно найти подробную спецификацию поведения.

В ходе экспериментов я узнал, что должен следить за созданием циклов set-property... when-property-is, даже если эти циклы «стабильны» — т.е. они не изменяют какую-либо часть цикла, просто «подтверждают» это. . Это ограничило мои возможности, поэтому я решил попробовать другой способ - определить совершенно новое свойство, (просто), например:

  <define-property name="precise.permutation" values="webkit,gecko,ie,unsupported"/>

... а затем что-то вроде:

  <set-property name="precise.permutation" value="webkit">
    <!-- ... custom conditions ... -->
  </set-property>
  <set-property name="precise.permutation" value="gecko">
    <!-- ... custom conditions ... -->
  </set-property>
  <set-property name="precise.permutation" value="ie">
    <!-- ... custom conditions ... -->
  </set>
  <set-property name="precise.permutation" value="unsupported">
    <!-- ... custom conditions ... -->
  </set-property>

... Затем я попытался ограничить это всем, кроме неподдерживаемого, который используется в качестве примера, но совершенно нелогичен, поскольку использует тот же тег set-property, что и выше:

  <set-property name="precise.permutation" value="webkit,gecko,ie" />

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

К сожалению, похоже, это не работает должным образом (пробовали с GWT 2.8 RC2). Несмотря на то, что «неподдерживаемая» перестановка не отображается (это желательно), комбинации свойств из нее снова появляются в других перестановках (что нежелательно).

Может ли кто-нибудь помочь мне найти авторитетную и полную документацию по этому вопросу или помочь мне разобраться, пожалуйста?

Спасибо!


person Learner    schedule 12.09.2016    source источник
comment
Можете ли вы обрисовать в общих чертах то, что вы после? Например, каковы пользовательские условия и каков ожидаемый результат (по сравнению с тем, что он есть)? Предполагая, что у вас есть условия "один ко многим" ИЛИ в каждом из них, тогда вы должны получать несколько перестановок на precise.permutation, поскольку вы не определили никакого свертывания (по крайней мере, вы не разделили ). Без конкретики мы не можем увидеть то, чего вы не понимаете.   -  person Colin Alworth    schedule 13.09.2016
comment
То есть, что именно вы пробовали, чего ожидали и что получили вместо этого? Исходя из этого, мы можем либо сказать вам, что вы не учли (и как это исправить или сформулировать по-другому), либо сообщить об обнаруженной вами ошибке (и, возможно, рассказать вам, как ее обойти).   -  person Colin Alworth    schedule 13.09.2016
comment
Моя проблема в том, что я не знаю, что именно делают конструкции *.gwt.xml, поскольку они нигде точно не определены. Таким образом, я не могу сформировать никаких ожиданий — я просто копаюсь в темноте. Попытка выяснить, как напрямую контролировать перестановки, а также уменьшить их внутреннюю сложность - мне вообще не нужна поддержка некоторых случаев, особенно. в некоторых перестановках..   -  person Learner    schedule 13.09.2016
comment
Короткая версия состоит в том, что перестановки состоят из перекрестного произведения всех значений всех свойств. Используя безусловный <set-property>, вы можете уменьшить значения, которые возможны глобально, а условные теги позволяют гарантировать определенное значение для этого свойства только в этом конкретном случае. Правила свертывания аналогичны безусловным правилам, поскольку они сокращают возможное количество значений. Это действительно так - правила могут показаться простыми (или могут быть кратко написаны), но правил больше нет, просто нужно буквально следовать этим правилам. Больше не нужен пример.   -  person Colin Alworth    schedule 13.09.2016
comment
Но как они оцениваются? Один раз, по порядку, или они каким-то образом основаны на событиях и могут запускаться в любое время и в любом порядке? Что на самом деле делает ‹set-property›, поскольку оно используется для фиксирования значения до единицы, ограничения возможных значений некоторыми, а также является условным? Например, могу ли я условно установить для него несколько значений?   -  person Learner    schedule 13.09.2016
comment
Они оцениваются все сразу, эффективно в начале компилятора, чтобы узнать, сколько работы еще предстоит сделать. Любые поставщики свойств (не обсуждавшиеся до сих пор) оцениваются во время выполнения в JS, чтобы решить, какую уже существующую перестановку использовать, в том числе какую мягкую перестановку в этой перестановке (но на самом деле это не применимо, поскольку на самом деле перестановок нет). Порядок имеет значение только в том случае, если более позднее свойство набора может переназначить более раннее, но в противном случае это просто умножение. SO — это не приложение для чата — либо опубликуйте конкретный пример и вопрос, либо перейдите в список рассылки или irc.   -  person Colin Alworth    schedule 13.09.2016
comment
Я просто еще немного поэкспериментировал и думаю, что теперь понял. Это немного беспорядок, поскольку имена неверны (перестановки не являются перестановками), а set-property фактически переопределяет набор значений и т. д. Попробуем ответить на это ниже.   -  person Learner    schedule 13.09.2016


Ответы (1)


Я до сих пор не нашел подробной документации, но я провел массу экспериментов и пришел к следующему выводу...

(Примечание: в моих примерах используются некоторые концепции Sencha GXT, с которыми я разрабатываю)

‹define-property› используется для определения свойства и его возможных значений, но не является последним словом в отношении того, какие значения будут фактически использоваться. Для каждого свойства в иерархии файлов *.gwt.xml должно быть ровно одно такое определение.

‹set-property› НЕ присваивает свойству значение A, а создает своего рода правило с НАБОРОМ ВОЗМОЖНЫХ значений для этого свойства (в идеале — подмножество того, что определено в <define-property›). Последнее объявление ‹set-property› для данного свойства выигрывает. Будь осторожен! Если вы используете ‹set-property› после ‹inherits› (наследование модуля), вы можете/будете переопределять любые унаследованные правила. Обратите внимание, что существуют условные правила и безусловные правила. Например,

<set-property name="gxt.user.agent" value="ie10, ie11, gecko1_9, safari5, chrome"/>

... будет безоговорочно утверждать, что при определении перестановок свойство 'gxt.user.agent' может иметь любое из перечисленных значений. Наоборот,

<set-property name="user.agent" value="safari">
  <any>
    <when-property-is name="gxt.user.agent" value="safari5" />
    <when-property-is name="gxt.user.agent" value="chrome" />
  </any>
</set-property>

Будет указано, что user.agent может быть «safari» только тогда, когда «gxt.user.agent» является либо «safari5», либо «chrome». Порядок кажется важным, поэтому вам нужно, чтобы правила для зависимых свойств объявлялись после правил для их зависимостей. Циклические зависимости не смогут выполнить компиляцию. Вы можете создать множество условных правил, если они не противоречат друг другу. Я пока не знаю, что будет, если они это сделают, но предполагаю, что победит последний объявленный.

Обратите внимание, что условные правила также могут указывать несколько возможных значений. Например (только иллюстрация, может не соответствовать вашим потребностям):

<!-- On desktops we do all browsers including IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9, ie11">
  <when-property-is name="gxt.device" value="desktop" />
</set-property>
<!-- ... but on tablets and phones we exclude IE -->
<set-property name="gxt.user.agent" value="safari5, chrome, gecko1_9">
  <any>
    <when-property-is name="gxt.device" value="tablet" />
    <when-property-is name="gxt.device" value="phone" />
  </any>
</set-property>

Вы можете использовать «любой» и «все» для создания сложных/составных критериев. Они могут быть вложены друг в друга.

Как это можно использовать для точного управления перестановками? Возможно, вам это не понадобится, но мне помогло начать с определения двух таких свойств:

<define-property name="custom.use.case" values="case1, case2, ..."/>
<property-provider name="helix.product.mode"><![CDATA[   
    var useCase = ...; // JavaScript code to determine the use case
    return useCase;
  ]]>
</property-provider>
<define-property name="custom.permutation" values="perm1, perm2, ..."/>

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

<!-- Case 1 restrictions -->
<set-property name="gxt.device" value="desktop">
  <when-property-is name="custom.use.case" value="case1" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9, ie11">
  <when-property-is name="custom.use.case" value="case1" />
</set-property>
...

<!-- Case 2 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
  <when-property-is name="custom.use.case" value="case2" />
</set-property>
<set-property name="gxt.user.agent" value="chrome, safari5, gecko1_9">
  <when-property-is name="custom.use.case" value="case2" />
</set-property>
...

<!-- Case 3 restrictions -->
<set-property name="gxt.device" value="tablet, phone">
  <when-property-is name="custom.use.case" value="case3" />
</set-property>
<set-property name="gxt.user.agent" value="safari5">
  <when-property-is name="custom.use.case" value="case3" />
</set-property>
...

etc.

Следующее, что нужно сделать, это свернуть все свойства, кроме для custom.permutation, потому что мы хотим, чтобы custom.permutation управлял перестановками:

  <collapse-property name="custom.use.case" values="*" />  
  <collapse-property name="gxt.device" values="*" />
  <collapse-property name="gxt.user.agent" values="*" />
  <collapse-property name="user.agent" values="*" />
  <collapse-property name="user.agent.os" values="*" />

Этот подход позволяет чрезвычайно точно контролировать «перестановки» и их внутреннюю сложность, «мягкие перестановки», как некоторые их называют. Для каждого возможного значения свойства custom.permutation будет ровно одна перестановка. Каждая перестановка будет иметь только необходимые «мягкие перестановки», если вы хорошо справитесь с настройкой приведенных выше правил.

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

Если вы используете GXT, начиная с версии 4, вы заметите, что он добавляет свойство gxt.device, имеющее такие значения, как рабочий стол, планшет и телефон. Это привело к увеличению времени компиляции примерно в 6-7 раз после обновления до GXT 4, потому что наши перестановки вышли из-под контроля. Некоторые из них в буквальном смысле были созданы для Internet Explorer, работающего на планшете с Mac OS. Вы можете оценить, какой пустой тратой времени являются перестановки для несуществующих вариантов использования. Реализовав вышеизложенное, мы смогли сократить время компиляции GWT примерно до половины исходного времени или примерно в 10-12 раз быстрее, чем сразу после обновления GXT 4.

person Learner    schedule 13.09.2016