как не ронять сервер на больших выгрузках / Хабр | Веб-студия Nat.od.ua
как не ронять сервер на больших выгрузках / Хабр
Бытует мнение, что Битрикс прожорлив, и способен поглотить все ресурсы, которые есть на сервере. Такая проблема действительно существует, и компаниям иногда приходится рассматривать покупку другой конфигурации сервера, например, при сильном расширении ассортимента или увеличении количества задач бизнеса, решаемых обращением к БД.
Посмотрим, как можно сэкономить ресурсы сервера, чтобы таких вопросов не возникало.
Зачем это надо
Сначала приведём пример стандартной задачи и покажем, что оперативная память сервера быстро расходуется при использовании метода GetList. А затем разберёмся, как избежать проблемы.
Итак, у нас есть интернет-магазин на 50 000 товаров. У каждого товара есть 20 пользовательских свойств. Задача: пробежаться по всем товарам и что-то сделать, изменить какие-то свойства или выгрузить каталог.
В данном примере я показываю код в исследовательских целях.
Итак, что обычно делает программист Битрикс, когда надо получить элементы каталога:
$elements = CIBlockElement::GetList(
array(),
array(“IBLOCK_ID” => $iblockId),
false,
false,
array(“ID”, “IBLOCK_ID”, “NAME”)
);
while ($element = $elements->GetNextElement()) {
$el=$element->GetFields();
$el=$element->GetProperties();
$items[]=$resElement;
}
На выгрузках в несколько тысяч элементов этот код сработает, и мы получим список элементов. Но уже на 20 000 элементах сервер отправляется в даун. Что же происходит, и почему сервер падает?
Чтобы это выяснить, используем дебаг методы Битрикс и метод PHP memory_get_usage(), который позволяет получить количество используемой оперативной памяти.
$debuglable=”main”;
BitrixMainDiagDebug::startTimeLabel($debuglable);
echo “
Количество используемой оперативной памяти: ". round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL."
“;
$counter=1;
$elements = CIBlockElement::GetList(
array(),
array(“IBLOCK_ID” => $iblockId),
false,
,
array(“ID”, “IBLOCK_ID”, “NAME”)
);
while ($element = $elements->GetNextElement()) {
$el=$element->GetFields();
$el=$element->GetProperties();
$items[]=$resElement;
}
echo “
Количество используемой оперативной памяти: ". round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL."
“;
BitrixMainDiagDebug::endTimeLabel($debuglable);
$lable= BitrixMainDiagDebug::getTimeLabels();
echo “Выборка из “.$counter.” элементов :
"; echo 'Время выполнения скрипта: '. $lable; echo "
“;
Получим такой результат (рис.1). Зафиксируем, что размер выборки одного элемента составляет около 1,5 Мб.
Рис. 1. Выборка из 1 элемента.
Увеличим выборку до 10 элементов, изменяя переменную $counter, для регулирования количества выводимых элементов:
Рис. 2. Выборка из 10 элементов.
Увеличим выборку до 100 элементов:
Рис. 3. Выборка из 100 элементов.
Ну и увеличим до 1000 элементов:
Рис. 4. Выборка из 1000 элементов.
Итак, мы видим что при увеличении количества элементов быстро растёт потребление оперативной памяти, что в конечном счете приводит к тому, что объём данных превышает размер оперативной памяти сервера и сервер падает.
Конечно, данную проблему можно решить разбив запрос на несколько, используя параметр nOffset, запустить цикл, получить результат нескольких запросов и решить вопрос.
Но так мы не решаем проблему, а скорее ее усугубляем. Усложняем код и получаем цикл запросов к БД.
Есть другой путь?
Можно использовать ключевое слово yield в PHP для создания функции-генератора. Какая польза от yield в PHP?
Возможно, вы уже слышали, но на практике ещё не применяли. Обратимся к справке PHP:
Когда вызывается генератор, он возвращает объект, который можно итерировать. Когда вы итерируете этот объект (например, в цикле foreach), PHP вызывает методы итерации объекта каждый раз, когда вам нужно новое значение, после чего сохраняет состояние генератора и при следующем вызове возвращает следующее значение.
Когда все значения в генераторе закончились, генератор просто завершит работу, ничего не вернув. После этого основной код продолжит работу, как если бы в массиве закончились элементы для перебора.
Вся суть генератора заключается в ключевом слове yield. В самом простом варианте оператор “yield” можно рассматривать как оператор “return”, за исключением того, что вместо прекращения работы функции, “yield” только приостанавливает её выполнение и возвращает текущее значение, и при следующем вызове функции она возобновит выполнение с места, на котором прервалась.
Как применить yield в нашем случае и что мы получим:
// Функция-генератор для получения свойств элемента инфоблока
function getProperties($elements)
{
while ($element = $elements->GetNextElement()) {
$resElement=$element->GetFields();
$resElement=$element->GetProperties();
yield $resElement;
}
}
$iblockId=7;
$counter=1;
echo “
Количество используемой оперативной памяти: ". round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL."
“;
// Получение всех элементов инфоблока
$elements = CIBlockElement::GetList(
array(),
array(“IBLOCK_ID” => $iblockId),
false,
,
array(“ID”, “IBLOCK_ID”, “NAME”)
);
$propertyes=getProperties($elements);
echo “
Количество используемой оперативной памяти: ". round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL."
“;
BitrixMainDiagDebug::endTimeLabel($debuglable);
$lable= BitrixMainDiagDebug::getTimeLabels();
echo “Выборка из “.$counter.” элементов :
"; echo 'Время выполнения скрипта: '. $lable; echo "
“;
При выборке одного элемента результат тот же что и при первом методе:
Рис. 5. Использование генератора: выборка из 1 элемента.
При выборке 10 элементов потребление памяти не меняется:
Рис. 6. Использование генератора: выборка из 10 элементов.
На 100 элементах потребление памяти также не растёт:
Рис. 7. Использование генератора: выборка из 100 элементов.
Ну и проведём финальный эксперимент. Сделаем выборку из 20 000 элементов. Помним, что при первом варианте такая выборка укладывала сервер.
В результате скрипт выполнялся минуту, но потребление памяти выросло совсем немного:
Рис. 8. Использование генератора: выборка из 20 000 элементов.
За счет чего мы получили такой результат? Ответ кроется в природе генераторов. При создании массива весь массив помещается в память целиком, а при использовании генератора при итерировании вы каждый раз получаете только один элемент итерируемого массива. Что и позволяет снизить потребление оперативной памяти.
В результате мы получили легкий понятный код. Не переусложнёный пагинацией обращений к БД. И то, что при первом варианте в принципе было невозможно на текущей конфигурации сервера, теперь выполняется, и мы получаем необходимый нам результат.
Где в Битрикс можно применить данный подход?
Во-первых, это всё, что связано с выгрузкой каталога интернет-магазина: формирование прайслистов, фидов и другое.
Во-вторых, обработка данных пользователей:
чистка от регистраций ботов,
изменение формата телефонов,
добавление или удаление каких-то свойств.
В-третьих, это массовое изменение свойств товаров: цен, характеристик и т.п.
А также другие задачи, для выполнения которых требуется выгрузка большого количества элементов.
P.S. Ну и напоследок скажу, что для обработки массивов и объектов PHP предлагает удобные инструменты библиотеки SPL — набор классов для итерации объектов. При их использовании у вас появляются дополнительные возможности при итерировании массивов и объектов.
React + Three.js. Создаём собственный 3D шутер. Часть 2 / Хабр | Веб-студия Nat.od.ua
React + Three.js. Создаём собственный 3D шутер. Часть 2 / Хабр
Привет, уважаемые участники Хабр!
Введение
В современной веб-разработке границы между классическими и веб-приложениями стираются с каждым днём. Сегодня мы можем создавать не только интерактивные сайты, но и полноценные игры прямо в браузере. Одним из инструментов, который делает это возможным, является библиотека React Three Fiber – мощное средство для создания 3D-графики на основе Three.js с использованием технологии React.
В сегодняшней статье мы реализуем:
анимацию прицеливания из оружия;
анимацию вспышки при стрельбе;
добавим звуковой эффект при выстреле.
Репозиторий на GitHub
Финальное демо
Небольшие правки
Перед началом работы, создадим новую папку images для изображений в папке assets. И перенесём в эту папку изображение поверхности пола.
Также изменим путь к изображению в файле Ground.jsx.
Файл Ground.jsx с изменённым путём к изображению
Код раздела
Механика прицеливания
Как и в большинстве шутеров, прицеливание задействуется при помощи нажатия правой кнопки мыши. Но пользователи могут переназначить данную кнопку на любую другую в любой момент в настройках игры. Поэтому мы не будем непосредственно в коде задавать условие нажатие данной клавиши, а реализуем отдельный конфиг, в котором будем задавать управление.
В React(Vite) уже существует возможность без дополнительных библиотек создать такой конфиг. Для этого необходимо создать в корне проекта файл .env. Далее, именно в формате VITE_*** мы можем задавать переменные окружения, которые мы сможем использовать в любом месте нашего проекта.
В файле конфигурации .env добавим две переменные, которые будут содержать коды нажатия кнопок мыши. А именно, код кнопки мыши для активации стрельбы, а также для прицеливания.
.env с добавленными переменными
Теперь необходимо переработать логику нажатия кнопок мыши, чтобы при нажатии разных кнопок активировались разные действия.
Но сначала необходимо исправить некоторое некорректное поведение при перехвате курсора мыши на холсте. В данный момент, при клике мыши по экрану сразу же срабатывает действие выстрела, что выглядит немного странно. Поэтому мы добавим логику, что пока курсор не будет перехвачен приложением, то никаких событий клика не будет происходить.
Теперь мы воспользуемся библиотекой для хранения глобального состояния Zustand. В файле App.jsx добавим состояние, а также добавим обработчики событий на блокировку и разблокировку курсора.
Изменения в файле App.jsx
В файле Weapon.jsx добавим новую логику, которая будет разграничивать нажимаемые клавиши мыши, а также учитывать состояние перехваченного курсора.
Создадим функцию mouseButtonHandler. Внутри будем определять текущее состояние перехваченного курсора и в случае, если курсор ещё не был перехвачен, то мы не будем выполнять никаких действий. Ещё необходимо импортировать из конфига .env значения для клавиш мыши, при использовании которых активируется режим стрельбы или прицеливания.
Получение значений из .env
Также изменим логику обработчиков событий при нажатии и отпускании клавиш мыши.
Изменённый обработчик событий по клику мыши
Теперь займёмся непосредственно реализацией анимацией прицеливания.
Для начала, добавим новое состояние useAimingStore для хранения состояния прицеливания.
Импорт Zustand
Состояние в Weapon.jsx
Добавим переменную для возможности изменения состояния прицеливания.
Получение функции setIsAiming
А в функции mouseButtonHandler, где ранее оставили пустое место для кнопки AIM_BUTTON, добавляем изменение состояния.
Изменение состояния в mouseButtonHandler
Перейдём к файлу Player.jsx и займёмся реализацией внутри него.
Во-первых, необходимо импортировать состояния useAimingStore из файла Weapon.jsx. А также перенести константу easing в корень файла.
Импорт useAimingStore и константа easing
Добавим состояние isAiming для дальнейшего использования в файле.
Состояние isAiming
Для сохранения состояния анимации добавим два состояния: анимация прицеливания и возврат в исходное состояние.
Добавление состояний aimingAnimation и aimingBackAnimation
Теперь создадим функцию initAimingAnimation, в которой будут описываться оба состояния анимации прицеливания.
Функция initAmingAnimation
Чтобы данная анимация могла запускаться, необходимо при инициализации приложения вызвать функцию initAimingAnimation. При этом именно тогда, когда уже будет готов для взаимодействия объект, внутри которого находится модель оружия.
useEffect для инициализации анимации initAimingAnimation
При изменении состояния isAiming необходимо запускать или анимацию прицеливания, или возврата оружия в начальное положение. Для этого добавим useEffect, внутри которого по условию будет срабатывать та или иная логика. Так, например, при начале процесса прицеливания, потребуется остановить анимацию “покачивания”, а затем запустить анимацию прицеливания. При отпускании кнопки мыши запускается анимация возврата оружия в начальное положение, а при срабатывании события onComplete повторно запускается анимация “покачивания”.
useEffect для активации эффекта анимации
Но сейчас при инициализации приложения происходит начальный запуск анимации и получается, что будто игрок прицеливался, а затем выходит из режима прицеливания. Происходит это потому, что по умолчанию isAiming установлен в false, и при инициализации сразу же срабатывает ветка “или” в условии. Решить это можно, исправив значение по умолчанию в null, а затем изменив условие, добавив конкретное значение в условии.
Состояние с изменённым значением isAiming на null
useEffect для активации анимации с исправленным условием
Таким образом, теперь при клике правой кнопки мыши у нас происходит анимация прицеливания, а при отпускании – выход из этого режима.
Анимация прицеливания
Код раздела
Рефакторинг анимации отдачи
Перед тем, как приступить к следующей части нашей статьи, проведём некоторый рефакторинг реализации анимаций.
В файле Player.jsx изменим название функции с setAnimationParams на setSwayingAnimationParams. А также заменим данное название функции в остальных местах.
Файл Player.jsx с изменённым названием функции
А из функции initSwayingObjectAnimation уберём константу easing, т.к. ранее мы вынесли её в корень файла.
Убранная константа easing
Перейдём к исправлению файла Weapon.jsx.
Изменим значение для recoilDuration на 50.
Изменённое значение recoilDuration
Удалим recoilBackAnimation за ненадобностью. Вместо этого теперь добавим isRecoilAnimationFinished.
Добавленное состояние isRecoilAnimationFinished
Для функции generateNewPositionOfRecoil добавим значение по умолчанию для параметра currentPosition.
Значение по умолчанию для функции generateNewPositionOfRecoil
В функции initRecoilAnimation удалим константу initialPosition за ненадобностью.
Убрана переменная initialPosition
Для Tween-анимации переработаем логику, сделав её автоматически-возвратной к исходной позиции, из которой началось выполнение анимации. Также удалим возвратную анимацию twRecoilBackAnimation.
Изменённая функция initRecoilAnimation
Переработаем useEffect, разделив на 2 разные функции. В первой будет инициализации анимации, а во второй будет запуск анимации отдачи оружия.
Изменённая логика useEffect
Код раздела
Анимация вспышки при выстреле
Теперь займёмся реализацией отображения вспышки при выстреле из оружия.
В файле Weapon.jsx импортируем функцию useLoader. А также загрузим изображение вспышки в assets/images.
Изображение вспышки при выстреле
В компоненте импортируем данное изображение как FlashShoot.
Импорт изображения
Далее воспользуемся функцией useLoader для загрузки данного изображение на сцену. А также добавим состояние для сохранения анимации flashAnimation.
Импорт useLoader
Загрузка изображения на сцену и состояние анимации вспышки
Создадим новое состояние flashOpacity для плавного изменения прозрачности вспышки. Также создадим новую функцию initFlashAnimation, в которой опишем последовательность анимации. И после этого воспользуемся useEffect для инициализации анимации.
Реализация анимации вспышки при выстреле
Теперь необходимо вывести данное изображение на сцене на одном уровне с моделью оружия, задав расположение таким образом, чтобы изображение располагалось непосредственно на конце дула оружия.
Добавление изображения на сцену
И в конце добавим вызов анимации при каждом выстреле в функции startShooting.
Доработанная функция startShooting
Анимация вспышки при выстреле
Код раздела
Добавление звука выстрела
Добавим подготовленный звуковой файл в папку assets/sounds.
Импортируем его в файл.
Импорт аудиофайла
При помощи HTMLAudioElement мы можем добавить звуковой файл для текущей страницы (не для сцены).
Добавление аудио в документ
При вызове функции startShooting запускаем данный аудиофайл. При нескольких выстрелах запускаемые аудиофайлы будут запускаться и накладываться друг на друга. И в конце просто прекращать воспроизводиться.
Проигрывание аудио в функции startShooting
Код раздела
Заключение
В этой статьи мы добавили анимацию прицеливания, анимацию появления вспышки при выстреле, а также звуковой эффект при выстреле. В следующей части мы продолжим дорабатывать нашу игру, добавляя новый функционал.
Спасибо за прочтение и буду рад ответить на комментарии!
7 тегов, которые упростят вам жизнь / Хабр | Веб-студия Nat.od.ua
7 тегов, которые упростят вам жизнь / Хабр
В этой статье я расскажу про 7 HTML-тегов, которые, возможно, вы еще не открыли для себя. Мы посмотрим, как они работают и насколько поддерживаются современными браузерами. Поехали!
/
Это теги для добавления текста с надстрочным и подстрочным индексами.
Иногда нам нужно выделить символы или цифры, которые находятся выше или ниже базовой линии текста. Например, в химии для обозначения химических формул, в математике для записи степеней и индексов, в музыке для обозначения аккордов, или просто для оформления сносок и сокращений. Все это можно легко достичь с помощью тегов и .
Никаких атрибутов не требуют.
Пример использования в математическом выражении:
Σi=1n (xi2 + yi2)
Результат вывода кода
Пример использования в музыке:
Песня: “Wonderful Tonight” by Eric Clapton
A E7
It’s late in the evening
D A
She’s wondering what clothes to wear
A E7
She puts on her make-up
D A
And brushes her long blonde hair
На данный момент, по статистике caniuse, поддерживаемость тегов , на уровне 96%:
/
Это теги для оформления текста, связанного с клавишами и выводом кода.
— используется для обозначения клавиш на клавиатуре или клавиатурных комбинаций. Это может быть полезно, например, при создании инструкций или руководств по использованию программного обеспечения.
Пример:
Нажмите Enter, чтобы продолжить.
— этот тег используется для отображения вывода кода, результатов выполнения программы. Этот тег может быть полезен при демонстрации примеров кода на веб-странице.
Пример:
Для вывода текста на экран в Python используется функция print().
P.S. Также существует тег ,который по сути делает то же самое, однако, разница состоит в том, что
используется для отображения программного кода, а — для отображения результата выполнения этого кода.
Поддерживаемость браузерами тегов и :
(Bi-Directional Override) используется для изменения направления текста. Это особенно полезно при работе с языками, которые читаются справа налево, такими как, например, арабский или иврит.
Тег в HTML имеет всего один обязательный атрибут:
Пример:
مرحبا بك في موقع الويب
Привет, это обратное направление текста
Привет, это обратное направление текста
Также существует CSS свойство direction, которое позволяет делать то же самое, но более глобально, на уровне стилей:
HTML:
Это текст с измененным направлением.
CSS:
.right-to-left {
direction: rtl; /* Устанавливаем направление текста справа налево */
}
Поддерживаемость тега:
Этот тег используется для расшифровки аббревиатур и акронимов. В этом примере используется для создания аббревиатуры "HTML" с полным расшифровкой "HyperText Markup Language". Если навести курсор мыши на аббревиатуру, то можно увидеть всплывающую подсказку с полной расшифровкой.
Атрибуты:
title — используется для расшифровки аббревиатуры/акронима. Когда юзер наводит курсор мыши на аббревиатуру, всплывает подсказка (tooltip) с тем текстом, что был указан в атрибуте.
NASA, является ведущей организацией в области исследования космоса и аэронавтики.
Поддерживаемость браузера опять составляет 96,16%:
Этот тег используется внутри элемента
Чаще всего с optgroup используются атрибуты label и disabled:
Атрибут label используется для установки названия группы вариантов выбора внутри
Результат кода:
Атрибут disabled применяется для отключения группы вариантов выбора. Когда группа
Поддерживаемость браузерами — 96,16%:
Продолжая тему выпадающих списков, стоит рассказать про тег
Тег
Чтобы указать, какой список вариантов должен отображаться для какого поля ввода,
А еще этот тег поддерживает функцию автозавершения: браузер автоматически заканчивает ввод пользователя на основе доступных вариантов из списка
Тег
Использование с типом color:
Использование с типом range:
Поддерживаемость браузерами составляет 96,48%:
Теги
используются для создания спойлеров и скрытой информации без использования JavaScript. Эта пара может быть полезна для создания, к примеру, FAQ-страницы, фильтров и сортировок (указание скрытых свойств для экономии места), инструкций, руководств и комментариев.Внутрь тега
помещается тег , который служит своего рода “кнопкой” для открытия/скрытия информации. Пример: Как я могу установить приложение?
Для установки нашего приложения, перейдите на страницу "Загрузки" и следуйте инструкциям для вашей операционной системы.
Тег
может иметь атрибут open, который определяет, будет ли содержимое блока отображаться открытым по умолчанию при загрузке страницы и не требовали щелчка пользователя для раскрытия. По умолчанию атрибут open равен false: Какой-то вопрос
Этот блок с вопросом уже открыт при загрузке страницы.
Теги поддерживаются браузерами на 96,78%:
details & summar
, который служит своего рода “кнопкой” для открытия/скрытия информации. Пример: Как я могу установить приложение?
Для установки нашего приложения, перейдите на страницу "Загрузки" и следуйте инструкциям для вашей операционной системы.
Тег
может иметь атрибут open, который определяет, будет ли содержимое блока отображаться открытым по умолчанию при загрузке страницы и не требовали щелчка пользователя для раскрытия. По умолчанию атрибут open равен false: Какой-то вопрос
Этот блок с вопросом уже открыт при загрузке страницы.
Теги поддерживаются браузерами на 96,78%:
details & summar
Как я могу установить приложение?
Для установки нашего приложения, перейдите на страницу "Загрузки" и следуйте инструкциям для вашей операционной системы.
Какой-то вопрос
Этот блок с вопросом уже открыт при загрузке страницы.
Теги поддерживаются браузерами на 96,78%:
details & summar
как научиться понимать то, что нарисовал дизайнер / Хабр | Веб-студия Nat.od.ua
как научиться понимать то, что нарисовал дизайнер / Хабр
Чтобы понимать, что нарисовал дизайнер, нужно проникнуться его мышлением, принципами и правилами, которые он применяет при создании макетов. Только тогда мы сможем правильно интерпретировать его дизайн и избежать простых ошибок, которые при разработке фронтенда забирают огромное количество времени.
Если у вас только один фронтенд, все еще не так плохо. Однако, когда их количество достигает 10, микроошибки в компонентах могут отнимать до 200-300 человеко-часов в год. С учетом современных зарплат, это значительная сумма. А помимо фронтенда у нас также есть бекенд, девопс и тестирование, что также требует значительных затрат. Давайте вместе разберемся, как можно справиться с этой проблемой.
Эта статья основана на докладе Николая Маринина, Product owner в Ultie.org, участника программного комитета и спикера FrontendConf. За свою более чем 16-летнюю карьеру в IT, он работал на стыке дизайна и фронтенд-разработки и уделял много времени поиску способов улучшения коммуникации между дизайнерами и фронтенд-разработчиками.
Будем рассматривать на примере простой панели нашего сервиса по проведению соревнований по флаинг диску. Как в дизайне, так и в верстке, основу составляют layout’ы и компоненты. Простыми словами: layout’ы предоставляют основу для компонентов, и компоненты не нарушают и не изменяют layout’ы.
Идеально, когда вы видите макет таким образом, разделяя layout’ы и компоненты, учитывая отступы, длину текста и боксы для иконок, и понимаете, как все будет масштабироваться:
Кроме того, вы можете проверить дизайнера в Figma с помощью режима SHIFT+O, который показывает линии на всех объектах.
Outline режим в Figma
Но, иногда у дизайнера и фронтенд-разработчика не хватает опыта. Разработчик мыслит инлайновыми ссылками, и может не понимать, куда направляются данные и отступы, и как все будет масштабироваться:
С другой стороны, дизайнер может не владеть культурой формирования макетов в Figma. Иконки могут быть не в боксах, компоненты не выделены, отсутствуют ограничители текста и многое другое:
Outline режим в Figma
1. Компоненты
Основная проблема в интерпретации дизайна заключается в использовании разных инструментов. У дизайнера есть Auto layouts. Они помогают создавать адаптивные макеты, реагирующие на изменение контента и размеры экрана. Фактически, хорошие дизайнеры сейчас не просто рисуют, а верстают с помощью Flexbox. Он может направлять данные в нужные стороны, устанавливать отступы и прижимать контент. Все это видно сразу при нажатии на компонент.
Для разработчика все немного сложнее. Ему трудно визуализировать то, что он видит в Figma, потому что для него это просто код. Особенно сложно, когда у компонента большая вложенность элементов.
Когда дизайнер рисует компонент, он использует 10 точек для расположения данных. 9 по кругу и одна посередине. Эти точки помогают ему направить или закрепить данные внутри компонента. Если данные расположены точно посередине, они распределяются в сторону краев.
Давайте рассмотрим обычный компонент карточки команды с 4 элементами и представим, как это выглядит с использованием 10 точек:
На изображении видно, что логотип «прилипает» к левому верхнему краю, а название команды с городом — к левому нижнему. Все выглядит аккуратно, но меняется, когда мы тестируем сверстанную версию компонента. Например, при добавлении большего количества текста или изменении размера с помощью Firebug или другого инструмента в браузере.
В идеальном мире, компонент должен одинаково вести себя как в нарисованном, так и в сверстанном виде. Поведение должно выглядеть так же, как на видео:
Давайте рассмотрим еще один пример карточки с фоном, так как с ним часто возникают проблемы. Вот как он выглядит с нашим подходом:
Теперь давайте протестируем компонент на изменение размеров и количества текста.
Посмотрим, как правильно он должен себя вести:
Естественно, из этого подхода всегда будут исключения. Например, дизайнер может решить зафиксировать элемент не в 10 точках. В таком случае, нам придется выяснить, почему он решил не цеплять элемент в привычном положении.
«Идеальные» компоненты, которые правильно нарисованы и сверстаны, действительно значительно упрощают процесс адаптации. Вам достаточно сжать layout, и данные автоматически встанут на свои места, практически без изменения компонентов. Останется только исправить размеры шрифта для нужных breakpoint’ов.
2. Layouts
Давайте упростим нашу панель до такого вида, чтобы мы четко видели отступы и расположение компонентов. Таким образом, мы получим два layout’а навигации и два layout’а с контентом.
Светлая область – layouts. Темная – компоненты.
Направление данных и отступы
Разберем частые ошибки, которые совершают разработчики.
2.1. Направление отступов
Одна из самых распространенных ошибок — это использование разных подходов к отступам внутри layout’ов. Исключением является Flexbox, с которым таких проблем не возникает. Однако, в других случаях разработчики могут применять отступы в разные стороны, тогда при добавлении нового компонента, мы получим:
Пока вы работаете над проектом один, это не является большой проблемой. Но если в команде 10 разработчиков, и каждый делает отступы по-своему, баги будут возникать постоянно. Поэтому, важно договориться о едином направлении отступов. Я всегда рекомендую направлять margin’ы в горизонтальных layout’ах внутрь, а в вертикальных — вниз. Это помогает создать более последовательный и согласованный внешний вид компонентов в проекте и уменьшает количество ошибок.
2.2. Влияние дизайном компонентов на дизайн layout’ов
Допустим, у вас есть боковое меню с 4 ссылками, и вы решили немного расширить layout с помощью padding’ов (выделены голубым) по краям или сверху.
Однако, когда вы будете добавлять новый компонент, вам придется вручную добавлять padding снова. Пока во всём проекте 2-3 компонента — это терпимо, но после того, как их становится 100+ — уже неприятно. Если дизайнер решит изменить дизайн layout, вам придется переписывать стиль каждого компонента в проекте в ручную.
Кроме того, такие компоненты будут странно выглядеть в Storybook. Хотя его создание может помочь избежать таких ошибок. Поскольку сразу будет видно, что компонент занимается не тем, чем нужно 🙂
2.3 Область действия компонентов
Некоторые дизайнеры иногда забывают о правильной разметке, а разработчики просто берут размеры, указанные в макете. Поэтому важно помнить, что минимальная высота любого компонента почти всегда должна быть не менее 24px. Также следует учитывать, что в интерфейсах обычно нет inline данных. Исключением является большое количество текстовых данных, например, в новостях. В таких случаях компонент всегда должен растягиваться на всю ширину layout.
Не забывайте добавлять отступы в 8-16px по краям ссылок, чтобы пользователю было удобнее нажимать на них.
3. Цвета
Существует два подхода к формированию цветов: RGBA и RGB. Один использует прозрачность, в то время как другой избавляется от нее. Однако, самые нетерпеливые дизайнеры, чтобы ускорить работу, начинают их смешивать. Это может привести к несогласованному результату, как показано на примере:
Внимательные разработчики начинают умножать значения этих цветов. Менее опытные могут забыть добавить прозрачность, особенно для серого цвета, где отличия в несколько процентов практически незаметны.
Создание большого количества цветов в проекте может значительно усложнить работу разработчика. Поэтому единственное верное решение — просить дизайнера привести все цвета к единому стандарту (если он еще не сделал этого) и использовать функциональные стили для цветов.
4. Иконки
Многие дизайнеры используют иконки разной стилистики и размеров, и при этом забывают обвязывать их боксами, чтобы упростить жизнь разработчику.
Вместо того, чтобы пытаться индивидуально позиционировать каждую иконку в меню, проще самим завести боксы в Figma или сделать контейнеры одного размера и отцентровать иконки в них. Это будет работать в 98% случаев. Исключением будут иконки с визуальным смещением в одну из сторон, при котором требуется изменить способ их центрирования.
5. Компоненты форм
Еще одна распространенная ошибка фронтенд-разработчиков заключается в неправильном использовании inline-элементов при определении размеров компонентов. Чаще всего это происходит при верстке компонентов форм, таких как input, select, button.
Давайте рассмотрим эту проблему на примере классической кнопки. Обычно разработчик добавляет padding со всех сторон от текста, и на этом успокаивается. Однако, если изменить шрифт, или он не подгрузится, или будет иначе отображаться в другой операционной системе, то мы получим такую картину:
Как вы могли заметить, при смене шрифта есть проблема с изменением позиции текста кнопки. Она связана с различными базовыми линиями и высотой букв у разных шрифтов.
Простым и эффективным решением этой проблемы будет использование фиксированной высоты для кнопки и добавление padding’а по краям. При этом выравнивание текста можно настроить с помощью межстрочного интервала. Не помешает сделать несколько размеров кнопок, которые вы будете использовать в проекте.
Заключение
В статье перечислены основные паттерны ошибок и их полезно знать и дизайнерам и фронтендерам. Они по-разному видят процесс и настраивают свои инструменты. Поэтому если одни невнимательны к работе других, кому-то приходится делать двойную работу.
Пример с АвтоВАЗом отлично демонстрирует, как важно обеспечить соответствие между дизайном и финальной версткой. 8 лет назад были выложены новые рендеры Лада XRAY. Всё было красиво и аккуратно, но при выпуске автомобиля мы увидели изменение размеров, мелкие люфты и еще много недочетов. То же самое сейчас происходит при разработке продуктов. Если у вас итоговая верстка «люфтит и плавает» относительно того, что задумал дизайнер, то у пользователя будут те же ощущения от продукта.
Поэтому будьте внимательнее и больше взаимодействуйте с дизайнерами. Если у вас возникли вопросы или сомнения относительно дизайна, не стесняйтесь обратиться к дизайнерам. Любой адекватный дизайнер, если его попросить, с радостью объяснит, как работает его дизайн.
Добавление WebAuthn в веб-приложение / Хабр | Веб-студия Nat.od.ua
Добавление WebAuthn в веб-приложение / Хабр
Привет! В этой статье мы научимся добавлять WebAuthn в веб‑приложения со стороны frontend‑разработчика. WebAuthn представляет собой новый метод аутентификации, который обеспечивает более высокий уровень безопасности, заменяя устаревшие пароли и SMS‑подтверждения на аутентификацию на основе публичных ключей. Это не только повышает защиту от несанкционированного доступа, но и упрощает вход для пользователей. Например VK и другие компании уже переходят на подобные технологии, отходя от обычных паролей.
Основы публичного шифрования
Для понимания WebAuthn важно знакомство с концепцией публичного шифрования. Это метод, где используются два ключа: публичный и приватный. Публичный ключ можно свободно распространять, и он используется для шифрования сообщений. Шифротекст, полученный таким образом, может быть расшифрован только соответствующим приватным ключом, который должен оставаться в секрете. Эта технология лежит в основе WebAuthn, где публичные ключи обеспечивают надежную аутентификацию без передачи конфиденциальных данных.
Схема работы WebAuthn
WebAuthn
WebAuthn работает на основе нескольких ключевых этапов:
Создание вызова (challenge): Сервер генерирует уникальный вызов и отправляет его устройству пользователя.
Подтверждение пользователя: Пользователь подтверждает свое намерение аутентифицироваться, используя биометрию, PIN‑код или другой метод.
Подпись вызова: Устройство подписывает вызов своим приватным ключом, подтверждая легитимность запроса.
Отправка утверждения (assertion): Устройство отправляет подписанный вызов обратно на сайт.
Проверка утверждения: Сайт проверяет подпись с помощью ранее сохраненного публичного ключа. Успешная проверка подтверждает аутентификацию пользователя.
Пример реализации в веб-приложении
В этой части статьи мы займемся разработкой простого веб‑приложения, используя React.js. Наше приложение будет включать в себя одно поле для ввода имени пользователя и две функциональные кнопки: ‘Регистрация’ и ‘Вход’.
Регистрация
Для регистрации нового пользователя, нам нужно реализовать функцию, запрашивающую создание новых учетных данных через navigator.credentials.create(). Важный компонент здесь — publicKeyCredentialCreationOptions, который определяет параметры для создания нового ключа. Для более подробного понимания этих параметров, рекомендую ознакомиться с документацией WebAuthn.
// Функция для создания новых учетных данных (credentials) с использованием Web Authentication API.
const getCredential = async ({
challenge, // Хеш (вызов) который получаем от сервера
}) => {
// Опции для создания публичного ключа.
const publicKeyCredentialCreationOptions = {
rp: {
name: ‘my super app’, // имя надежной стороны (Relying Party)
id: ‘webauthn.fancy-app.site’, // идентификатор надежной стороны (Домен)
},
user: {
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)), // преобразование userId в Uint8Array
name: ‘User’, // имя пользователя
displayName: ‘Full username’, // отображаемое имя пользователя
},
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)), // преобразование challenge в Uint8Array
pubKeyCredParams: ,
timeout: 60000, // таймаут ожидания ответа (в миллисекундах)
excludeCredentials: [], // список учетных данных, которые следует исключить
authenticatorSelection: { // критерии выбора аутентификатора
residentKey: ‘preferred’,
requireResidentKey: false,
userVerification: ‘required’, // требование верификации пользователя
},
attestation: ‘none’, // тип аттестации, здесь не требуется
extensions: { // расширения
credProps: true, // если true, возвращаются свойства учетных данных
},
};
// API вызов для создания новых учетных данных с помощью переданных опций.
return await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions,
});
};
Эта функция возвращает объект PublicKeyCredential, который в JavaScript представляет собой публичные учетные данные. Они создаются при регистрации через WebAuthn API.
После отправки этих данных на сервер, он проводит проверку публичного ключа и, при успешной верификации, регистрирует отправившего его пользователя
PublicKeyCredential
Аутентификации
Для аутентификации пользователя нам потребуется создать функцию, применяющую navigator.credentials.get(). Эта функция будет использовать параметры publicKeyCredentialRequestOptions, которые должны включать challenge (вызов) и rpId (идентификатор надежного сайта, обычно домен)
const getAssertion = async ({ challenge }) => {
// Создание объекта с параметрами запроса учетных данных (public key credential request options)
const publicKeyCredentialRequestOptions = {
// Преобразование challenge (предоставленного сервером) в Uint8Array.
// Это необходимо, так как WebAuthn требует, чтобы challenge был в бинарном формате.
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
// Пустой массив, указывающий, что любые зарегистрированные учетные данные могут быть использованы.
// Можно указать конкретные учетные данные, если требуется ограничить доступ.
allowCredentials: [],
// Идентификатор надежной стороны (Relying Party ID), обычно домен, с которым ассоциирован запрос.
rpId: ‘webauthn.fancy-app.site’,
// Время ожидания в миллисекундах для завершения процесса аутентификации.
timeout: 60000,
// Уровень проверки пользователя. В данном случае требуется подтверждение (‘required’).
// Другие варианты могут включать ‘preferred’ или ‘discouraged’.
userVerification: ‘required’,
};
// Вызов метода get() объекта navigator.credentials с переданными параметрами.
// Этот вызов инициирует процесс получения ассерции аутентификации от пользователя.
return await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
});
};
Функция будет возвращать объект PublicKeyCredential, который затем нужно отправить на сервер. Это необходимо для процедуры аутентификации и последующего получения токена доступа.
PublicKeyCredential
Демо
Если вы хотите попробовать этот функционал на своем устройстве, воспользуйтесь ссылкой на тестовый стенд. В консоли вы увидите PublicKeyCredential, который используется как для регистрации, так и для аутентификации. Также, для детального изучения кода, предлагаю ссылку GitHub‑репозиторий.
Спасибо за внимание)
Обзор фреймворка для сбора данных OWASP Nettacker / Хабр | Веб-студия Nat.od.ua
Обзор фреймворка для сбора данных OWASP Nettacker / Хабр
OWASP Nettacker — это автоматизированная платформа (фреймворк) для автоматического тестирования на проникновение, сканирования уязвимостей, сбора информации и создания отчетов, включая найденные уязвимости, информацию об используемых компонентах и другие сведения.
Nettacker использует такие протоколы, как TCP SYN, ACK и ICMP, для обхода устройств Firewall, DS, IPS.
OWASP Nettacker разработан некоммерческой организацией OWASP, которая специализируется на обеспечении безопасности веб-приложений. Свое название программа получила от образования слов «Network» (сеть) и «Attacker» (атакующий).
Среди достоинств OWASP Nettacker можно выделить следующие:
бесплатный проект с открытым исходным кодом;
кроссплатформенность — запустить инструмент можно на ОС семейства Windows, Linux/Unix, macOS. Также доступен вариант запуска в контейнере Docker;
поддержка обширного функционала (более 80 модулей) «из коробки», включая такие инструменты, как сканер портов, сканеры для поиска информации об используемых модуле, SSH Brute force и другие. Ознакомиться с полным списком встроенных модулей можно по ссылке;
быстрая работа благодаря поддержке многопоточности;
наличие функционала для создания отчетов;
мультиязычность — утилита локализована на более чем 20 различных языков (включая русский язык);
наличие встроенного API.
Установка OWASP Nettacker
Nettacker является кроссплатформенным ПО, однако проще всего запустить утилиту в контейнере Docker. Для этого на сервере, где установлен Docker, достаточно выполнить команду:
docker run -it –name nettacker –rm owasp/nettacker /bin/bash
Для проверки корректности запуска утилиты, выполняем команду:
python3 nettacker.py -h
Использование OWASP Nettacker
Благодаря большому количеству встроенных модулей, Nettacker можно использовать для различных сценариев, среди которых можно выделить следующие:
сбор сведений о веб-сайте;
сканирование на наличие открытых портов;
обнаружение новых хостов;
поиск ПО, которое использует веб-сайт.
Разберём работу основных модулей. В качестве атакующей цели можно использовать как доменное имя, так и IP-адрес. Также в процессе сканирования можно использовать 2 и более модуля одновременно. Для этого их необходимо разделить запятыми.
Сканер портов
Функционал для сканирования на наличие открытых портов эквивалентен функционалу программы Nmap. Для того чтобы просканировать веб-сайт geeksforgeeks.org, необходимо выполнить команду:
python3 nettacker.py -i geeksforgeeks.org -m port_scan
В выводе отобразилась таблица, которая содержит в себе дату и время начала сканирования (столбец date), цель (target), используемый модуль (module_name), а также вывод самого модуля. В данном случае мы использовали модуль port_scan, который обнаружил открытые порты на сервере (столбец port).
Nettacker поддерживает следующие форматы для задания сканируемых объектов:
IP-адрес — 192.168.1.1;
диапазон IP-адресов — 192.168.1.1-192.168.255.255;
подсеть — 192.168.1.0/24;
доменное имя — test.com;
URL — http://test.com https://test.com.
Также можно задать необходимые адреса в файле и передать данный файл на сканирование. Для этого используется ключ -l. Создадим обычный текстовый файл с именем addresses без расширения со следующим содержимым:
owasp.org
testhtml5.vulnweb.com
testaspnet.vulnweb.com
Передадим данный файл в качестве цели для сканирования открытых портов:
python3 nettacker.py -l addresses -m port_scan
Можно просканировать только конкретные порты. По умолчанию Nettacker сканирует весь диапазон портов, которые заранее прописаны. Чтобы уменьшить время сканирования, можно задать только конкретные порты, используя ключ -g, например, 80 и 22:
python3 nettacker.py -i geeksforgeeks.org -m port_scan -g 80,22
Поиск поддоменов
В Nettacker присутствует отдельный модуль для поиска поддоменов. Для этого используется команда:
python3 nettacker.py -i owasp.org -m subdomain_scan
Сбор информации о веб-сайте
В Nettacker присутствуют модули для поиска различной информации о веб-сайте. Разберём некоторые из них:
admin_scan — сканирует на наличие таких директорий как /admin /cmsadmin /wp-admin и так далее..
python3 nettacker.py -i domain1-test.ru -m admin_scan
Как можно заметить, модуль обнаружил на сайте такие директории, как /administration.html /administration.php /administrator /administrator/account.asp /administrator/account.php
pma_scan — проверяет на наличие страницы (phpmyadmin) для входа на phpMyAdmin:
python3 nettacker.py -i domain1-test.ru -m pma_scan
При сканировании была найдена страница со входом на phpMyAdmin (см. скриншот выше).
wordpress_version_scan — определяет версию WordPress (применимо к сайтам, которые используют WordPress в качестве CMS):
python3 nettacker.py -i domain1-test.ru -m wordpress_version_scan
Была найдена версия WordPress под номером 5.1.17.
wp_plugin_scan — сканирует сайт на наличие используемых плагинов WordPress (применимо к сайтам, которые используют WordPress в качестве CMS):
python3 nettacker.py -i domain1-test.ru -m wp_plugin_scan
В примере выше были найдены 2 плагина WordPress — nextgen-gallery и contact-from-7.
x_powered_by_vuln — проверяет заголовок X-Powered-By на наличие в нем информации об используемом программном обеспечении веб-сайта:
python3 nettacker.py -i flynow.vn -s -m port_scan,x_powered_by_vuln
Как можно увидеть, в последнем столбце в качестве значения в заголовке X-Powered-By используется Nginx.
Создание отчетов
После каждого сканирования Nettacker создает отчет, который по умолчанию сохраняется в usr/src/owaspnettacker/.data/results/ и в формате .html:
Отчет состоит из двух частей — интерактивного графа:
Его можно перемещать, чтобы увидеть карту действий сканера:
В конце отчета располагается таблица, в которой представлены результаты:
В столбце json_event можно узнать более подробную информацию об отправленном запросе:
Также в качестве форматов для отчета поддерживаются форматы csv и json. Для того чтобы сохранить отчет под новым именем и в новом формате, необходимо использовать ключ -o, например:
python3 nettacker.py -i owasp.org -m admin_scan -o results.csv
Сгенерированный отчет будет сохранен в текущей директории, из которой была запущена утилита nettacker. Можно указывать абсолютный (полный) путь, куда будет сохранен файл с отчетом. Также при использовании форматов csv и json в отчетах не будут использоваться графики.
OWASP Nettacker хорошо подходит для сбора информации о требуемом хосте. Благодаря большому количеству поддерживаемых модулей, можно легко находить только нужную информацию.
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
-15% на заказ любого VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
Исследование режима Copy-on-Write в pandas. Часть 3 / Хабр | Веб-студия Nat.od.ua
Исследование режима Copy-on-Write в pandas. Часть 3 / Хабр
Появление в библиотеке pandas режима Copy‑on‑Write (CoW, копирование при записи) — это изменение, нарушающее обратную совместимость, которое окажет некоторое воздействие на существующий код, использующий pandas. Мы разберёмся с тем, как адаптировать код к новым реалиям, сделать так, чтобы он работал бы без ошибок тогда, когда режим CoW будет включён по умолчанию. Сейчас сделать это планируется в версии pandas 3.0, выход которой ожидается в апреле 2024 года. В первом материале из этой серии мы разбирались с особенностями поведения CoW, во втором — говорили об оптимизации производительности, имеющей отношение к новому режиму работы pandas.
Мы планируем добавить в систему «тревожный режим», в котором она будет выдавать предупреждения при выполнении любой операции, поведение которой меняется при включении CoW. Эти предупреждения будут привлекать к себе очень много внимания пользователей, поэтому к возможности их появления стоит относиться с осторожностью. В этом материале рассматриваются некоторые типичные проблемы кода и то, как его можно адаптировать для того чтобы его поведение не изменилось бы после включения CoW.
Цепное присваивание
Цепное присваивание — это такое действие, когда состояние объекта изменяется в ходе выполнения двух последовательных операций.
import pandas as pd
df = pd.DataFrame({“x”: })
df > 1] = 100
Первая операция выбирает столбец «x», а вторая ограничивает количество строк. Существует множество различных комбинаций этих операций (например — в комбинации с loc или iloc). При использовании CoW ни одна из этих комбинаций работать не будет. Попытка их применения приведёт не к молчаливому бездействию системы, к выдаче исключения ChainedAssignmentError, направленного на то, чтобы соответствующие паттерны были бы удалены из кода.
Обычно вместо подобных конструкций можно использовать loc:
df.loc > 1, “x”] = 100
Первое измерение loc всегда соответствует row-indexer. Это означает, что у программиста имеется возможность выбрать подмножество строк. Второе измерение соответствует column-indexer, что позволяет выбрать подмножество строк.
Применение loc обычно позволяет ускорить код в случае, когда нужно задать значения подмножеству строк. Поэтому это позволит сделать код чище и даст улучшение производительности.
Это — очевидный пример ситуации, в которой CoW оказывает влияние на код. Кроме того, CoW влияет и на цепные непосредственные операции с объектом:
df.replace(1, 100)
Тут прослеживается тот же паттерн, что и в предыдущем примере. Первая операция — это выбор столбца. Метод replace пытается работать с временным объектом, в результате чего обновить состояние исходного объекта этому методу не удастся. От подобных паттернов тоже довольно легко избавиться. Делается это путём указания столбцов, с которыми нужно работать.
df = df.replace({“x”: 1}, {“x”: 100})Антипаттерны
В предыдущем материале речь шла о том, как работают механизмы CoW, и о том, как объекты DataFrame совместно используют данные, на которых они основаны. При непосредственной модификации одного из объектов, использующих общие данные, будет выполнено защитное копирование.
df2 = df.reset_index()
df2.iloc = 100
Операция reset_index создаст срез данных, на которых основан объект df. Результат выполнения этой операции присваивается новой переменной — df2. Это означает, что два этих объекта совместно используют одни и те же данные. Это остаётся в силе до тех пор, пока объект df не будет уничтожен в ходе сборки мусора. Операция setitem, в результате, вызовет копирование данных. В этом совершенно нет необходимости в том случае, если программисту больше не нужен исходный объект df. Обычная перезапись значения одной переменной просто сделает недействительной ссылку, которая удерживается объектом.
df = df.reset_index()
df.iloc = 100
Подводя итог, можно сказать, что создание множества ссылок в одном и том же методе приводит к поддержанию в рабочем состоянии ненужных сущностей.
При этом временные ссылки, создаваемые при объединении нескольких методов в цепочку — это вполне нормально.
df = df.reset_index().drop(…)
При таком подходе в рабочем состоянии останется лишь одна ссылка.
Обращение к массиву NumPy, на котором основан объект DataFrame
Сейчас библиотека pandas позволяет обращаться к NumPy‑массивам, на которых основаны датафреймы, пользуясь to_numpy или .values. Возвращённый массив — это копия данных в том случае, если соответствующий DataFrame состоит из данных разных типов. Например:
df = pd.DataFrame({“a”: , “b”: })
df.to_numpy()
Этот объект DataFrame основан на двух массивах, которые необходимо объединить в один. Это вызывает копирование данных.
Другой случай — это когда в основе DataFrame лежит лишь один массив NumPy:
df = pd.DataFrame({“a”: , “b”: })
df.to_numpy()
Тут можно напрямую обратиться к массиву и получить не копию, а срез. Это — гораздо быстрее, чем копирование всех данных. Теперь можно работать с массивом NumPy и, в принципе, можно непосредственно модифицировать его элементы, что приведёт и к изменению и исходного объекта DataFrame, и тех объектов, которые используют те же данные, что и этот объект. Всё становится гораздо сложнее при применении CoW, так как это означает отсутствие множества защитных копий данных, существовавших ранее. Гораздо больше объектов DataFrame теперь будут совместно использовать одни и те же области памяти.
Из-за этого команды to_numpy и .values будут возвращать массивы, предназначенные только для чтения. Это значит, что в получившиеся массивы нельзя будет записывать данные.
df = pd.DataFrame({“a”: , “b”: })
arr = df.to_numpy()
arr = 1
Эта конструкция вызовет исключение ValueError:
ValueError: assignment destination is read-only
Избежать этой проблемы можно двумя способами:
Вручную инициировать копирование в том случае, если нужно избежать изменения объектов DataFrame, которые совместно используют память, хранящую массив.
Сделать массив пригодным для записи. Это решение отличается лучшей производительностью, но оно обходит правила CoW, поэтому им следует пользоваться с осторожностью.
arr.flags.writeable = True
В некоторых ситуациях это невозможно. Один из типичных случаев — это когда обращаются к отдельному столбцу, который основа на PyArrow:
ser = pd.Series(, dtype=”int64”)
arr = ser.to_numpy()
arr.flags.writeable = True
В результате выполнения такого кода будет выдано исключение ValueError:
ValueError: cannot set WRITEABLE flag to True of this array
Массивы Arrow иммутабельны, в результате тут нельзя сделать так, чтобы в массив NumPy можно было бы записывать данные. В данном случае переход от Arrow к NumPy — это пример операции, где копирования данных не происходит.
Итоги
Мы рассмотрели наиболее серьёзные изменения pandas, связанные с режимом Copy‑on‑Write. Этот режим станет стандартным в pandas 3.0. Мы, кроме того, поговорили о том, как можно адаптировать код к особенностям CoW, сделать так, чтобы включение этого режима не нарушило бы работу программ. Если вы сможете избежать антипаттернов, описанных в этом материале, это значит, что вы без проблем обновитесь до версии pandas, в которой режим копирования при записи будет включён по умолчанию.
О, а приходите к нам работать? 🤗 💰
Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.
Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь.
Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.
Присоединяйтесь к нашей команде
PHP и Laravel дайджест новостей за октябрь 2023 года / Хабр | Веб-студия Nat.od.ua
PHP и Laravel дайджест новостей за октябрь 2023 года / Хабр
Всем привет! Краткий обзор новостей из мира PHP и Laravel за октябрь 2023 г.
PHP Дайджест
Вышли PHP 8.1.25 и PHP 8.2.12
В этих выпусках несколько исправлений ошибок и улучшений в модулях Core, CLI, CType, DOM, Fileinfo, Filter, Hash, Intl, MySQLnd, Opcache, PCRE, SimpleXML, Streams, XML и XSL.
Вышел пятый релиз кандидат PHP 8.3.0
Очередной релиз-кандидат вышел в соответствии с графиком. Шестой RC ожидается 9 ноября и станет последним перед финальным релизом PHP 8.3.
Подробный список того, что появится в PHP 8.3, можно найти на сайтах php.watch или stitcher.io.
SjonHortensius/phpshell стал публичным
Репозиторий phpshell, на базе которого работает сайт 3v4l.org стал общедоступен.
Symfony исполнилось 18 лет
18 октября 2005 года был сделан первый публичный коммит проекта Symfony.
Открыта программа раннего доступа PhpStorm 2023.2
В первой версии EAP улучшена поддержка PHP 8.3, добавлен мастер создания новых проектов для Symfony и поддержку преобразования аннотаций Doctrine в атрибуты.
Ядро PHP
Большинство новостей ядра PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:
📣RFC: Rounding Integers as int
На данный момент функции округления round, ceil и floor возвращают число с плавающей точкой, но при использовании целых чисел выше 2^53 получаются неожиданные результаты из-за потери точности. Marc Bennewitz предлагает выполнять округление для заданного целого числа и возвращать полученное целое число, если это возможно.
📣RFC: Unbundle ext/imap, ext/pspell, ext/oci8, and ext/PDO_OCI
Derick Rethans предлагает удалить модули из ядра PHP и перенести в репозиторий PECL.
📣RFC: Multibyte for trim function mb_trim, mb_ltrim and mb_rtrim
Yuya Hamada предлагает добавить многобайтовую поддержку для функций обрезки.
📣RFC: RFC1867 for non-POST HTTP
RFC1867 определяет тип контента multipart/form-data. PHP поддерживает анализ этого типа контента, но только для POST-запросов. Если осуществляется POST-запрос и тип содержимого multipart/form-data, тело запроса немедленно обрабатывается перед запуском PHP-скрипта и заполняется в суперглобальные переменные $_POST и $_FILES. Эта функция запускается автоматически и не предоставляется непосредственно пользователю.
Ilija Tovilo предлагает добавить новую функцию request_parse_body(), чтобы вывести существующую функциональность на пользовательский уровень и использовать ее для других HTTP-методов.
📣RFC: Change the edge case of round()
Saki Takamachi предлагает изменить поведение функции round в крайних случаях и перестать ожидать от чисел с плавающей точкой десятичного поведения и начать ожидать, что числа с плавающей точкой будут вести себя как числа с плавающей точкой.
✅RFC: Increasing the default BCrypt cost
RFC о котором мы говорили в прошлом выпуске принят единогласно. Большинством голосов было принято, что в PHP 8.4 значение cost по умолчанию будет увеличено до 12.
✅RFC: A new JIT implementation based on IR Framework
Ещё один RFC из прошлого выпуска также принят единогласно в обоих голосованиях: в PHP 8.4 появится новая реализация JIT, тем временем старая реализация будет удалена.
Laravel дайджестLaravel дайджестОбновления Laravel
В этом месяце вышло три релиза (10.26 – 10.28). Они большие, но в основном это фиксы – где-то что-то поправили – в док-блоках, в аннотациях и добавили тесты. В Git workflow обновили Git auto-commit action с четвертой на пятую версию.
10.26. Vendor::Publish prompt
Взглянем на поиск в команде vender::publish. Бывает, что в огромном списке нужно выбрать определённую цифру и указать, что именно из vendor service provider необходимо опубликовать. Теперь есть vendor publish с новым Laravel Prompt, где появился поиск. Теперь быстро можно найти что нам требуется и сразу опубликовать все необходимые файлы от vendor service provider. С таким поиском передавать опцию с namespace провайдера больше не надо.
10.26. Route::List -vv option
Прокачали artisan команду Route::list. Появилась опция -vv, которая выведет развёрнутую информацию по применённым к роутам мидлварам.
Artisan.page
Вышел проект по Artisan-командам в Laravel. На нём собраны все Artisan команды и все возможные опции и аргументы которые у них есть. Многих из них нет в официальной документации, а на этом сайте есть! Реализована удобная навигация. Для тех, кто любит быстро и удобно что-то генерировать в одну команду.
Видео версия дайджеста:
Запуск альфа-теста Капибара(Новый Старый Пикабу) | Веб-студия Nat.od.ua
Запуск альфа-теста Капибара(Новый Старый Пикабу)
Продолжу рассказывать о развитии Капибары, опенсорсном проекте, цели которого воспроизвести лучшее что было на пикабу и не наступить на их же “грабли”. Первая часть здесь: https://habr.com/ru/articles/759598/
Пару недель назад у нас стартанул полу-закрытый альфа-тест. Сейчас выдаём ранний доступ на сайт kapi.bar отважным авторам-альфатестировщикам и активным комментаторам взамен просим слать нам багрепорты и пока быть самим себе модераторами. Функционал для создания постов, комментариев и выставления оценок для них есть. Ленты “Новое”, “Тренды”, “Топ”, “Обсуждаемое” и поиск по тегам уже работают и доступны для чтения всем желающим.
Теперь об обновлениях за последние пару недель:
📸 Изображения
Теперь на сайте Капибары пользователи могут загружать изображения в посты и комментарии! Так же доступна загрузка изображений в формате apng, gif размером до 5мегабайт. Каждое загруженное изображение конвертируется на стороне бэкенда в формат webp для оптимального отображения и снижения нагрузки на инфраструктуру.
Читать далее
Как наложить макет на вёрстку через PerfectPixel / Хабр | Веб-студия Nat.od.ua
Как наложить макет на вёрстку через PerfectPixel / Хабр
Привет! Меня зовут Сергей Криворучко, я работаю наставником на курсе «Фронтенд-разработчик» в Практикуме. Иногда у студентов возникают сложности с PerfectPixel — расширением Chrome, совмещающим макет из Figma с вёрсткой в браузере.
В этом материале я расскажу, как корректно экспортировать макет, установить PerfectPixel, управлять расширением и находить элементы страницы, которые стоит поправить на вёрстке. Для примера взял макет, с которым работают студенты на курсе.
Экспортируем макет из Figma
Откройте нужный макет и выделите его полностью — удостоверьтесь, что в меню слева выделились все разделы страницы, а в окне Preview также видны все элементы.
Переключите Figma в режим разработчика, чтобы посмотреть ширину макета. В нашем примере она составляет 1 440 пикселей.
Удостоверьтесь, что в разделе Export установлен масштаб «1x» и нажмите на Export. Знание ширины макета нам ещё пригодится, поэтому я назвал файл «1440.png».
Устанавливаем PerfectPixel
Установите расширение со страницы в интернет-магазине Chrome. Чтобы PerfectPixel отображался в панели инструментов, нажмите на иконку «Расширения» и активируйте «скрепочку» возле нужного плагина.
Импортируем изображение макета в PerfectPixel
Если вы работаете со страницей, сохранённой на вашем компьютере, то можете получить уведомление о необходимости предоставить доступ к локальным файлам. Для этого перейдите на страницу «Управление расширениями», найдите кнопку «Сведения» у PerfectPixel и установите флажок напротив «Разрешать открывать локальные файлы по ссылкам».
«Глазик» в окне расширения включает и отключает отображение макета на странице. «Замочек» фиксирует его в выбранном положении. А последняя кнопка активирует режим инверсии, в котором макет и вёрстка накладываются друг на друга с помощью вычитания — если они совпадут полностью, получится просто серая картинка.
Откройте расширение и подключите экспортированное изображение по кнопке «Добавьте ваш первый слой». Чтобы совместить макет с вёрсткой, установите масштаб «1.0» в окне расширения.
Перейдите в «Инструменты разработчика», включите мобильный режим и введите ширину — в нашем случае это «1440».
Совместите макет с вёрсткой, перетаскивая его мышью. Более детально настроить положение изображения можно стрелочками в расширении. И не забывайте нажать «замочек», чтобы при скроллинге страницы настройки не сбивались.
Проверяем соответствие вёрстки макету и вносим изменения в код страницы
Возможно, вы увидите некоторые отклонения. Например, в начертании шрифтов или переносе строк. Это нормально, потому что отображение текста в браузере и Figma может различаться, мы этим не управляем.
Но если произошли заметные отклонения, например, в отступах между абзацами, их стоит поправить. Для этого выберите нужный элемент и посмотрите его свойства в «Инструментах разработчика».
В нашем случае неверный отступ появился из-за неотстроенного «гэпа» между блоками текста. Чтобы найти верное значение, нужно подбирать разные варианты (можно увеличивать или уменьшать отступ стрелочками), пока вёрстка и макет не совпадут.
После можно скопировать установленный стиль и перенести его в исходный файл в вашем редакторе.
Как работать с PerfectPixel: видеоинструкция
Если в каких-то моментах инструкция показалась недостаточно наглядной, посмотрите видеоинструкцию — за восемь минут я проделываю тот же путь от экспорта макета до внесения изменений в вёрстку.