Увидел сейчас отличное выражение: «код как шутка — если его приходится объяснять, то это плохой код»
Отличный принцип, как по мне
Автор: dd
-
Код как шутка
-
Осторожно, простыня!
За последние 2 месяца у начальства компании развился серьёзный интерес к разделению бэка и фронта. Не знаю с чем это конкретно было связано, но надеюсь я в этом сыграл не последнюю роль
Так как фронтом теперь занимаются отдельные люди, я подумал, а почему бы и в бэке не привнести существенные изменения? например, сменить фреймворк🤡
Звучит смешно и слишком радикально, однако я так просто от этой идеи отказываться не захотел и попросил дать мне шанс испытатьsymfony, сделав небольшой проект (реально небольшой — одна апи точка + одна страница для отображения хранимых данных)
Естественно, я убил на этот проект в 3 раза больше времени, чем если бы делал наyii2, но я для себя много чего нового узнал
Например,symfony— это очень удобно, это разделение всего и вся на компоненты, это грамотно, но это ОЧЕНЬ медленно
Я взял 2 демо-проекта,yii2иsymfony, развернул их и начал закидывать запросами через утилитуhey. В итоге оказалось, чтоyii2до 5 раз быстрее при запросе обычной странички, которая выводитhello, $_GET['name']. Понятно, что я не могу прийти на собрание и сказать — давайте-ка перейдём на новый фреймворк, он в 5 раз медленнее, но удобство разработки в разы выше. Меня просто засмеют — я пока не привил должного отношения к хорошему коду в компании.
Но это дало повод задуматься — что я могу стащить изsymfony, чтобы получить скоростьyii2и удобствоsymfony?
Самое очевидное удобство, которое бросается в глаза в первый час разработки — валидация на атрибутах. При чём не на старющих аннотациях через комментарии, а на нормальных, уже нативных вphpатрибутах.
Подумано — сделано. За полтора часа накидал систему валидации и простецкие валидаторы, типаnot null,equalsи тд. Написал тест, сравнивающий нативную валидациюyii2и самописную. Не знаю, чего я ждал, но получил, что моя реализация в 7 раз быстрее нативной. Я не знаю что творится за кулисами валидаторов вyii2и уже не хочу выяснять.
На этом однако процесс не остановился — я часто пишу апи, часто пишу консольные команды. Все они должны быть транзакционными от и до, и в лог должно падать сколько время каждый процесс занял. Это огромная куча кода, который постоянно дублируется. Выход? 2 простых атрибута —#[Timed]и#[Transactional]. Вешая их на любой экшен я теперь получаю весь нужный мне функционал, не тратя ни капли сил.
Следующий шаг логичен как ничто другое — вынести всё это дело в композер-пакеты и использовать их в текущих проектах. Это заняло около часа может, не более, но я по итогу в проектах занимаюсь нужными вещами, а не написанием бойлерплейтов, получаю чистейшие исходники, которые не заляпаны кучей дублирования и читаются как книга. Детский восторг и всё такое.Выводы очень простые:
1. Просите давать вам возможность пробовать что-то совершенно новое в обмен на опыт и обучение коллег. Это может быть фреймворк, может быть язык, может быть новая БД (я смотрю на тебя,SurrealDB), что угодно — важен факт обучения и познания.
2. Что-то понравилось? Тащите себе в проект, адаптируйте, расширяйте функционал. Это бесценный опыт, который в итоге упростит жизнь вам и вашим коллегам.
3. Атрибуты — огонь -
REST, который не совсем REST
Сегодня я узнал, что то, что все называет rest api на самом деле даже близко не rest; теперь у вас тоже есть инструмент душнилы😃
https://htmx.org/essays/how-did-rest-come-to-mean-the-opposite-of-rest/
-
Некоторые интересные и полезные вещи
1. Плагин для PHPStorm, добавляющий много разных проверок по качеству кода: https://plugins.jetbrains.com/plugin/7622-php-inspections-ea-extended-
На что мне плагин открыл глаза:
— В функцию in_array нужно передавать третьим параметром true, чтобы сравнение элементов было строгим (===), без приведения типов (==)
— Анонимные функции/замыкания необходимо всегда объявлять статическими, не делая этого только в крайне необходимых случаях: https://habr.com/ru/post/561550/
— В юнит-тестах вместо assertTrue($cond1 === $cond2) можно использовать assertSame($cond1, $cond2)
— Не стоит использовать array_merge внутри циклов. Однако, решения этой проблеме не указано. Я заменил на$output = […$output, …$arrayToMerge];Подробнее: https://chemaclass.medium.com/never-use-array-merge-in-a-loop-74917b056ff9
— Модификаторы abstract/final идут перед модификаторами области видимости: https://www.php-fig.org/psr/psr-12/
— Приведение типов через (int)/(bool)/etc до 2 раз быстрее, чем аналогичные функции приведения intval/boolval/etc: https://stackoverflow.com/a/35949025/5320740
— Вместо базового класса Exception лучше кидать RuntimeException
— Void в качестве типа возврата функции лучше, чем его отсутствие2. Была задача скачать и обработать 30 гигабайтный файл с одного государственного ресурса
Соединение обрывалось примерно на 25-30 процентах завершённости
Начал думать что делать и решением в лоб оказалось пытаться скачать файл несколько раз, при этом передавая в curl сдвиг
Пример реализации тут: https://gist.github.com/ndunks/778c7efad0956e0f99deae73c52e718fОсталось его только распаковать. В памяти, естественно, это всё не поместится, поэтому я использовал файловые потоки, чтобы по кускам вытаскивать данные из архива в отдельную папку. Пример реализации тут: https://stackoverflow.com/a/8102667/5320740
-
Спор про ORM и DTO
Недавно на реддите натолкнулся на заминусованный комментарий, в котором автор яростно пишет о том, какая ORM плохая технология
Мне стало интересно что он может предложить в ответ и почему с ним так много несогласных
По итогу он скинул ссылки на 2 статьи, которые по-моему заслуживают прочтения:
1. https://www.yegor256.com/2014/12/01/orm-offensive-anti-pattern.html
2. https://www.yegor256.com/2016/07/26/active-record.htmlВся суть статей сводится к тому, что использование объектов-данных (DTO) в связке с ORM — зло и вообще грубое нарушение принципов ООП
По мнению автора статей объект должен сам знать о подлежащей структуре в хранилище и должен сам им управлять
И тогда возникает много вопросов: чем же это отличается от ActiveRecord или паттерна Repository? И куда помещать методы с бизнес-логикой? Кто мешает в DTO хранить бизнес-логику?
Ни на один вопрос я пока ответа в статье или комментариях к статье не нашёл, нашёл только несогласных с постом, например: http://disq.us/p/1v8un8uСоглашаться или нет — решать вам, но как минимум послушать и услышать такую точку зрения точно надо, потому что она идёт вразрез со стандартом индустрии
P.S. в комментариях на реддите мне подсказали, что этот паттерн называется DataAccessObject, если хотите дальше в эту углубиться
-
Nginx как reverse proxy для нескольких проектов
На этом же проекте пришлось овладеть навыками "продвинутой" конфигурации нгинкса
Было принято решение накатить нгинкс в режиме реверс прокси для того чтобы размещать больше одного проекта на сервере
В каждом проекте не один контейнер и поэтому нгинкс проекта тоже нужно настраивать и в режиме реверс-прокси
Итого имеем:
1. Запрос приходит на железный сервер
2. Нгинкс по server_name определяет в какой проект направить запрос
3. Контейнер с нгинксом этого проекта определяет в какую часть проекта направить запрос (статика, админка, апи, фронт)
4. Нужный контейнер делает свою работу и возвращает результат
Звучит просто (оно собственно и есть просто), но сложным моментом было связать это всё с абсолютно неинтуитивной системой урлов в yii2, когда нужно было в нескольких разных местах и конфигах прописать базовый урл для каждого проекта (/admin для админки, /api для апи, и тд)
Тут наверное надо бы поднять вопрос поддоменов, потому что это бы сильно всё упростило, но начальство пока против, буду дальше думать над аргументацией🙂 -
Запуск проекта на новом стеке
Пару недель назад наконец-то запустил проект, разработкой которого занимался с нуля
Решил пойти вразрез с привычными в компании технологиями:
1. Вместо железного сервера для хостинга был выбран докер
2. Вместо мускула взят постгрес
3. На фронте работает реакт (разраб, покажись)
4. На бэке php8.1 + yii2 (тут конечно хотелось бы симфони, но пока не дорос)
Запуск прошёл не прям так, чтобы гладко, но пионером в новом стеке быть не просто
В течение недели устраняли мелкие баги, но по итогу имеем проект, который разворачивается за 10 секунд где и как угодно (при наличии докера) и в котором фронт наконец-то (впервые для этой компании) отвязан от бэка
Плюсов маловато, но надо ли больше?
Наш сисадмин в процессе развёртывания даже не участвовал, только сервак создал отдельный для проектов на докере
Мы не потратили ни секунды на натягивание вёрстки на данные, как это было раньше во всех проектах (на одном из которых я так потерял 30 часов)
Имеем полностью документированное апи для фронта, чтобы не задавать лишних вопросов бэкендеру
Вдовесок ко всему этому мы с фронтом умудрились seo и sitemap подтянуть к этом сайту, чтобы наш отдел продвижения не ругался, что сайт не индексируетсяНе бойтесь пинать своих ПМов и начальство в направлении использования адекватных современных технологий, вам же потом от этого легче и лучше будет
-
Деструктуризация массива в цикле PHP
Сегодня листал сводку по новостям php и наткнулся на пакет для упрощения работы с циклами, основанном на функционале питона
Однако, самым интересным для меня в этом пакете оказались примеры использования, а конкретнее вот этот: https://github.com/markrogoyski/itertools-php#zip
Оказывается, можно проводить деструктурирование массива в объявлении цикла! Вроде бы очень очевидный функционал, но ни разу не видел такого
Сразу же вспомнил около десятка циклов, в которых можно это использовать, чтобы сделать код чище и красивее -
Дочитан «Совершенный код»
Я не думал, что этот день когда-то настанет, но я наконец-то дочитал «совершенный код» Макконнелла, это заняло у меня 4 месяца почти
Но я теперь с уверенностью могу сказать, что эту книгу обязан прочитать каждый и что по мере ее прочтения я становился лучше с каждой страницей
Не могу выделить какие-то отдельные главы, потому что для меня как для молодого разработчика полезным было всё
10/10, советую
-
Что такое контейнеры на самом деле
Прекрасная статья о том, что такое контейнеры в линуксе и что на самом деле из себя представляет докер: