Chulakov Dev – Telegram
Chulakov Dev
1.15K subscribers
140 photos
5 videos
205 links
Канал команды разработки Студии Олега Чулакова.

Советы по Frontend- и Backend-разработке web-сервисов, мобильных приложений, статьи и презентации от наших разработчиков, анонсы проектов и многое другое.

Обсудить проект @YuraAndreev
Download Telegram
​​Кубическая кривая Безье и SVG

Использовать кубическую кривую Безье можно и в SVG. Например, если нужно быстро нарисовать в интерфейсе какой-нибудь график или простую иконку.

Создать такую линию можно с помощью команды C, в которую нужно передать координаты точек P1, P2 и P3:
<path d="M x0, y0 C x1, y1, x2, y2, x3, y3" />

Пример использования:
codepen.io/OlegChulakovStudio/pen/zWLQYL
Кубическая кривая Безье и canvas

Аналогично можно нарисовать такую линию и в canvas. Для этого нужно воспользоваться функцией bezierCurveTo, которая доступна в рамках 2D-контекста:
context.bezierCurveTo(x1, y1, x2, y2, x3, y3)

Пример использования:
codepen.io/OlegChulakovStudio/pen/pLqOXz

О других возможностях 2D-контекста canvas можно узнать из нашей интерактивной презентации.
Базовые принципы защиты

В этой заметке мы рассмотрим базовые принципы защиты, которые помогут избежать серьезных проблем с безопасностью на вашем сайте. К потенциальным уязвимостям относятся SQL-инъекции и XSS-атаки.

Принцип №1: проверка корректности ввода обязательно должна осуществляться и в backend-части web-приложения. Часто разработчик допускает очевидную ошибку, оставляя валидацию вводимых данных только на стороне браузера. В современных фреймворках такого рода проверка и фильтрация обеспечиваются на уровне модели данных или на уровне middleware-сервисов. Так, например, Yii2 Framework поддерживает множество стандартных валидаторов, а также позволяет реализовывать кастомные механизмы проверки данных.

Принцип №2: работа с SQL-запросами в БД должна производиться с подготовленными на предыдущем этапе данными. Любые входные данные для любого SQL-предложения должны быть типизированы на уровне PDO-типов, а их вставка в SQL должна производиться с помощью переменных привязки.

Принцип №3: препроцессинг вывода. При выводе данных в HTML необходимо также обрабатывать данные. Если вы выводите plain-текст, то необходимо использовать функцию языка htmlspecialchars, а если вы выводите html, например, введенный пользователем через визуальный редактор, то необходимо использовть более сложный механизм обработки выходных данных. Например, HTML Purifier. К счастью, современные фреймворки также включают в себя хелперы и компоненты для этого. Например, Yii2 содержит метод encode в хелпере Html-detail) для вывода plain-text. Для вывода html в Yii2 реализован хелпер yii\helpers\HtmlPurifier, который достаточно легко настраивается под нужды разработчика.
Yii2 FileStorage

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

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

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

Для фреймворка Yii2 мы разработали компонент FileStorage, который реализует большинство необходимых задач:
1) загрузку файлов из различных источников (например, из POST-запроса или по URL-адресу);
2) централизованное хранение оригинальных и измененных файлов с привязкой к объектам моделей данных;
3) получение расширенной информации о загружаемом или загруженном ранее файле;
4) API для добавления, получения и удаления файлов с автоматизацией очистки кэша модификаций;
5) разграничение доступа к загруженным файлам на основе взаимодействия с системой аутентификации Yii2;
6) основные операции над изображениями: различные методы ресайза, наложение водяных знаков, генерация thumbnail-изображений и т.д.

В репозитории доступна подробная инструкция по установке и настройке компонента, а также примеры его использования.
Listeners

В прошлой заметке мы рассказали о нашем компоненте Yii2 FileStorage.

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

Слушатель подписывается на нужное ему событие и может совершать необходимые дополнительные операции. Например, для поля загрузки изображения формы можно добавить логику ресайза изображения до нужного размера, наложить вотермарк, добавить правила доступа и многое другое.

Для файлов изображений доступны два базовых слушателя:
1) ImageManager — производит изменение оригинального файла изображения, при этом оригинал изображения не сохраняется. Действует как фильтр: какое бы изображение ни загрузил пользователь, оно будет приведено к нужному формату;
2) ThumbsManager — генератор превью для загружаемого изображения с удобными конфигурационными настройками.

Основными источниками событий являются загрузчики файлов. Они легко расширяемы и позволяют загружать файлы из различных источников. Например, из архива, удаленного сервера по прямой ссылке или BLOB-значения БД.

