0. kalyaka 582 09.06.18 23:16 Сейчас в теме

Управление состоянием формы через конечный автомат

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

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо развёрнутое
Свернуть все
1. bulpi 174 19.06.18 12:10 Сейчас в теме
"Но кого особо волнует объём кода в современном мире ПО?"
Меня волнует, меня. Когда мне нужно что-то переделывать в конфигурациях, написанных такими умниками.
Грибоедов , "Горе от ума". Мне всегда вспоминается это гениальное название, когда я читаю подобные вещи.
mbalyukin; Solovyeff; oninfostart; Yakud3a; Soloist; корум; rpgshnik; grumagargler; SlavaKron; +9 Ответить
9. kalyaka 582 19.06.18 18:42 Сейчас в теме
(1) Извините, ответ получился в отдельный пост ниже
2. kalyaka 582 19.06.18 12:31 Сейчас в теме
Не зная системы понять ее по фрагментам может быть очень тяжело и наоборот - знание системы позволяет реализовывать качественные системы с более сложным поведением.

Если в качестве аналогии взять технологию Конвертации, то при описании правил на выходе тоже генерируется код. И наверняка, если писать код обмена без правил его объем будет меньше, однако это ж не говорит в пользу такого подхода?
3. Идальго 131 19.06.18 14:00 Сейчас в теме
Думаю, что вот излишне формы лучше не усложнять, таких вот обработчиков состояний стараться не городить шибко много. Муторно поддерживать всё это, особенно когда разные люди и каждый на свой лад (и в разных местах) пишут такие штуки. А в целом норм написано вроде.
Solovyeff; Gang031; rpgshnik; bulpi; CSiER; +5 Ответить
8. kalyaka 582 19.06.18 18:39 Сейчас в теме
(3) Согласен, поэтому планирую модуль формы генерировать на основе декларативного описания по аналогии получения модуля обмена из Конвертации данных
4. unichkin 1262 19.06.18 17:34 Сейчас в теме
Модули форм не оформлены по стандарту. Нет областей основных разделов. Кроме того, для параметризованной передачи используется ЭтаФорма, а не ЭтотОбъект. Далее в внеконтекстных методах формы - используется параметр "ЭтаФорма". Понятно что эта переменная вне контекста не является именно свойством, а это переданный параметр. Но все-равно, кажется что нужно выделить этот нюанс, который при разработке может создать лишнюю "кашу в голове" - я в таких случаях именую параметр просто "Форма". Пример:
&НаКлиентеНаСервереБезКонтекста
Функция ПроцентСкидки(Форма)
    Если Форма.Объект.Статус = ПредопределенноеЗначение(...)    
    //...

КонецФункции

// Вызов
Если ПроцентСкидки(ЭтотОбъект) > 0 Тогда
//...

Показать


Подобный пример можно увидеть на ИТС https://its.1c.ru/db/v8std/content/2149184279/hdoc
21. kalyaka 582 20.06.18 20:40 Сейчас в теме
(4) Согласен. По началу я так и писал. Однако при разработке системы удобнее использовать имя ЭтаФорма, т.к. В этом случае работает контекстная подсказка. После разработки глаз «замылился» и мне уже казалось вполне обычно использование ЭтаФорма как параметр.

Про оформление областей разделов узнал для себя новое. Сами разделы то появились относительно недавно.

В приведенных модулях форм демо-обработок нет смысла выделять разделы, т.к. Сами обработки - пустышки, назначение которых пояснить работу механизма.
24. unichkin 1262 21.06.18 00:04 Сейчас в теме
(21)
В приведенных модулях форм демо-обработок нет смысла выделять разделы, т.к. Сами обработки - пустышки, назначение которых пояснить работу механизма.

