dev notes
1.39K subscribers
33 photos
6 videos
189 links
Пишу про Go, Vim, и про то, как я медленно ползу в сторону FAANG.

С предложениями: @junsenpub
Download Telegram
Сегодня будет жарко - ребята из Skyeng будут обсуждать с ребятами из подкаста "Цинковый прод" текущее состояние, перспективы и будущее языка PHP. Будет ли с нами PHP через несколько лет? Что нас ждёт после выхода 8-ой версии?

Ответы на все вопросы будут здесь - https://www.youtube.com/watch?v=QrlWrFILjMk
​Перевёл статью - Redux в 30 строчек на PHP

Если хочешь узнать, как работает Redux под капотом, поработать с callable-функциями и написать своё хранилище состояния приложения - го под кат!
​У нас тут в чатике скинули релиз альфы PHP 8.0! Альфа выложена для тестирования, использовать её на боевых проектах категорически не рекомендуется. Тем не менее, если ты, так же как и я, уже хочешь посмотреть на JIT, на комбинированные типы методов, новый синтаксис атрибутов и другие прелести - скачать можно тут.
​От компании к компании узнаёшь всё больше компонентов хорошей разработки. На последнем месте работы я увидел очень интересную вещь - отдел тестирования с грамотным руководителем вполне может нивелировать плохое руководство как в менеджерских решениях, так и в отделах разработки.

Я работал в команде, где был старый легаси-проект. Из-за неверной архитектуры и плохих решений ("ща быстро сделаю, а на следующей неделе -перепишу" - типичный комментарий под 5-ти летним коммитом) каждое изменение могло уронить сайт. Тесная связь модулей, где каждый метод может быть дублирован в другом месте, а контекст вокруг метода не всегда позволяет разобраться что это именно он - основной критерий ошибок. И, как это обычно бывает, бизнесу нужны задачи, времени на рефакторинг или распутывание старого кода тебе никто не даёт.

Именно на таких проектах свою роль начинает играть команда тестирования. Прежде я работал с тестировщиками, но чтобы проект тестировали так слаженно -ещё не видел.
Думаю, полезным будет рассказать этапы тестирования и флоу вокруг тестирования глазами разработчика, потому что как показывает практика - в подавляющем большинстве компаний этому уделяется очень мало внимания.
Первый этап - разворачивание проекта не тестовом стенде. Тестовый стенд - это сервер по окружению повторяющий боевой, но привязанный к определённой ветке. Я, закончив задачу, кидаю PR, PR ревьювится кем-то из команды. В нашем случае это всегда был тимлид, и частенько ревью превращалось в перекрёстное, вкупе с другими разработчиками. После получения апрува - код заливается на ветку, привязанную к тестовому стенду, после чего задача уходит в статус "Тестирование".

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

Закончив тестирование либо будут описаны моменты, которые вызвали вопросы и задача уйдёт на доработку, либо задача будет переведена на выкладку в dev. dev - это среда, почти дублирующая боевую, за исключением пользовательской нагрузки. После выкладки задача тестируется на dev-среде, и после релизится на боевой сервер.

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

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

При этом как бы не требовал бизнес - выкладка массива задач с dev на prod никогда не производилась без окончания тестирования, и к отделу тестировщиков бизнес вопросов не имел - как дотестируем, так и выложим.

Резюмируя, интеграции с отделом тестирования, и написание тестов как таковых играет очень большую роль в больших и сложно-масштабируемых проектах, порой являясь крайним рубежом, определяющим стабильность работы всей системы. Для себя я делаю вывод, что пренебрегать командой тестирования в будущем - никогда не буду, без неё работать тяжело и не весело.
Почти день потратил на настройку xdebug в docker'е. Проблема была в том, что конфиги докера - очень нетипичные, контейнеров очень много и чёрт ногу сломит, что там где.
Большинство статей показывают docker-compose из nginx + php, причём оба Dockerfile'a в 10 строк - конь в вакууме, которого нет на реальных проектах.
В итоге из кучи мануалов по настройке самым верным и простым в реализации оказался этот - https://blog.denisbondar.com/post/phpstorm_docker_xdebug
Кажется, вписать его можно в любую docker-конфигурацию, где есть nginx и php.
Пользуйтесь на здоровье)
Когда-то все мы упали сюда по этой же причине)
Интересный формат, будем посмотреть :)
Forwarded from PHP Digest
Открытое собеседование № 1
Cтрим в четверг, 16 июля, в 17:00 по Москве/Киеву/Минску

https://www.youtube.com/watch?v=FQNd9W3nb3A

Валентин @phpyh и я @phpdigest совместно проведём открытое собеседование с Патриком Фельдешем.

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

Трансляция будет на новом YouTube канале PHP Point — подписывайтесь, чтоб не пропустить следующие проекты.
Ребята из mail перевели отличную статью о том, как golang работает с различными уровнями процессорного кэша - https://habr.com/ru/company/mailru/blog/510200/

По словам Джеки Стюарта, трехкратного чемпиона мира по гонкам Формулы-1, понимание автомобиля помогло ему стать лучшим пилотом: «Гонщику не обязательно быть инженером, но нужен интерес к механике».