Мы реализовали три базовых источника:
1) UploadedFile — реализует получение файла при загрузке формы методом POST;
2) RemoteUplodedFile — получение файла по прямой ссылке;
3) LocalUploadedFile — получение файла из локальных ресурсов сервера.
Вращение в canvas

В 2D-контексте canvas есть функция rotate, работа которой ставит в тупик многих, кто пытается ей воспользоваться. Объекты, отрисованные после вызова этой функции, поворачиваются на указанный в ней угол. Однако есть одна сложность: вращение выполняется не относительно центра объекта, как в CSS, а относительно начала координат всего холста.

То есть, если отрисовать прямоугольник в центре холста, то опорной точкой вращения будет верхний левый угол всего canvas-а.

Чтобы выполнить вращение вокруг нужной точки, нужно сместить к ней начало координат с помощью функции translate и разместить новый объект с соответствующим сдвигом:
context.translate(originX, originY);
context.rotate(angle);
context.fillRect(x - originX, y - originY, width, height);


Пример с вращением прямоугольника относительно его центра:
codepen.io/OlegChulakovStudio/pen/NMxMzv
Channel name was changed to «Chulakov Dev»
Silence is gold, but not for us

После затяжного перерыва мы решили вернуться в эфир.

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

Стартуем в первой половине сентября.
Я тебя по IP вычислю

Современое веб-приложение с геотаргетированным контентом стремится автоматически определить ваш регион или город.

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

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

Взаимодействие с внешним продуктом по http-соединению является медленным и не обеспечивает должной надежности. Необходимо выбирать те сервисы, которые предоставляют возможность получать базы геоданных полностью и работать с ними локально. Тогда такие БД можно будет обновлять в фоновом режиме по расписанию, запрашивая их у вендора.

На базе сервиса SypexGeo мы разработали компонент для Yii Framework, упрощающий работу с геоданными посетителей сайтов в backend-окружении.
Mobile интересует?

Наряду со сложными интеграциями и разработкой веб-сервисов Студия активно развивает направление нативной мобильной разработки для ОС iOS и Android.

Мы привыкли делиться опытом, и нам важно ваше мнение.

Стоит ли публиковать заметки по Mobile Dev в этом канале или завести отдельный? 🤔
Разреши узнать, где ты

В предыдущей заметке мы рассмотрели возможность получения геоданных пользователя по IP-адресу на стороне сервера.

С помощью нативных средств HTML5 на стороне клиентского приложения тоже можно работать с геолокацией пользователя.

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

Если такое поведение приемлемо, то работать с геоданными в JavaScript можно через метод getCurrentPosition() свойства geolocation объекта navigator.

API предусматривает тонкую конфигурацию запроса с целью повлиять на его производительность. Управлять можно приоритетом точности options.enableHighAccuracy, кешированием определенных ранее геоданных options.maximumAge и максимальным временем выполнения запроса options.timeout.

Пример работы с API можно посмотреть в сниппете.
Окружай себя правильно
#frontend #reactjs #nodejs

Недавно мы получили frontend-приложение на React.js для оценки трудозатрат по расширению его функциональности. Для того чтобы запустить полученный сервис, нам пришлось модифицировать код. Всему виной — отсутствие механизма работы с переменными окружения.

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

К переменным окружения относятся порты, на которых будет запущено приложение или URL-адрес RESTful-сервиса. Значения этих параметров могут отличаться для разных сред, например, для тестового стенда и боевого сервера.

В проектах мы выделяем такие переменные в .env-файлы. А чтобы упростить процесс развертывания и ничего не потерять, в репозиторий проекта укладывается файл .env.example. Он содержит перечень всех переменных окружения для текущего проекта. Файл .env создается путем копирования .env.example и не находится под контролем git.

Для конфигурации react-приложений можно использовать npm-пакет dotenv.
CDN или нет — вот в чем вопрос
#frontend #react #nextjs

При масштабировании frontend-приложений на фреймворке Next.js нам часто приходится размещать статические файлы сборки на CDN-ресурсах. К таким файлам относятся бандлы JS/CSS и элементы дизайна в виде медиафайлов.

В Next.js предусмотрен стандартный механизм управления адресом хранения статических файлов приложения. Через параметр assetPrefix можно задать префикс, который будет использован при формировании пути к ассетам. Установить значение параметра можно в файле next.config.js.

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

Для тестового окружения переменная среды ASSET_PREFIX в .env-файле будет пустой, а для промышленного — будет содержать URL-адрес CDN-сервиса.

Например, в Stylus можно использовать префиксы при формировании адресов таким образом.

А в компонентах переменная окружения будет доступна из свойства env объекта process.