Коль выкладывается встраиваемая подсистема, с примерами - я считаю что "нет смысла" так рассуждать :) Это т.н. хороший тон. А то выходит - вот это я оформлю, а вот здесь - можно и забить.
Беда в том, что те кто только начинает постигать 1С - учась и смотря на такие примеры вообще опускают оформление в 99% случаев. А вместе с ним - и прочие стандарты ИТС. Дьявол в деталях..
pavlov_dv; +1 Ответить
27. kalyaka 582 21.06.18 23:34 Сейчас в теме
(24) Тут я сторонник рационального перфекционизма. Что касается непосредственно подсистемы должно быть на самом высоком уровне, т.к. это основа.

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

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

Идея должна либо умереть, либо превратиться в практику. Это как с новым изобретением. Вначале собираются устройство образно на "соплях". Демонстрируют и убеждают вложиться. После, как говорят, идея должна преодолеть пустыню смерти.
5. unichkin 1262 19.06.18 17:54 Сейчас в теме
Общие модули подсистемы также не оформлены, нарушены рекомендации итс по именованию методов https://its.1c.ru/db/v8std#content:2149184296:hdoc. Присутствуют избыточные судя по коду модули "ОбщийВызовСервера", "ОбщийКлиентСервер" - также не оформленные. Флаги серверного модуля "УправлениеФормой" - выставлены некорректно с т.з. стандарта https://its.1c.ru/db/v8std#content:2149184118:hdoc.
Идея хорошая, но я б себе это внедрять не стал. Либо после доработки. А там, вероятно родился иной архитектурный концепт.
22. kalyaka 582 20.06.18 20:48 Сейчас в теме
(5) про общие модули «ОбщийВызовСервера», «ОбщийКлиентСервер». Не знал, что они вообще кого то привлекут внимание. Дело в том, что эти модули я использую во многих разработках и не только я.

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

А вот про «УправлениеФормой» -Согласен, для серверного модуля нужно ставить Внешнее соединение и Клиент (обычное приложение), это я не доглядел. Спасибо :)
25. unichkin 1262 21.06.18 00:06 Сейчас в теме
(22)
Конкретно в этом решении из модуля используется две простые функции, одна в подсистеме и одна в демо-обработке, т.е. Использование их вообще не принципиально.

Получается, я при встраивании должен об этом думать?.. И где-же универсальность?
28. kalyaka 582 21.06.18 23:36 Сейчас в теме
(25) Продукт еще не полный, пока просто зацените идею :)
6. grumagargler 662 19.06.18 18:02 Сейчас в теме
подскажите пожалуйста, а если у поля свой обработчик ПриИзменении, что в этом случае предлагает подход?
YaroslavHolovatiy; +1 Ответить
7. kalyaka 582 19.06.18 18:24 Сейчас в теме
(6) в этом случае Вы сами ответственны за вызов процедуры УправлениеФормой, подсистема не перекрывает уже установленные обработчики.

