БАГодельня
2.23K subscribers
190 photos
1 video
127 links
Канал про разработку и безопасность: код, костыли, разбор задач, ревью и размышления.

Вещает руководитель отдела разработки: @ipatove
Download Telegram
Бегущий в лабиринте

📖 Мы редко делаем проекты, которые заканчиваются после запуска. Сделал, зарелизил и забыл – это только для коротких промоакций, которые сами по себе живут несколько месяцев. А любой сервис или сайт, всегда растет вместе с бизнесом заказчика, меняется и подстраивается под новые реалии. Это актуально как для e-commerce, каталогов и витрин, так и просто корпоративных сайтов, а про функциональные сервисы уже и говорить нечего, они без остановки дорабатываются и растут.

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

Это не из вредности или глупости разработчиков и заказчиков. Такой жизненный цикл у проекта и его кода – нельзя запланировать на 5 лет вперед всю структуру и четко придерживаться плана, всегда что-то меняется на ходу, из-за чего и появляются «нестандартные» решения.

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

Про один такой инструмент я и хотел рассказать, но пост получился совсем о другом – «что такое долгий проект и почему в нем появляются костыли». Описание уже не влезет, лимит по символам для телеграма загоняет в рамки. Поэтому продолжу в следующем посте завтра.

⁉️ Это инструмент для фронтендеров – хранение и передача знаний в интерактивном виде. Есть идеи что это может быть?

#Мысли
👍92
Storybook – коллекция компонентов интерфейса

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

Уже давно были мысли, что нужно все систематизировать и каталогизировать, даже на фронте. Но кроме простых заметок в гуглдок или ридми репозитория, ничего дельного не приходило в голову. Но примерно год назад случайно наткнулся в лекции от фронтов Яндекса на название инструмента Storybook. Полезли смотреть – выглядит круто и очень удобно. Это коллекция компонентов проекта, со всеми описаниями и возможностью в интерактивном режиме покрутить свойства этих компонентов.

Начали пробовать использовать – в одну сборку засунули, во вторую, в статичную, на vue 2, потом на vue 3. Пока экспериментировали, собрали все возможные шишки, но оно того стоило. Сейчас в работе проект с фронтом на vue 3, на нем уже полноценно используется сторибук, как обязательный шаг на этапах верстки.

Много попутных преимущество находится по мере внедрения storybook. Можно сверяться с дизайнерским ui-kit и корректировать друг друга. Удобно тестировать компоненты – видны все состояния и все возможные свойства. И пока нет готовой верстки проекта или даже ни одной страницы, то уже что-то можно демонстрировать заказчику: небольшие кусочки, которые сверстаны и отлажены.

❗️ Для примера – ссылка на наш сторибук из последнего проекта, который еще в работе: ссылка на компонент.

#Мысли
👍7
Доработка сайта в файлах кеша

📖 Года 3 или 4 назад был у нас небольшой заказ по микродоработкам сайта на CMS OpenCart. Правки совсем простенькие – обновить текста, картинки и чуток перестроить фильтры в каталоге. Трафика на сайте толком не было, а принимать решение – брать проект на долгую в работу или нет, планировали после изучения кода. Поэтому делать тестовый сайт не стали, контроль версий тоже не настраивали сходу. Ну и решили совместить изучение проекта, вместе с выполнением первых доработок.

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

Прошло два-три дня, и заказчик попросил еще одну правку мелку внести. Но уже по логике, тогда полез покопаться уже программист поопытней. Доработал логику, сбросил кеш CMS, чтобы обновились отрендеринные вьюхи. И тут сюрприз – каталог сайта упал, а все изменения, что делали первым заходом, пропали.

📌 Начали разбираться. Оказалось, что молодой специалист половину задач сделал в файлах кеша. Как можно было залезть в папку с именем cache и там копаться в файлах, имена которых состоят их хешей, до сих пор остается загадкой. И самое интересное, что часть логики была реализована в файлах кеша, а часть в обычных файлах. Из-за этого и сломался каталог, после сброса кеша для всего сайта.

Хотел найти пруфов – скринов переписок с путями к файлам кеша, но не удалось. Видимо уже голосом обсуждали, что случилось. Сохранились только переписки с предположениями о проблеме.