Пример конфигурации приложения для работы с различными префиксами, в зависимости от текущего окружения, можно посмотреть в сниппете.
Сколько нужно глаз тестировщику
#qa #frontend

«Я открыл IE 6 на MS Windows XP, и ваш выпадающий список стал невыпадающим» — клиент.

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

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

Для зеркального выполнения действий с функциональными блоками сайта на разных устройствах и браузерах мы используем Browsersync. Это инструмент open source, разработанный на Node.js.

Применение подобных инструментов значительно экономит время тестирования продукта и позволяет не отвлекаться QA-специалисту на выполнение промежуточных действий, таких как обновления страницы или вставка URL-адреса на другом устройстве. Все это влияет на качество продукта в релизе и степень удовлетворенности конечных пользователей, а главное — на настроение заказчика.
​​Настройки без страха и упрека
#backend #db #models #structures

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

Модель данных Entity-Attribute-Value позволяет для любой сущности создавать неограниченное количество свойств и заполнять их значениями нужных типов.

Например, пользователь в разделе «Профиль» может выбрать удобный для него формат даты или запретить показ рекламы на сайте. Тогда настройка «Формат даты и времени» будет иметь тип select — одиночный выбор значения из списка. А параметр «Показывать рекламу» будет хранить значение «Да» или «Нет» и иметь тип boolean. Можно реализовать и другие типы: number, string, text и даже multiselect.

Сложные типы настроек, такие как select и multiselect, имеют предустановленные списки значений, которые хранятся в таблице config_variant. Установленные значения настроек хранятся в таблице config_value. Таблица config содержит информацию об атрибутах сущности, которые представляют собой непосредственные настройки. Для их группировки применяются категории, которые хранятся в таблице config_category.

Для конкретной настройки есть возможность указать классы валидаторов и параметры их конфигурации. Информация о каскаде валидаторов хранится в поле validators и имеет тип JSON.

В некоторых случаях можно пренебречь нормализацией БД в угоду удобства. Как альтернативное решение хранения вариантов выбора можно рассматривать упаковку их в JSON-поле таблицы config.

EAV дает возможность разработчику гибко выстраивать CRUD для управления настройками, соблюдая поддержку целостности данных на уровне СУБД. Такая модель хранения легко ложится в реализацию слоя приложения практически любого современного фреймворка и покрывается абстракциями ORM для удобства работы.
Need for speed
#frontend #css #animation #stylus

Мы давно знаем, как управлять плавностью анимации в CSS. Но бывают ситуации, когда изинг невозможно реализовать по двум точкам на кривой Безье.

Например, необходимо реализовать поведение стрелки спидометра на чистом CSS. Стрелка разгоняется от начального положения до заданного значения и колеблется вокруг него, постепенно замирая.

Динамика движения стрелки описывается функцией с плавным ростом и затухающими колебаниями возле целевого значения. Построить примерный график такой функции можно на клетчатом листе бумаги, рассчитав ее значения для нескольких ключевых точек. По оси x откладывается время анимации от 0 до 100 %, а по оси y — прогресс движения стрелки от 0 до 1.

Построить интерполированный график и получить промежуточные значения координат поможет сервис кубической интерполяции. Чтобы получить достаточное количество точек установим Step X Output, равный 1. Модифицировать график в интерактивном режиме можно с помощью опции «Интерактивный график JSXGraph».

На основе полученных точек можно произвести расчет ключевых кадров с помощью конструкции цикла в препроцессоре Stylus. Поворот стрелки спидометра изменяется свойством transform: rotate().

Готовую анимацию и код ее исполнения можно увидеть здесь.

💡Чтобы не «зашивать» координаты функции в CSS, можно хранить их в отдельном JSON-файле, а затем импортировать в Stylus: points = json('data.json', { hash: true }).
Воркшоп в Студии
#workshop #backend #php #dbms

Студия откроет двери всем желающим посетить наш воркшоп по Backend-разработке 31 октября 2019 в 19:00. Тема мероприятия — «Обработка больших массивов данных». Формат — лайфкодинг с обсуждением происходящего и обменом опыта.

Подробную информацию об ивенте можно найти здесь.

Приходите, будет интересно и полезно.
Когда размер имеет значение
#mobile_native #android #kotlin

Начинающий Android-разработчик рано или поздно сталкивается с задачей определения основных параметров экрана — ширины и высоты. С появлением Apple-подобной «брови» в верхней части дисплея Android-устройств задача стала неочевидной.

Stack Overflow показывает несколько ответов, предполагающих использование двух нативных методов getSize и getMetrics.

У Honor 10 Lite заявленная высота экрана составляет 2340 px, но нативные методы возвращают 2139 px.