Думаю это нормально: система обеспечивает обработчик по умолчанию, а если поведение по умолчанию Вам не подходит, то Вы пишите свой обработчик.
10. grumagargler 662 19.06.18 18:47 Сейчас в теме
(7) ясно. Выскажусь как разработчик похожего механизма: вы уделили большое внимание теории, оставив без должного внимания практику. В подавляющем большинстве случаев, видимость/доступность связана не только с действием пользователя, но и программной обработкой и события, напрямую с этим не связанным, например при перечтении данных формы; наличие вызова обновления из таких обработчиков - делает несостоятельной всю описываемую теорию, потому что она ложится на плечи программиста. Значительно проще сериализовать неподдерживаемое условное оформление формы (включая условия СКД) в реквизит формы, дав программисту в руки безконтекстную клиент/серверную функцию обновления по зависимому реквизиту или обновляемому контролу.
YaroslavHolovatiy; +1 Ответить
11. Adept 19.06.18 19:11 Сейчас в теме
(10) Может не внимательно смотрел, вы выкладывали этот механизм в свободный доступ? Хотелось бы посмотреть ...
12. grumagargler 662 19.06.18 19:23 Сейчас в теме
(11) Реализация выполнена в рамках решения Тестер. Но, Александр, это решение внутри на английском, по собственным стандартам, и вероятно будет совсем вам не интересно. На всякий случай: за это там отвечают два модуля: Appearance и AppearanceSrv, а пример использования см. в основной форме справочника Scenarios (https://github.com/grumagargler/tester)
13. grumagargler 662 19.06.18 19:40 Сейчас в теме
(11) (непонятно почему пропало измененное сообщение) Реализация выполнена в рамках решения Тестер. Но, Александр, это решение внутри на английском, по собственным стандартам, и вероятно будет совсем вам не интересно. На всякий случай: за это там отвечают два модуля: Appearance и AppearanceSrv, а пример использования см. в основной форме справочника Scenarios (https://github.com/grumagargler/tester)
14. kalyaka 582 19.06.18 20:33 Сейчас в теме
(10) Теория рождается из обобщения практики. Другое дело, что вначале модель может быть слишком идеальной.
Следующей своей задачей вижу проверить теорию на практике и при необходимости доработать реализацию.

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

Если же имеется в виду работа с моделью в терминологии MVC, то для этого у меня есть другое решение.

В Вашем примере при перечтении данных формы я так понимаю нужно полностью пересчитать её состояние - это достигается вызовом процедуры УправлениеФормой без указания источника изменений. В этом случае читается, что изменились все параметры состояния. И тот факт, что система сама не может «догадаться» пересчитаться при внешних событиях (требуется программировать эти случаи) делает несостоятельным предложенное решение?

По поводу использования условного оформления идея интересная. Вы писали о разработке похожего механизма, было бы интересно ознакомиться.
YaroslavHolovatiy; +1 Ответить
15. grumagargler 662 19.06.18 21:21 Сейчас в теме
(14)
делает несостоятельным предложенное решение?

Спасибо за содержательный комментарий. Но я смею утверждать, что да, подход не выдерживает испытание практикой. Понимаете, если бы цепочка связанного оформления полей запускалась полностью декларативно, тогда нет вопросов, и в вашем примере, это почти так и происходит через вентиль ОбработчикПриИзменении (). Но, повторю, мне очень редко встречаются случаи, когда изменяемый реквизит только то и делает, что влияет на оформление формы. Более частыми, идут задачи такого плана: установили галку -> ушли на сервер заполнять таблицу -> сделали там её (на сервере) видимой -> вернулись на клиент. Другой пример: изменили реквизит Договор -> получили из него валюту -> увидели что она не локальная -> сделали доступной состав реквизитов с курсом (не говорим про ФО). Оба случая, во-первых, желают изменить (в частности видимость) оформление на сервере, чтобы с клиента опять сервер уже платформа не вызвала (для видимости это произойдет почти наверяка), во-вторых - будут требовать от программиста как минимум одну строку кода для запуска обновления связанных полей, что в данном случае - фактически делает из декларативного подхода, просто копилку настроек оформления полей. И вот в этой связи, я предлагаю чуть другой подход - собрать неподдерживаемое условное оформление и применять его по необходимости. Решение не претендует на элегантность и новизну, но с практической точки зрения очень удобно (вопросы сравнения конфигураций с проблемой УО вынесем за скобки, потому тут тоже есть о чем подискутировать).
Подход можно посмотреть в конфигурации Тестер (https://github.com/grumagargler/tester), там два модуля Appearance и AppearanceSrv, применение см. в форме справочника Scenarios, написано по своим стандартам, на английском, поэтому вероятно, будет интересен с чисто теоретической точки зрения.
YaroslavHolovatiy; +1 Ответить
23. kalyaka 582 20.06.18 23:26 Сейчас в теме
(15)
очень редко встречаются случаи, когда изменяемый реквизит только то и делает, что влияет на оформление формы. Более частыми, идут задачи такого плана: установили галку -> ушли на сервер заполнять таблицу -> сделали там её (на сервере) видимой -> вернулись на клиент

Здесь я предлагаю четко различать часть связанную с оформлением формы и часть модели, когда происходит изменение данных. Эти части связаны в одну сторону: состояние формы отражает данные модели. Модель первична.

Вначале обсчитывается модель (заполняются таблицы, рассчитываются курсы и т.д.). Затем рассчитываются параметры состояния формы, некоторые из которых (базовые) опираются непосредственно на данные. От базовых рассчитываются зависимые. Получаем список измененных параметров состояния, от которых в свою очередь зависят настройки элементов формы.

Обсчёт модели происходит по зависимостям реквизитов. Более подробно механизм я описал в своей статье про MVC.

Так вот, если эти две модели соединить (MVC и состояние формы), то в модуле формы ничего программировать вообще не нужно будет - весь код будет располагаться для модели в модуле Менеджера (например), а для состояния в функциях состояния.

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

во-вторых - будут требовать от программиста как минимум одну строку кода для запуска обновления связанных полей
Не потребует, если использовать две модели (MVC+состояние формы).

собрать неподдерживаемое условное оформление и применять его по необходимости
Посмотрел, на английском без единого комментария выглядит как в лесу зимой: все кругом белым бело и голые деревья -процедуры :) Да, можно подумать о таком подходе, правда, здесь контекстный вызов сервера без альтернатив. И нужно придумать как обсчитывать условия по изменениям. И возможно описаний условий будет больше, чем в моем варианте. Одно дело задать все условия по разным свойствам оформления, другое - обыграть все это в коде функции состояния.
26. grumagargler 662 21.06.18 00:41 Сейчас в теме
(23)
Обсчёт модели происходит по зависимостям реквизитов. Более подробно механизм я описал в своей статье про MVC.

Так вот, если эти две модели соединить (MVC и состояние формы), то в модуле формы ничего программировать вообще не нужно будет - весь код будет располагаться для модели в модуле Менеджера (например), а для состояния в функциях состояния.

У меня был неудачный опыт описания логики работы формы декларативно. Я думаю, что единственное, на что годен декларативный подход - оформление. То, что в модуле ничего программировать не нужно, не нахожу преимуществом. Почему? Потому что непонятно, что, когда и где происходит, это сложно отлаживать (нужно помнить где ставить точки останова и делать их условными), добавим сюда отсутствие рефакторинга, который будет невыполним в строковых полях зависимости, невозможность анализа конфигурации (поиск неиспользованных обработчиков), сложности обработки равносвязных полей (например, ввод документа из журнала, где фильтром был склад и организацию нужно заполнить по его владельцу).
Не согласен с мнением "...заморачиваться с работой без контекста формы..."). Вы решаете проблему зависимостей, принося в жертву совсем немаловажные вещи. А такая ли уж большая эта проблема зависимостей? Я считаю, что небольшая. Даже обыденная вещь, как организация правильного клиент-серверного взаимодействия - это не вопрос оптимизации, это вопрос правильной архитектуры вашего кода в рамках проектных решений платформы (вопросы безопасности, отзывчивости интерфейса, а порой и обхода проблем с вызовом сервера самой платформы).

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

Посмотрел, на английском без единого комментария выглядит как в лесу зимой

Понимаю вас, но так в команде все пишут, это одно из требований.
29. kalyaka 582 22.06.18 00:13 Сейчас в теме
(26)
Потому что непонятно, что, когда и где происходит, это сложно отлаживать ...отсутствие рефакторинга, который будет невыполним в строковых полях зависимости

Тут я приведу аналогию с конвертаций данных. Если Вы владеете этой технологией, то представляете как можно отлаживать правила. Здесь я вижу аналогичный подход. Однако здесь, в отличии от Конвертации, используется несколько принципиально иной подход к обработчикам. Все обработчики вызываются как процедуры или функции, поэтому проблем с отладкой быть не должно, ведь весь код реально присутствует в модуле (впрочем сейчас принято весь код выкладывать в модуль), а не в текстовом аргументе процедуры Выполнить.

невозможность анализа конфигурации

Здесь соглашусь. Опять же сошлюсь на опыт с конвертацией данных. Для анализа нужно использовать отдельное решение типа конфигурации Конвертация.

большая эта проблема зависимостей?
Проблему я в свое время подробно исследовал в своих статьях (Шаблон MVC, Программирование интерфейсов)

было бы очень здорово, если бы вы накидали рабочий пример в типовой конфигурации

Такой пример я планирую выложить. Идея с типовой интересная. Действительно, зачем придумывать пример, если можно взять типовое решение и переложить его в новой подсистеме работы интерфейса. Возможно это будет очень затратно, но очень эффектно :)
36. kalyaka 582 23.03.20 10:39 Сейчас в теме
37. grumagargler 662 23.03.20 15:55 Сейчас в теме
(36) Да, я читал, спасибо! Мы пошли чуть иным путем, реализовали свой небольшой язык уо (см.вложение)
Прикрепленные файлы:
ca.pdf
16. rpgshnik 2187 20.06.18 01:45 Сейчас в теме
Листинги не кликабельны, на мониторах 15" ни чего не видно.
У инфостарта при создание публикации есть "вставить сниппет" лучше бы его использовали.
18. kalyaka 582 20.06.18 09:26 Сейчас в теме
(16) в статье я сознательно отказался от сниппетов в пользу картинок для повышения иллюстративности кода в окружении.
С картинками однако есть проблема - они по разному отображаются при разном разрешении. На том же ipad или mac картинки выглядят четко. Попробуйте увеличить масштаб в браузере (у меня под windows при масштабе 175% исчезают боковые поля инфостарта и картинки показываются в разрешении близком к исходному) или же используйте просмотр картинок в исходном разрешении (нужно нажать (+) на картинке в заголовке статьи и там можно листать все иллюстрации)
С другой стороны весь приведенный код доступен в обработках и конфигурации, приложеных к статье.
YaroslavHolovatiy; +1 1 Ответить
17. evgen7938 7 20.06.18 04:40 Сейчас в теме
Конфигурацию не качал, но по тому, как преподносится материал, видно сразу, что решение очень хорошо спроектировано и учтены очень многие детали.
Лично я хочу выразить признание и уважение.
Вы проделали очень большую работу и уделили много внимания мелочам.
pbabincev; raider-rec@ya.ru; Evil Beaver; +3 Ответить
19. kalyaka 582 20.06.18 09:27 Сейчас в теме
20. Evil Beaver 6752 20.06.18 18:06 Сейчас в теме
Плюсую не читая. Сложные формы ВСЕГДА делаются на конечных автоматах. Радостно, что это приезжает в мир 1С.
harmit; tsukanov; +2 Ответить
30. WalterMort 318 14.08.18 10:31 Сейчас в теме
Для меня загадка, почему задача управления состоянием формы так будоражит умы 1С-ников. Не встречал решений в которых формы поголовно ведут себя вопреки заложенной логике. Не встречал программистов, настолько плохих, чтобы у них были трудности с управлением видимостью/доступностью. А вот что часто встречал - уродливые архитектуру и интерфейсы с кучей кнопок, полей появляющихся и исчезающих по ходу работы с формой, вечные вопросы пользователю и ещё портянки кода на обслуживание всего этого. Вот сделать форму понятной и лаконичной (а вместе с ней и код формы понятным и лаконичным) - автомат не поможет.
31. kalyaka 582 14.08.18 14:28 Сейчас в теме
(30)
Не встречал решений в которых формы поголовно ведут себя вопреки заложенной логике... А вот что часто встречал - уродливые архитектуру и интерфейсы с кучей кнопок, полей появляющихся и исчезающих по ходу работы с формой
Если я правильно Вас понял, хоть архитектура и уродлива, но работает верно: нужные кнопки появляются где надо и когда надо? Т.е. Вопрос только в том, что слишком запутанные алгоритмы обслуживают эти формы, их сложно сопровождать, но можно.
В принципе это наверно нормально, что сложные формы порождают сложные алгоритмы и архитектуру?
Так вот, идея автомата заключается в том, что вместо программирования поведения формы акцент делается на программирование состояний формы. При этом переход из одного состояния в следующее берет на себя подсистема, а программирование заключается в выделении таких состояний и описании их.
Что решает подсистема при этом: подсистема рассчитывает оптимальный переход и гарантирует соответствие конечного состояния заданному. Алгоритмически система берет на себя задачу: рассчитать измененные параметры состояния, найти зависимые параметры и рассчитать их, найти элементы формы или объединения элементов, состояния которых изменились, пересчитать их состояния и отобразить их на форме.
Почему это должно быть проще и надежнее? Потому что есть 100500 способов перехода из одного состояния в другое и есть только одно описание этого состояния. Подсистема берет на себя 1-ое, а второе должно быть согласно требованиям.
32. WalterMort 318 14.08.18 16:44 Сейчас в теме
(31) Я скорее о том, что сложные формы в принципе зло и их быть не должно. Надо в первую очередь думать как сделать сложную форму проще, а не превращать код сложной формы в нечитаемый манускрипт.