#Юмор
🤣12😁3👍1
Заполнение задачного чек-листа из чата телеграм

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

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

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

📌 Чтобы было меньше «потеряшек», а больше структурированных вводных и комментариев, решили использовать телеграм и его ботов. К каждому чату по проекту привязали задачу в тасктрекере. А бота научили реагировать на команды при ответе на сообщение. То есть на любое сообщение в общем чате, можно ответить с текстом команды для бота. Пока тестируем добавление в чеклисты и комментарии к задачам. Так каждый комментарий за 3 сек фиксируется в тасктрекере и уже не потеряется.

Помимо тасктрекере, можно использовать, например, гугл таблицы, если в них удобней обрабатывать поток мелочей. Нам проще и удобней хранить в тасктрекере – redmine, он уже прилично доработан под внутренние процессы, и обзавелся дополнительными api и модулями, которые писали себя.

❗️Если интересно развитие этого бота, дайте знать – через реакции и комментарии. Буду тогда приводить сводки раз в 1-2 недели: что получилось добавить или наоборот убрать по функционалу, почему так сделано и какой профит от всего этого.

#Кейсы
👍19
Массовая оптимизация картинок сервисом TinyPNG

Полное описание приложения выкладывал на канале пару месяцев назад: посмотреть.

📖 Вкратце для тех, кто не в курсе: это скрипт для массовой оптимизации картинок с помощью сервиса TinyPNG. Работает через api и имеет преимущества перед браузерной версией: нет лимита 5 Мб на один файл, нет лимита в 20 одновременных обработок файлов. К тому же приложение забирает картинки из любой структуры папок и выстраивает такую же вложенность после обработки – не нужно руками растаскивать по папкам.

При работе с сервисом TinyPNG по api, кроме плюсов, есть и ограничение – 500 обработок картинок в месяц для одного бесплатного аккаунта. При необходимости можно докупить или менять аккаунты. Мне лимита хватает на месяц и в бесплатном тарифе – на скрине график. Но после того, как первый раз опубликовал приложение, им стали активно пользоваться и не все влезают в эти лимиты. За октябрь несколько человек писали в ЛС, что вылетают ошибки у приложения. Сегодня еще раз прислали эту ошибку. Значит, пора исправлять.

📌 Добавил в работу скрипта проверки на доступные лимиты и корректность ключа api.
Обновленные билды можно скачать тут:
– Под Windows: скачать.
– Под MacOs: скачать.
И инструкция по эксплуатации: читать.

❗️Благодарю, за обратную связь, которую присылаете в ЛС. Без нее бы не скоро выловили такую проблему. Если еще есть какие-то предложения или вопросы, всегда готов их обсудить. Можно в комментариях к постам или в ЛС.

#НашиРазработки
👍8
Примеры обработки изображений с помощью ImageMagick

📖 ImageMagick – набор программ для обработки графики. Под разные языки программирования есть библиотеки, с помощью которых можно работать с этими программами. Но кроме обращения из кода, так же иногда удобно и из консоли что-то по-быстрому обработать «в ручном режиме» или написать bash-скрипт с вызовом этих команд. Примеры самых ходовых команд покажу в этом посте. Но сперва нужно установить ImageMagick, скачать под любую ОС можно на официальном сайте: ссылка.

Конвертация формата изображений:
magick test.png test-new.jpg

Нарезать картинку на кусочки размером 200x200.
Создаст файлы с именем test-new-0.png, где 0 - номер кусочка, начиная с верхнего левого края. Последний индекс – нижний правый угол.
magick test.png -crop 200x200 test-new.png

Вырезать из картинки кусок размером 200x200, со смещением по X 100 и Y на 50 пикселей:
magick test.png -crop 200x200+100+50 test-new-crop.png

Вырезать кусок картинки по пропорции – взять 50% ширины и 100% высоты, начиная от верхнего левого края(+0+0):
magick test.png -crop 50%x100%+0+0 test-new-crop-50.png

Ресайз картинки с сохранением пропорции(по меньшей стороне):
magick test.png -resize 400x200 test-resize.png

Ресайз картинки с сохранением пропорции(по большей стороне):
magick test.png -resize 400x200^ test-resize-2.png