Рассмотрим пример вычисления фактического размера экрана Android-устройства.

В методе DisplaySizeGetter.getSize определяется версия используемого SDK и устанавливается опорный тип SdkType. Для каждого типа SdkType определен свой метод getSize с реализацией алгоритма получения размеров в зависимости от версии SDK.
Толстые репозитории
#vcs #git #frontend

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

Тогда сопровождение контента ложится на frontend-разработчиков. Тяжелые изображения, видеофайлы и иные бинарные файлы сохраняются в git-репозитории. Размер репозитория возрастает, скорость его работы замедляется. Облачные сервисы управления VCS начинают умышленно замедлять скорость клонирования/скачивания «толстых» репозиториев.

Существуют различные решения для выделения больших бинарных файлов из репозитория — CDN-сервисы, сервисы хранения статики. Для хранения бинарной статики в Git мы используем Git Large File Storage, который поддерживается на популярных площадках: GitHub, BitBucket, GitLab.

При инициализации Git LFS для указанных типов файлов в репозитории формируются и хранятся ссылки на них. Сами файлы хранятся отдельно и в единственном экземпляре в специальном хранилище.

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

Например, мы хотим хранить все файлы с расширением .jpg в директории public текущего репозитория. Для этого воспользуемся следующими командами:
$ git lfs track public/**/*.jpg
$ git add .gitattributes
$ git commit -m "install Git LFS"
$ git push
Грокаем и мокаем
#mobile_native #android #kotlin

Robert Anson Heinlein «Stranger in a strange land»

В разработке сложных мобильных приложений могут протекать процессы, требующие фиктивных тестовых данных или mock-объектов. Например, процесс написания unit-тестов и запуска их в CI/CD либо демонстрация приложения в demo-режиме, где использование оригинальных источников данных невозможно или нецелесообразно.

Рассмотрим, как произвести подмену модели ViewModel на MockViewModel при реализации demo-режима приложения. Добавим в gradle-файл модуля добавим boolean-переменную, обозначив демо-сборку приложения.

Получение ViewModel во фрагменте выглядит так:
ViewModelProviders.of(yourFragment).get(YourViewModel.class)


Реализуем класс ViewModelHolder, который будет уточнять класс модели ViewModel исходя из используемого режима приложения.

Во всех фрагментах приложения мы можем использовать вызов метода getViewModel класса ViewModelHolder для получения нужной модели.

ViewModelHolder.getViewModel(this,YourViewModel::class.java)


Если описать свою модель MockYourViewModel, наследуя ее от YourViewModel, то в ней необходимо будет переопределить только те методы, которые нужно мокнуть. В gradle можно явно указать, какой тип ViewModel необходимо использовать. А использование BuildConfig.IS_DEMO не будет дублироваться по всему приложению.
Самое время поставить точку
#frontend #debug #react #nodejs

Каждый современный браузер, даже IE, имеет встроенные средства отладки клиентского JavaScript. У Chrome, например, есть инструменты разработчика, которые позволяют расставлять точки останова, выводить отладочную информацию и в режиме реального времени работать с некоторыми объектами js.

У такой отладки есть минусы — вы отлаживаете уже скомпилированный js, например из EcmaScript или TypeScript. Получается, что код пишется на одном языке, а отлаживается — на другом. Иногда удобно сразу исправлять код в момент отладки.

Наши frontend-разработчики используют IDE Visual Studio Code, в которой есть удобные встроенные средства отладки кода 🐞

VS Code позволяет настраивать различные сценарии отладки — можно отлаживать и серверный, и клиентский js.

Для настройки дебагера в VS Code используется файл ./vscode/launch.json. Чтобы мы могли отлаживать браузерный js, понадобится расширение, сопрягающее работу отладчика с браузерами движка Chrome. Для отладки nodejs-кода будем использовать вот это расширение.

Microsoft создала даже сборник рецептов настройки отладчика для различного типа приложений и языков разработки.
Например, для отладки кода на Next.js можно взять за основу вот эту инструкцию (https://github.com/Microsoft/vscode-recipes/tree/master/Next-js) и отлаживать как клиентскую, так и серверную часть вашего приложения. Не забудьте включить source-maps в настройках сборщиков для Dev-режима, чтобы отладчик показывал исходный, а не транспилированный код.

Старайтесь минимизировать использование механизмов псевдоотладки, типа console.log. Отладка в режиме runtime дает вам полностью объективную, живую картину состояния ваших переменных, объектов и текущего хода выполнения. Вы производите отладку внешними средствами, не изменяя свой код, и спите спокойно, не думая о том, что ваши console.log() проявят себя на промышленном сервере или в браузере у конечного пользователя 🙃