Форум
Философия программирования
Тема
Как правильно задавать вопросы
B
I
abc
U
X
3
X
3
H1
H2
H3
H4
H5
H6
Asm
C/C++
C#
Erlang
Haskell
IDL
Java
Lisp
MSIL
Nemerle
ObjC
OCaml
Pascal
Perl
PHP
Prolog
Python
Ruby
Rust
SQL
VB
Здравствуйте, Alekzander, Вы писали: A>Здравствуйте, Sinclair, Вы писали: S>>То есть декларативщина победила - несмотря на то, что в ней крайне сложно делать вещи, которые чуть менее очевидны. A>А можно показать пример того, как "крайне сложно делать вещи, которые чуть менее очевидны"? A>А я, в свою очередь, разверну свои вопросы. Чтобы разговор стал более предметным. Вместо абстрактной декларативности я возьму лучшую на данный момент реализацию — HTML. A>[q] A>Элементарно, как ты хендлишь лайаутинг при изменении размеров окна? A>[/q] A>Лэйаутинг всегда был проклятием императивных гуёв. Очень часто с ним обходились, как мой тёзка из Македонии: делаем окно no-resize на все времена (т.е. 640×480 или меньше), вот и весь сказ. Иногда контролы растягивали по ширине. Мы все помним эти простыни [tt]OnResize() { control1.Move(); control2.Move(); ... control10.Move(); }[/tt], с тоннами бойлерплейта. Когда контролов много, логика усложнялась, туда добавляли условия, иногда группировали айдишники (или хендлы, или уж сразу ссылки/указатели). Ладно, если контролам надо было просто подгонять ширину, а если что-то большее? A>Допустим, нужно сделать представление с карточками контактов (как в Outlook). Там ведь и переносы на новую строку, и расстояние между карточками, и отступы. И в дело вступает, как я это называю, LISP-архитектура (от старой шутки про то, что любая сложная система без ЛИСПа содержит самодельный ЛИСП, умеющий половину от оригинала, несовместимый и глючный). То есть, люди начинают писать свой layout-менеджер. Самое смешное, что часто люди этого даже не понимают. Им так и кажется, что у них всё императивно. Они начинают... что? Правильно: искать КОМПОНЕНТ. (Кстати, это ещё один антоним декларативности — декларативность с компонентностью не совместима, точнее, в HTML (как высшей форме декларативности) есть только псевдокомпоненты, а не настоящие компоненты, об этом ниже). Компонент, который умеет отображать карточки. А декларативную схему программист закладывает в настройки этого компонента. Когда их сериализуешь — получишь декларативность, но очень хорошо замаскированную. Криптодекларативность. :) В HTML, для сравнения, не нужен компонент, а нужен простой div. (Или текст, или кнопка, или любой контейнер). Лэйаутинг натягивается на что угодно. A>Настоящая проблема (императивщиков) в том, что декларативные средства сейчас стали очень изощрёнными. Даже простая сетка в императивном коде уже превращается в проблему. Там, где в CSS можно указать: [tt]grid-template-columns: 2fr 1fr 1fr;[/tt] и получить сетку с тремя колонками, первая из которых вдвое шире остальных, императивщикам уже надо писать логику с нуля. Некоторые подключают ЧатГПТ, который, как раз, хорошо генерирует решения задач, которые миллион раз уже решали. Но CSS умеет намного больше. Допустим, надо слить в пары две первые и две последних ячейки (в индексах узлов). Или сливать помеченные ячейки. И тут разом приплыли и императивщики, и ЧатГПТ. A>[q] A>Как ты делаешь адаптивность? (Под разные размеры, разные dpi, разный предпочтительный размер шрифта) A>[/q] A>Вообще, флексов-гридов-авторазмеров, по идее, достаточно, чтобы сделать адаптивный дизайн под любой экран. Но бывает, что мы хотим радикально поменять расстановку элементов для маленького, среднего и большого размеров. В CSS у нас есть брейкпоинты (они же медиазапросы), которые помогают привязывать способ расстановки к диапазонам. Писать это всё руками — можно застрелиться. Впрочем, те, кто не пишут и не думают ни о какой адаптивности — они, ясен пень, совершенно не страдают. :) A>"Предпочтительный размер шрифта" — раньше это была чисто браузерная хрень: A>[url=https://files.rsdn.org/144487/firefox_eWOCPdf3Pq.png]Image: firefox_eWOCPdf3Pq.png[/url] A>Но вообще, теперь она везде. В Андроиде, в 11-й винде: A>[url=https://files.rsdn.org/144487/ApplicationFrameHost_r4iP7Awdx9.png]Image: ApplicationFrameHost_r4iP7Awdx9.png[/url] A>Как её учитывать? A>В CSS для этого есть специальные единицы — rem (доли базового размера). Что удобно, дефолтный базовый размер обычно привязывают к степени двойки (16), и это даёт нам всегда конечную десятичную дробь для условно-среднего юзера при переходе от пикселей. Было бы удобнее иметь "условный пиксель", но этого в CSS, увы, нет. Вернее, есть, но не во всех стандартах. Однако, "условный пиксель" можно получить препроцессингом, например, в LESS, если задать нужную переменную, [tt]width: 20/@rem;[/tt] будет означать "ширина 20 пикселей при дефолтном размере, с пропорциональным изменением при недефолтном". А в императивщине что? Это даже сравнивать смешно. A>Далее, относительность размеров в CSS иерархическая. R в rem это Root. Но на каждом уровне размеры можно привязать к контейнеру. Допустим, размер иконки 2em это два базовых размера текста для конкретно этого контейнера. A>Опять же, если просто не знать про настройку базового размера текста, и игнорировать её, проблема решится сама собой. Для программиста, не для юзера. A>[q] A>Как поддерживаешь no-mouse A>[/q] A>Если человек похож на Стивена Хокинга и у него двигается один палец, надо сделать интерфейс доступным для работы с клавиатурой. Впрочем, я просто люблю активно использовать клавиатуру, а не дёргать мышь по пустякам. A>Я уже немножко устал писать, поэтому сразу к неочевидным вещам: A>[code] A>/* Special case: if any element OUTSIDE navbar is focused with keyboard, enforce hiding navbar. */ A>body:has(*:focus-visible) .navbar.headroom--not-top:not(:has(*:focus-visible)) A>{ A> --navbar-action: var(--navbar-dont-mess) !important; A>} A>/* Special case: if any element INSIDE navbar is focused with keyboard, enforce showing navbar. */ A>.navbar:has(*:focus-visible) A>{ A> --navbar-action: var(--navbar-show) !important; A>} A>[/code] A>Что тут написано? (Это можно было бы упаковать в одно выражение, но я его слегка денормализовал для читаемости). Написано тут следующее. Если пользователь навигирует по скроллируемому контейнеру при помощи кнопок Tab / Shift + Tab (допустим, он редактирует многостраничную презентацию и выделяет объекты внутри слайдов), контейнер, конечно, прокручивается, но выбранный элемент (именно при помощи клавиатуры!) может попасть под навигационную панель. Поэтому, при наличии выделенных с клавиатуры объектов панель должна [b]не мешать[/b]. Но если юзер донавигирует до контролов, расположенных на самой панели, она должна быть [b]отображена[/b]. A>При этом, у нас выдерживается правильный уровень абстрактности. "Не мешать" расшифровывается где-то отдельно. Это может быть простое скрытие, плавное скрытие, полупрозрачность, что угодно. A>Я очень хочу посмотреть, как в одну-две строки всю эту логику упихает императивщик. A>Но если о таком не задумываться, и вообще не делать клавиатурную навигацию, или не париться, когда выделенный элемент не видно под навигационной панелью, то, конечно, проблем снова не возникнет. A>А ещё, декларативный подход позволяет легко и просто задавать разные стилизации фокусных рамок для обычных кнопок, прозрачных кнопок на фоне картинки (например, кнопок управления видеопотоком), светлых, тёмных, всяких разных. ОС (та же винда) в лучшем случае отобразит квадратную рамку с фиксированным офсетом. Которая на круглой кнопке Play/Pause будет смотреться как на корове седло. Для сравнения: A>[url=https://files.rsdn.org/144487/chrome_j9KUoma3tV.png]Image: chrome_j9KUoma3tV.png[/url] A>Это стилизация фокусной рамки для круглой прозрачной кнопки на фоне видео. Она, что естественно, такая же круглая, как и сама кнопка. A>А вот это нечто похитрее: A>[url=https://files.rsdn.org/144487/chrome_Na8SopkNiG.png]Image: chrome_Na8SopkNiG.png[/url] A>Это таб-контрол с переопределениями. В ортодоксальном таб-контроле мы ходим по вкладкам через Tab и активируем их пробелом/Enter'ом. Тут же у нас объединённый контрол, в котором мы переключаемся между вкладками кнопками-стрелками (для удобства). Такие вещи легко переопределять при помощи tabindex: для контейнера он задаёт табабельность (возможность фокусироваться с клавиатуры), а для радиокнопок — её отменяет. При этом, за счёт [tt]:has()[/tt] в селекторе стилизации можно сделать общую фокусную рамку, но оставить старую логику навигации (с переходом от вкладки ко вкладке при помощи Tab). A>Как это всё описывать императивно? Со слезами на глазах. A>А вот ещё: A>[url=https://files.rsdn.org/144487/chrome_6OWoq5EpZW.png]Image: chrome_6OWoq5EpZW.png[/url] A>Это фокусная рамка (и сам контрол) поменяли свой цвет. Просто потому, что попали на тёмный фон. Декларативное описание в CSS позволяет очень просто группировать цвета (как и всё остальное), делая что угодно от простого "блок на тёмном"/"блок на светлом" до полноценных скинов. A>Конечно, если не делать скины, и не делать блоки разноцветными, то проблемы, опять же, не возникнет. A>[q] A>Как поддерживаешь ... слепых A>[/q] A>Ну, тут всё просто. Есть декларация — отдаём её скринридеру. Нет декларации — "слепой чёрт должен сидеть дома, а не пользоваться нашими UI'ем!" (ц). A>На самом деле, конечно же, дай дураку декларативный HTML/CSS, он и из него сделает императивное говно, и скринридер не сможет ничего озвучить. У декларативности есть свои градации. В HTML истинно декларативный интерфейс называется "семантическая разметка". A>Вообще, accessibility это такой тест на вшивость. Если делаешь хорошо (описывая кнопки как кнопки и т.д.), она будет сама собой. Если делаешь плохо, то не будет. Всякие технологии типа WAI ARIA содержат дохрениллион атрибутов, которыми можно управлять accessibility (метка, роль компонента, описание — всё это для скринридера), но искусство программиста в том, чтобы добиваться результата без их использования. Это официальный дзен accessibility, про который можно прочитать на MDN, например. A>Конечно, если не поддерживать слепых... Ну, тенденция уже понятна, да? :) A>[q] A>Как поддерживаешь ... слабовидящих, эпилептиков A>[/q] A>"Буду краток". Условные декларативные стилизации, собранные в одном месте, позволяют добиться результата намного проще, чем куча if'ов, разбросанных по всему коду. A>[q] A>Как что-то меняешь в чужих контролах? A>[/q] A>Был такой случай. Чел спросил: я, мол, пользуюсь слайдером Owl carousel (известный слайдер) и хочу задать промежуток адаптивно (т.е. не 10px, а 0.625rem, чтобы при изменении базового размера промежуток пропорционально менялся). А компонент принимает строго число, трактуя его как пиксели. Как быть? A>Императивно-компонентный подход настолько въелся в этих людей, что они не видят совершенно очевидного. Тут нет компонентов. А эти псевдокомпоненты (я обещал, что ниже объясню) — всего лишь декларативная разметка, декларативная стилизация и немножко обработчиков. A>Ему ответили совершенно правильно: посмотри, какую разметку генерирует "компонент", и перестилизуй её как хочешь. Грубо говоря, напиши: A>[code] A>.owl-slide A>{ A> margin: 0.625rem !important; A>} A>[/code] A>Что делают при отсутствии декларативности? Покупают исходный код компонента, меняют, пересобирают. Иногда декомпилируют. При каждом обновлении версии — смыть, повторить. A>А ведь в чужих компонентах бывают ошибки и похлеще. A>Поисправляешь их недельку-другую, и быстро начнёшь ценить декларативность. A>И чем больше у тебя юзеров, тем больше среди них слепых, одноруких, эпилептиков, тех, кто поставил размер базового шрифта ровно 21, юзает вертикальный экран с HiDPI и коэффициентом масштабирования 125%, и ещё выводит результат на печать. И приходится всё делать правильно, потому что каждая группа это, например, тысяча лицензий.
Теги:
Введите теги разделенные пробелами. Обрамляйте в кавычки словосочетания с пробелами внутри, например:
"Visual Studio" .NET
Имя, пароль:
Загрузить
Нравится наш сайт?
Помогите его развитию!
Отключить смайлики
Получать ответы по e-mail
Проверить правописание
Параметры проверки …