Можно комбинировать запросы, используя набор модификаторов. Например, кроп с ресайзом:
magick test.png -crop 200x200+100+50 -resize 400x400^ test-crop-resize.png

❗️ Примеры, которые привел – это только то, чем чаще всего приходится пользоваться. И это только малая часть возможностей ImageMagick. Полное описание всех возможностей можно посмотреть тут: ссылка.

#БазаЗнаний
👍10
Код ревью названий сущностей

📖 Примечание для лучшего понимания поста, тем, кто не знаком с php или фреймворком laravel. В php фреймворке Laravel есть встроенный планировщик задач, который называется schedule: документация. Этот планировщик имеет свои команды для вызова, свое настраиваемое расписание, классы и методы для работы с ним.

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

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

🔴 Также в этом названии не хватает уточнения, что это за расписание(Schedule). Такое общее имя можно задать только для глобальных настроек расписания, но никак не для конкретного куска логи. В данном случае должно быть уточнение про отчеты – ScheduleReports. Тогда уже и связь с планировщиком от фреймворка не такая прямая. Но лучше использовать синоним, например, TimingReports.

❗️Если резюмировать, то пост умещается в одно предложение: название сущностей, должно четко соответствовать их назначению, чтобы не вводить в заблуждение.

#КодРевью
👍10
Грейды разработчиков

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

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

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

📌 Получается такая градация:
Стажер – учится писать код.
Джун – научился писать код, но оттачивает навыки и учится декомпозировать задачи, тренируется задавать вопросы по вводным.
Мидл – оттачивает навыки, учится оценивать риски и прогнозировать сроки, предлагать оптимизацию и варианты решения.
Сеньор – оттачивает навыки и отвечает головой за свои задачи.
Тимлид – оттачивает навыки и отвечает ж#пой за свои задачи и всех гавриков из списка выше.

❗️Это черновик рангов, только суть. Жду ваших мнений в комментариях.

#Мысли
👍10😁3🥴1
Ревью условной конструкции. Switch...case против elseif

📖 На скрине коммит, где видна первая и исправленная версии кода. Это простенький кусок, без больших ветвлений, но как пример то, что нужно. Логика на скрине не важна, а только условие. Точнее вариант реализации условия.
Первое исполнение – удаленный красный код, строился на конструкции if…elseif (else if с пробелом тоже самое). А новая реализация после ревью – зеленый код, условие описано конструкцией switch...case.

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

📌 Оба подхода жизнеспособны и могут использоваться в разработке. Но на мой взгляд, если появилась необходимость добавить к условию (if…else) еще один вариант elseif, то это повод задуматься над куском кода, который сейчас пишите. Условия должны быть максимально простыми – если -> то -> иначе. Когда не получается вписать код в рамки такого ветвления, значит явно начинаются дебри. И даже если все заработает, то последующие доработки, будут происходить со скрипом, а сам код станет сложным и не очевидным.

❗️Но если по-другому уже совсем никак не удается вписать решение в простое условие и требуется описать больше двух вариантов событий, то switch...case справляется лучше, делая код прозрачнее и понятнее.

#КодРевью
👍8
Топ публикаций за месяц

📖 Ежемесячная рубрика с 5 самыми популярными статьями за месяц.
В подборку попадают публикации за прошлый месяц, по количеству реакция плюс количество пересылок в личные сообщения или группы – за каждое действие по одному баллу.

📌 Топ 5 постов за октябрь

1️⃣Трудный первый рабочий день
Рубрика #Юмор

2️⃣PDF-принтер для сайтов
Рубрика #НашиРазработки

3️⃣Мониторинг температуры и CO2 в офисе
Рубрика #Кейсы

4️⃣Фикс фикса или ревью коммитов
Рубрика #КодРевью

5️⃣Заполнение задачного чек-листа из чата телеграм
Рубрика #Кейсы

#Топ5Месяца
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥91
«Жирный» сервис – ошибочка в проектировании