Транслируя это правило на понимание работы железа и инструментов, с которыми мы работаем - можно значительно улучшить скорость работы наших программ.
В статье на простых примерах показывается, как хранятся данные в разных кэшах процессора и какие методы оптимизации существуют, чтобы добиться максимальной производительности при работе с кэшем. Лично я с удовольствием прочитал :)
Осенью нас порадует (а порадует ли?) новая версия PHP в стабильном виде. Много интересных RFC, вроде бы всё хорошо, но были моменты, которые мне сразу не понравились. Например - объявление и инициализация свойств класса в конструкторе, о чём я писал выше. Зачем?

Вчера на хабре вышла отличная статья от AlexLeonov - https://habr.com/ru/post/511266/
И заставляет задуматься, а действительно ли это то развитие языка, которое мы хотели? Что думаете по этому поводу?
Нашёл интересную серию уроков по работе Active Record в PHP - https://webshake.ru/oop-v-php-prodvinutyj-kurs/pattern-active-record-v-php

Реализация с нуля показывает, как этот паттерн работает с магическими методами в PHP, где там используется рефлексия и как дойти от сохранения значений в объект до записи их в базу. Вся информация знакомая, но, тем не менее, вспомнить её и повторить - лишним не будет :)

Кому интересно - от прикреплённого урока идём дальше по навигации, и под конец получим что-то похожее на самую базовую работу Eloquent в Laravel. Можно заморочиться и прикрутить билдер запросов, анализ аннотаций и глубже разобраться в том, как этот вид ORM работает.
Хеллоу комрадс! Ай фаунд джаст эн амазинг чанэл вэа а мэн из гугл девелопс а дистрибьютед датабэйс ин го!

А если серьёзно, то чувак возвёл свой акцент в абсолют и стабильно выпускает новые серии в свой многосерийный проект по разработке key-value хранилки на go! Способ подачи, конечно, странноватый, но материал отличный, в русском сегменте такого не найти.

Нет, ну вы только послушайте - https://www.youtube.com/watch?v=oPwGrCoOUdo
Только сейчас узнал что в Symfony есть крутой компонент, позволяющий управлять доступом к общим ресурсам - Lock Component.
Часто бывает, что команда не успевает закончить работу, а менеджер (будь то cron или обёртка в виде supervisor) запускает ещё один экземпляр. Со временем пулл процессов накапливается, и возникает неприятная вещи - взаимные блокировки, утечки памяти и на выходе если и не фаталы, то дубли в базе обеспечены.
Решение - подключаем трейт LockableTrait, и ставим проверку в начале команды:

if (!$this->lock()) {
$output->writeln('The command is already running in another process.');
return Command::SUCCESS;
}

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

В целом Lock Component позволяет использовать различные адаптеры, от Redis'а до семафоров, реализованных в PHP (https://www.php.net/manual/en/book.sem.php). Беру на вооружение :)
Я уже давно не пользуюсь клиентами для GIT и перешёл на работу из командной строки. И сейчас расскажу почему это круто, какие в этом плюсы и опишу пару команд, о которых, как выяснилось, многие не знают.

Привязываться к какому-либо инструменту для работы с системой контроля версий, как по мне, плохой выбор.
Когда я только завёл этот канал - единственный инструмент, который я использовал для работы с git - IDE PHPStorm. Ну а что, удобно: Ctrl + K - открывается окно с изменениями, которые можно одной кнопкой закоммитить. Ctrl + Shift + K - вот и запушили. А потом получилось так, что передо мной оказалась консоль боевого сервера, где не было привычных комбинаций, были локальные изменения, которые нельзя было заливать. pull бросался ошибками, а когда с помощью stackoverflow изменения были закоммичены - выяснилось, что коммит надо отменить, а изменения сохранить. С того момента я решил, что нужно набивать команды из консоли, разбираться в том, что умеет git и через некоторое время понял, какие возможности и удивительную гибкость несёт за собой такой подход.

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

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