А про кучу состояний проблема надуманная, никто не будет описывать кубик Рубика его возможными состояниями. А вот принцип "разделяй и властвуй" - пожалуйста. Вот процедуры управления элементами одной закладки, вот другой. Всё прозрачно и понятно.
Универсальность решения имеет границу, пройдя которую она начинает вредить.
33. kalyaka 582 14.08.18 21:03 Сейчас в теме
(32)
Надо в первую очередь думать как сделать сложную форму проще

Хочу уточнить, Вы имеете в виду проще в плане реализации, но не в поведении?

А про кучу состояний проблема надуманна

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

А вот принцип "разделяй и властвуй" - пожалуйста

Согласен, пожалуйста :) В предложенной системе этот принцип заложен в основу. По другому Вы не сможете описать состояние формы: для описания Вам потребуется разделить форму на элементы и состояние каждого элемента необходимо описать. Есть возможность объединять элементы в логические группы и тогда достаточно описать состояния группы элементов.

Универсальность решения имеет границу

Концепция конечного автомата это не просто унивесальность, это другая парадигама мышления. Фактически это функциональный подход в программировании.
34. WalterMort 318 15.08.18 12:39 Сейчас в теме
(33) проще в поведении, конечно. Минимум элементов. А видимость менять вообще зло. В лучшем случае вид формы должен изменятся с одним реквизитом, видом операции, например. Остальные "спецэффекты" типа "тут включил - здесь появилось" это отстой. А когда форма имеет простое поведение, и городить ничего не надо.
35. kalyaka 582 15.08.18 16:02 Сейчас в теме
(34) Я тоже против перегруженных форм с большим количеством возможностей.

Однако именно управление видимостью позволяет делать формы более простыми для пользователя. Особенно в управляемых формах, когда скрытые элементы не занимают пространство.

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

И возвращаясь к перегруженным и простым формам - на мой взгляд это две крайности. Нужно стремиться к формам с лучшим взаимодействием или с низким уровнем когнитивного сопротивления (Алан Купер), разве нет?
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Разработчик 1С
Санкт-Петербург
зарплата от 140 000 руб.
Полный день

Консультант-аналитик 1С
Санкт-Петербург
зарплата от 90 000 руб.
Полный день

Программист 1С
Москва
зарплата от 150 000 руб. до 200 000 руб.
Полный день

Аналитик 1С
Москва
зарплата от 120 000 руб. до 200 000 руб.
Полный день

Программист 1С
Екатеринбург
зарплата от 80 000 руб. до 130 000 руб.
Полный день