📖 В прошлом году мы начали разрабатывать внутренний сервис для одного из заказчиков. Сервис закрытый, им пользуются только сотрудники – автоматизация рабочих процессов и хранилище информации. Сейчас проект потихоньку превращается в CRM, со своими задачами отчетами и тд. Но когда к нам пришли с задачей, первичный запрос совсем не объяснял и никак не предвещал такой большой структуры. Все, что требовалось – это автоматизировать расчеты стоимости работ, простенький аналог гугловой таблицы. Заказчик не раскрыл или сам не знал свои планы, а мы не уточнили наводящими вопросами. Недооценили масштаб.

На первых итерациях разработки сервиса нужно было сделать раздел для генерации коммерческого предложения – КП. Он как лендос: текст, картинки, видео. Условный конструктор. Но контента много и каждый раз чтобы не заполнять основу, сделали первично заполненные шаблоны. Их можно скопировать и отредактировать под нового клиента. Когда делали копирование, не подумав, реализовали полное копирование файлов. Это казалось хорошей идеей – полностью разделить оригиналы и копии. Причем копии файлов делали физические. А в каждом КП 4-5 десятков картинок в хорошем качестве и десяток видео.

В итоге менеджеры делают полную копию КП каждый раз. И за год таких копий получилось приличное количество. Сервис стал весить 113 Гб. Это много, учитывая, что 99% этого объема занимает контент для КП. И по большей части все файлы являются дублями.

Пришлось полностью переписать логику хранения контента для КП и скрипты для удаления дублей. После отработки скриптов, которые ищут, мержут и удаляют дубли, оказалось, что из 18919 файлов только 326 уникальных. А вес всего сервиса уменьшился со 113 Гб до 15 Гб. Такие дела, 98 Гб было занято мусором – копиями. Сервис внутренний и пользуется им десяток человек, а 100 Гб им удалось заполнить примерно за 8-9 месяцев.

❗️ Описание новой реализации и алгоритма поиска дублей уже не влезает. Если интересно продолжение – дайте знать, допишу следующими постами.

#Юмор
👍21
Ключ от всех дверей

📖 Иногда с сервисов и сайтов приходят жалобы от пользователей, что где-то что-то не работает. Но выловить и повторить ошибку никак не удается. Часто это связанно с персональными настройками или заказами. Удобнее и проще всего отловить такие проблемы, если авторизоваться под пользователем, от которого было обращение.

Не всегда есть реализованный функционал авторизации под конкретным пользователем. Из CMS встречал такое только в Битриксе, а в кастомных разработках на подобные фичи постоянно нет времени. Остается только сброс пароля, поскольку в открытом виде в базе доступы не хранятся, а дешифрации хеш пароля не поддается. Но это плохой вариант. Мало того, что у пользователя что-то сломалось, так ему и пароль еще обновили.

📌 В таких ситуациях есть два варианта решения – временно подменить в БД хеш пользователя на заранее известный, авторизоваться под этим паролем и вернуть хеш на место. Однако на время подмены, может случиться ситуация, что пользователь будет авторизовываться и его будет ждать сообщение о неверно введенном пароле. Маловероятный сценарий, но возможный.
Есть второй вариант – подменить пользователя при авторизации или сразу создать сессию для конкретного пользователя.
Например, в Битриксе это можно сделать одной строкой:
$USER->Authorize($user_id); 

Не сложней и в wordpress:
wp_set_auth_cookie($user_id);

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

Такими трюками можно пользоваться и для авторизации под админом, когда потерялся пароль к админке или заказчик предоставил доступ только к серверу.

❗️Пару раз приходили мысли сделать универсальный скрипт для такой авторизации под ходовые CMS и типовые авторизации во фреймворках, но вовремя остановился – есть вероятность, что кто-нибудь забудет этот файл на сервере и на сайте останется «дыра», даже если сам скрипт закрыть дополнительной basic auth или каким-либо еще доступом. Поэтому каждый раз подобные авторизации делаем заново и сразу удаляем.

#Кейсы
👍13
Сравнение скорости работы if…else и switch…case

📖 Пару дней назад писал пост про условные конструкции if…else и switch…case. В нем рассматривалось удобство и читаемость кода, и упомянул, что непонятно какой из блоков работает быстрее. Но в комментариях @Zizibob прислал примеры кода на C++, C# и Python, в которых происходит измерение скорости работы. Спасибо ему за это!