1. Многие знают про git log, который отображает ветку коммитов. Например, нужно убедиться, что rebase корректно перенёс твои изменения поверх master'а - git log это отобразит. Так же он отобразит хэши коммитов, авторов и дату изменений. Но мало кто знает про более мощный инструмент - git reflog.
reflog показывает историю комманд, которые ты делал и отображает, сколько действий назад они были выполнены:

  7a9d27f04 (HEAD -> ... HEAD@{0}: commit (amend): ...
f45c7d11b HEAD@{1}: commit (amend): ...
f6745f94a HEAD@{2}: commit (amend): ...
e2b332a3d HEAD@{3}: commit (amend): ...
aa08bbdcc HEAD@{4}: rebase finished: returning to refs/heads/...
aa08bbdcc HEAD@{5}: rebase: ...
d60786481 HEAD@{6}: rebase: ...
889cd8739 (origin/master, origin/HEAD, master) HEAD@{7}: rebase: checko
ut master

Вместо ... названия веток и commit-сообщений. HEAD@{0} - последнее изменение - git commit --amend. Например, что-то сломалось и ты решил откатить изменения, но при этом сохранить файлы. Например - откатим git commit --amend. Для этого выполняем:
git reset --soft HEAD@{4} - откатываемся до того состояния, которые были при HEAD@{4} - до rebase, а флаг --soft позволяет сохранить все изменения.
2. Интерактивный rebase. Иногда нужно схлопнуть несколько коммитов, которые уже ушли в удалённый репозиторий, или, например, поменять сообщение у последнего коммита. Для этого можно использовать git rebase -i.
Например, мы хотим схлопнуть последние 2 коммита в один, и изменить ему сообщение. Для этого делаем:
git rebase -i HEAD~2, где после тильды указываются число коммитов от последнего - HEAD:

  pick d60786481 commit 1 name
pick 7a9d27f04 commit 2 name

# Rebase 889cd8739..7a9d27f04 onto 889cd8739 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.

Сначала идёт описание 2-х коммитов, а ниже, в комментарии, действия, которые мы можем над ними выполнить. Нам нужно выполнить squash, поэтому вместо pick пишем s или squash, сохраняем файл и открывается новый, где можно будет указать новое commit-сообщение. Указываем, сохраняем, профит. Если изменения были локально и не уходили в удалённый репозиторий - можно просто залить. Если уже уходили - то в push перед именем ветки ставим "+" - сокращения флага --force.

3. Интересная вещь - хэши коммитов. Непонимание того, как git отслеживает изменения, ведут к конфликам в коде. Например: у тебя есть dev и master-ветки. Тебе нужно что-то поправить, что уже ушло в master. Логично, что эти же изменения нужно залить и в dev. Бывает, что проще сначала сделать ветку от dev, сделать правку там (допустим, поправить надо конфиг в паре строк), залить в dev. Затем сделать ветку от master, поправить там и залить в master. Вроде бы задача решена, но в следующий раз, когда ты будешь вливать что-то из dev в master, git может начать ругаться, несмотря на то, что код полностью идентичен. Произойдёт это из-за того, что у коммитов не совпадут хеши, а хеши - это одно из условий проверки кода на конфликты. Придётся подтягивать изменения, делать rebase, заливать опять. В таком случае правильный вариант - это сделать изменения в dev, залить. Затем перейти в master, сделать rebase или merge на dev, и залить и туда. И обоих ветках будет одинаковый коммит и в последующем ошибок не возникнет.

git - мощнейший инструмент, и вышеописанные команды - только верхушка айсберга. Если подобный формат разрабора команд и разных фишек - понравится, в последующем буду чаще писать о том, на что способна эта система контроля версий.
В Symfony, начиная с версии 4.2 был добавлен autowiring через аннотацию @ required. Описываем любой публичный не статический метод, ставим над ним @ required, передаём ему аргументы, для типов которых есть сервисы - вуаля.

Но, через боль и слёзы узнал ещё одну вещь: autowiring в родительском классе в Symfony отработает только в том случае, если дочерний класс так же был интегрирован через autowiring. Аннотация @ required позволяет не инициализировать переменные через конструктор, что неочевидно может привести к такой ошибке: где-то создаём объект через new class(), конструктор не ругается (ведь зависимые классы подтягиваются через другой метод). И тут-то возникают ошибки. С одной стороны - это очевидно, так как обычная инициализация не включает никакие механизмы Symfony, упрощающие жизнь. С другой - я попался, теперь буду знать :)
Ночного абстрактного синтаксического дерева вам в ленту!
Нашёл отличный видос, где коротко рассказывают про инструменты статического анализа для PHP - на основе разбиения на лексемы, на основе AST и в добавок множество инструментов, о которых ты не слышал, но которые могут быть интересными.

https://www.youtube.com/watch?v=QJ3pRd4Ua08
Тем временем, JetBrains релизнули второй мажорный релиз PHPStorm в этом году.

Коротко о главном:
- Поддержка union types из PHP8
- Псевдотип false
- Новый движок потока управления
- Улучшения при работе с composer
- PHP_CodeSniffer, PHP CS Fixer и PHP Mess Detector можно запускать через docker compose
- Все команды Symfony, Laravel Artisan, Drupal Drush, WP-CLI и скрипты Composer можно очень быстро запускать в PhpStorm, не открывая терминала
- Функция извлечения подкласса из класса для рефакторинга классов, которым лучше быть быть парой классов
- Полная поддержка пул-реквестов GitHub
- Поддержка OpenAPI

Не коротко о главном:
https://www.jetbrains.com/ru-ru/phpstorm/whatsnew/
0 == "строка" — больше не true

Дожили, у нас отнимают самое дорогое (и слава богу): в PHP 8 нестрогое сравнение больше не будет выдавать тех удивительных результатов, один из которых приведён выше! Об этом сообщает соответствующий принятый RFC. Выдавалось это из-за того, что операнд со строкой приводился к числу, тип операндов не проверялся, и мы получали удивительные баги, если где-то случайно указали == вместо ===.

Ребята с редита жалуются, что если они накатят PHP 8, то их проверка паролей в банковском бэке сломается, и придётся всё исправлять :D Так что, если ты не пишешь бэк для Bank Of Amerika, PHP 8 — правильный выбор.