Результаты интересные – обе условные конструкции примерно одинаково быстро отрабатывают. Причем в коде на C++ switch…case чуточку быстрее, а в коде на C# наоборот if...else побеждает по скорости.

Для чистоты эксперимента и в рамках развлечения, переписали код еще на несколько языков. Чтобы проверка была максимально точная, алгоритм не менялся, а только переводился на другие языки, не меняя конструкции и способа измерения. Измерения на PHP, Go, Node.js, JavaScript, Ruby дают одинаковый результат – switch…case хоть и совсем немного, но работает быстрее, чем if…else. А вот Bash удивил, в нем switch...case отрабатывает ровно в два раза быстрее, чем if...else. Ну и еще один неожиданный поворот – код на Visual Basic сам по себе отработал очень быстро, а так же конструкция if...else опережает switch...case по скорости.

📌 Примеры кода, на разных языках программирования, можно посмотреть в онлайн-сервисе, который позволяет сразу запустить код и проверить результаты:
– Код на C++(победил switch…case): ссылка
– Код на C#(победил if…else): ссылка
– Код на Python(победил switch…case): ссылка
– Код на PHP(победил switch…case): ссылка
– Код на Go(победил switch…case): ссылка
– Код на JS(победил switch…case): ссылка
– Код на Ruby(победил switch…case): ссылка
– Код на Bash(победил switch…case в два раза): ссылка
– Код на VB(победил if…else): ссылка

❗️Из девяти проверенных языков, только в C# и Visual Basic побеждает if…else.
Если у кого-то есть замечания или комментарии по способу замера скорости или варианты замеров на других языках программирования – присылайте в комментарии, будем разбираться вместе.

#КодРевью
👍16❤‍🔥1
Форма слова в зависимости от числа

📖 В красивых и удобных интерфейсах важна каждая мелочь. Из них строится общее восприятие сервиса, сайт, приложения и тд. На мелочевку не обращаешь внимание, когда она отлажена, но когда есть «косячки», то они сразу бросаются в глаза и портят всю картину. Где-то отступ поехал, где-то размер кнопки выбивается из общих размеров, курсор не меняется на «руку» над интерактивным элементов или с текстами проблема – опечатка, кривая формулировка и тд.

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

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

📌 Вводная часть затянулась. Теперь к делу😁
Одной из таких мелочей является склонение слов, которые являются приписками к числам. Например, если выводить возраст, то он может иметь три разные формы: 1 год, 2 года и 5 лет. Такие склонения нужно обрабатывать перед выводом. Ситуации бывают разные, поэтому важно иметь заготовку кода как для фронта, так и для бекенда.

❗️ Примеры залиты в сервис, где можно посмотреть код и выполнить его:
– PHP: ссылка
– JS: ссылка

#БазаЗнаний
👍7❤‍🔥1🔥1
Дубли логики в сложном условии

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

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

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

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

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

#КодРевью
👍9
Ответственность за свою работу

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

Брать такой проект всегда страшновато. Это черный ящик, в котором может быть что угодно. Да и просто так от прошлых разработчиков не уходят, очень часто причиной является то, что качество или сроки перестали устраивать. Если дело только в сроках, то есть надежда на хороший код. Но если проблема в качестве, то явно «под капотом» что-то не так, даже если заказчик, не имея компетенций оценить реализацию, стал замечать проблемы.

Недавно пришел такой новый проект. Первой задачей нужно было привести в порядок корзину и оформление заказа. Посмотрев код бекенда, стало сходу понятно, что проще переписать, чем править существующее. Все выкидывать не стали, чтобы лишнее время не тратить – задача срочная. Но процентов 20-30 логики бекенда написали по-новой. И по первичным оценкам времени, такой вариант оказался быстрее. И главное, безопаснее. Поскольку правки существовавшей каши в коде могли потянуть за собой еще кучу дополнительных правок.
А вот на фронте решили внести правки в существующий код. Это была ошибка. Провозились полтора дня, потом все выкинули и за пол дня сделали заново.

📌 После таких проектов появляются вопросы. Как вообще можно продавать свои услуги, если они настолько не качественные? Как можно сдавать задачи, если там совсем мусор, который не работает? Как живется и на сколько крепко спиться после такого подхода к своей работе? Это неуважение в первую очередь к себе и ремеслу, которым занимаешься. У меня в голове не укладывается, как настолько наплевательски можно относиться к своей работе. И это не единичный случай. Это печально.

❗️Вспомнился монолог полицейского из русского фильма «Изображая жертву».
Осторожно! Видео 18+, с нецензурными выражениями: 📹смотреть.

#Мысли
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141❤‍🔥1🤔1
CodeReview. Проблема N+1

📖 Давно ждал в коде такой ошибки, название нравится – «Проблема N+1». Шутка, конечно, не надо так делать. Когда-нибудь мне нечего будет выкладывать в группу на тему код ревью, а все задачи будут готовы к релизу с первого подхода, но только не сегодня.

«Проблема N+1» – это ошибка производительности при выполнении запросов к базе данных, когда происходит N запросов для получения основных данных и еще один дополнительный запрос для каждой связанной записи, что приводит к возникновению N+1 запросов.

📌 На скрине в верхней части над красной чертой приведет исходный код, где есть эта проблема. Логика отработает и все данные будут верные. Но, с увеличением количества записей в таблицах БД, скрипт будет работать все медленнее и медленнее, пока совсем не перестанет работать и начнет выкидывать таймауты. В исходной реализации первой строкой происходит запрос к одной таблице, а потом в цикле происходят еще запросы к другой таблице для поиска связанных записей.

🔴 «Лечится» такая проблема с помощью связей и join-ов в запросах. В нижней части скрина приведет исправленный код. Логика тут написана на php фреймворке Laravel, который использует ORM. Но в итоге запрос будет вот таким, если писать его на чистом SQL:
SELECT *
FROM tbl_1
LEFT JOIN tbl_2
ON tbl_1.tbl_2_id = tbl_2.id


🔴 Кроме проблемы N+1, тут еще есть странный момент. Заметил, когда уже писал пост. Зачем-то из базы выгребаются вообще все данные, без каких-либо условий и лимитов. Такие запросы могут так же серьезно сказаться на нагрузке, ведь в БД может быть больше количество данных. И вряд ли они нужны все сразу.

#КодРевью
👍11
Как не нужно дебажить

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

Поиски проблем в коде ни к чему не привели, логов нет, а проблема падений оставалась. Время от времени сайт просто сыпался и выдавал 500ю ошибку. А если страницу перезагрузить, то все приходило в норму, как ни в чем не бывало. Самое неприятное, что ошибку не получалось воспроизвести – полный рандом. Но ошибкой точно есть: заказчик присылал скриншоты и сами поймали пару раз.

📌 Чтобы локализовать проблему, включили логирование ошибок и предупреждений в php. Включили, походили по сайту – все число в логах. Но и падений не случается – ошибок нет. Решили оставить сайт в покое и подождать пока логи что-нибудь не поймают.

Через пару дней позвонил заказчик – сайт совсем упал. Раньше хоть перезагрузка страницы помогала, а теперь полностью лег и не встает. Побежали разбираться. Выяснили, что сайт кидает 500ю из-за нехватки места на жестком диске. И причиной является наш лог с ошибками, который насобирал эрорров и варнингов аж на 10-12Гб, забил все место и тем самым положил сайт.

Логи почистили, сайт подняли и начали искать откуда такое количество ошибок в журнале. Оказалось, что туда все предупреждения записываются, а на одной из страниц была не критическая ошибка, но код вызывался в цикле. Так за 1.5-2 дня этот код сгенерировал больше 10Гб логов и уложил сайт окончательно.

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

#Юмор
👍22🔥1😁1
Лимиты размера файлов в ботах telegram

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

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

📌 Несколько дней ломали голову, как быть. А потом нашли, что у телеграм есть открытые исходники сервера для локальной разработки: ссылка. Их можно сбилдить и запустить локально, и отправлять запросы к api. Работает, как и обычные сервера телеграм, даже синхронизация переписок есть. Но в локального сервера есть преимущество – лимит по весу файлов там уже 2 Гб. Это именно то, что нужно. Дальше дело техники: накатили и сбилдили исходники у себя на сервере, прицепили к порту домен и стали использовать вместо телеграмовских серверов – все апи и хуки бота работают через наш сервер.
И приятный бонус – исходники можно дописывать под себя. Сервер написан на Си, с ним не работаем, но по мелочам в ознакомительных целях доработали одну апи.

❗️ Исходники сервера и инструкция по установке: ссылка.
И важный момент: при переключении хуков на свой сервер, нужно не забыть отвязать хуки бота от серверов телеграм, чтобы не было дублей запросов.

#Кейсы
🔥11👍31
Pinger – альфа-версия проверяльщика сайтов

📖 Я уже рассказывал (Пинг и SSL), что у нас есть бот, который проверяет работу клиентских сайтов, где нельзя или нет ресурсов, чтобы развернуть полноценную систему мониторинга. Это внутренний инструмент, а управление им происходит через конфиг. К тому же на него еще куча других внутренних метрик завязаны. Поэтому бота не показывал, только скринами и описанием.

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

Однако плотно занявшись телеграм-ботами, снова вернулась идея, только уже не в виде сайта или сервиса, а бота. Причем бот не только для уведомлений, но и для управления настройками. В итоге основную логику мониторингов написали на Go, а бота, который заменяет интерфейс, на Node.js.

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

📌 Итак, что умеет бот:
– Принимает сайты и ставит их в очередь на проверку
– Показывает список всех сайтов, которые добавлены
– Каждую минуту проверяет http-ответ сайта. И если случилась беда, то отправляет об этом сообщение
– Если сайт «упал», то так же наблюдает за ним. И когда сайт снова станет доступен, пришлет об этом уведомление
– Проверяет дату SSL и уведомляет за 7 дней до завершения
– Проверяет дату оплаты домена и уведомляет за 7 дней до завершения

❗️Ссылка на альфа-версию бота: @OWL_Pinger_Bot.
Очень важна обратная связь! Если интересно, то пишите в ЛС или в комментарии.

#НашиРазработки
🔥8👍5
Изменение php.ini для версии 7.4 и выше

📖 Начиная с версии PHP 5.3, появился FPM – менеджер процессов для php, он оптимизирует и ускорят работу. Но до 7й версии толком не использовался, возможно, это связано с отладкой оптимизации. А вот начиная с версии PHP 7.4, сам по себе php уже не умеет работать, только вместе с fpm.

Регулярно попадаются вопросы на stackoverflow, которые напрямую связаны с FPM. Вероятно, не все знают про этот менеджер процессов. И пытаются управлять настройками PHP по старинке, через конфиги Apache в .htaccess. Но когда процессами PHP начал управлять FPM, веб-сервер уже не может изменять параметры из конфига php.ini.

Раньше, до версии php 7.4 для обновления условной директивы upload_max_filesize, отвечающей за максимальный объем файла, который можно передать по http с помощью POST-запроса, достаточно было обновить .htaccess на серверах Apache. И тогда php бы поменял свои настройки. Сейчас такие фокусы уже не проходят.

📌 Теперь везде, начиная с версии php 7.4, а на некоторых серверах, где и раньше начали использовать FPM, для обновления директив PHP, нужно редактировать непосредственно конфиг php.ini. После чего, нужно перезапуускать службу FPM.

Чтобы было понятней, приведу полный маршрут обновления конфига php, на примере версии 7.4. Самой частой проблемой бывает, как раз лимит размера файла, который нужно передать на сервер. Для этого нужно обновить директивы upload_max_filesize – отвечает за лимиты передаваемых по http файлов методом post и post_max_size – отвечает за максимальный размер всего post-запроса, а не только файлов. Поэтому post_max_size не может быть меньше, чем upload_max_filesize.

📌 По шагам, команды в консоле:
– Сперва нужно найти расположение php.ini. Это можно сделать командой:
php --ini

– Редактируем upload_max_filesize и post_max_size на нужный размер. Например, 20M – 20 Мб. По умолчанию там 5 Мб.
– После сохранения php.ini достаточно перезапустить только службу FPM. Вот так:
service php7.4-fpm restart


Перезапускать Apache или Nginx не нужно.

#БазаЗнаний
👍7