Pull to refresh

Comments 55

Извините за достаточно оффтопный комментарий, но прям приятно читать статью. И структурированно и прям от "большого к малому" и все как-то по делу. Спасибо.

Класс! Правда по тексту все ждал абзац про решение принести ритуальную жертву Монолиту! ;) Может этого не хватило для ускорения сроков ;)

UFO just landed and posted this here

Если не экономить на кадрах, то такая задача решается быстрее.

Несомненно, если бы с самого начала было больше рук, решили все быстрее. 

Поддерживать тесты - дорого, симфони тоже кстати дорого.

Цена на поддержку тестов кажется оправданной для такого большого проекта.

По цифрам вообще фантастика какая-то, 500000 строчек чего, бизнес-логики?

Так посчитала автоматика при подсчете покрытия тестами. Это без учета наших бандлов, только монолит.

Какие именно уязвимости php 7.2 вас не устроили?

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

UFO just landed and posted this here

Т.е. по вашей логике год на переезд нужно тратить уже с имеющейся уязвимостью? Напоминаю, что 7.4 уже осталась совсем без поддержки, включая security fixes

Решение о поднятии версии принималось без менеджмента?

Какие именно уязвимости php 7.2 вас не устроили?

Этот вопрос меня покоробил с самого начала, но я не нашелся, что на него возразить.

Но вот этот прекрасный комментарий со Stack Overflow, приведенный ниже (мужчина обновляется с 5.3 на 5.5), как раз и является идеальным ответом:

we need to upgrade since AWS will start deprecating TLS 1.0 to S3 services on September. It requires the latest version of aws sdk which is compatible to at least 5.5 php. Since it's urgent we don't have time to recode the application to be compatible to the latest PHP versions.

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

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

Подозреваю что поэтапный переход (Symfony 3->5->6 и PHP 7.2->7.4->8.1) прошел бы быстрее и безболезненнее

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

Возможно, мы бы после первого этапа сделали какие-то выводы и скорректоровали свои планы для следующих этапов.

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

В следующий раз, скорее всего, пойду по поэтапному плану ?

Советую ещё обратить внимание на Mikado Method. Суть достаточно проста: если пытаемся что-то поменять и натыкаемся на блокер, то откатываем изменения назад и фиксим сначала блокер. Потом накатываем изменения обратно. Вроде бы и простая идея, но работает великолепно. Особенно в паре с поэтапным подходом.

Поучительно. По кешированию Doctrine - есть подозрение, что у вас использовался where .. in - родной построитель запросов не умеет корректно транслировать это в запрос, вместо этого прописывает все идентификаторы текстом в сам запрос, от этого плодятся миллионы похожих, но не одинаковых запросов, которые не могут быть эффективно закешированы

Например, если в DI класс описывает интерфейс и у него всего один наследник, в старой Symfony брался именно он. Теперь это считается ошибкой, потому что нужно явно описать интерфейс в yaml-файле

Да вроде так и осталось. По крайней мере мне еще не требовалось прописывать единственную реализацию интерфейса в yaml. Предположу что у вас классы с реализацией лежат в другом месте проекта, а лоадер DI сконфигурирован так, что не видит их.

Либо я неправильно понял проблему.

  • Количество юнит-тестов: ~12 000

  • Покрытие тестами: ~30%

  • При переходе сломалось до 4000 тестов

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

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

Мы используем собственный, самописный движок, который работает одинаково хорошо во всех версиях PHP 5.6+, в том числе и на PHP 8.2.3nts. Если соблюдать все PSR-стандарты плюс здравый смысл, то и проблем не бывает!

Совет: уменьшайте зависимости, не полагайтесь на множество внешних библиотек, если задачу можно легко и просто сделать самому! Тогда и проблем с обновлением будет мало, и проекты будут легковесными.

Спасибо товарищу, который его (движок) нам написал - горя не знаем!.. жаль только, что этот программист уволился в связи с последними событиями...

Ну так получается у вас "движок" написан по стандартам языка PHP 5.6 и вы не используете ни одной новой фичи из поздних версий. Сложно искать на такой код разработчиков.

А то что он запускается на 8.2 это скорее заслуга разработчиков PHP, которые с невероятным упорством тащат поддержку легаси из релиза в релиз.

У вас получается код для разработчиков, а не разработчики для кода. Нормально написанный код будет работать в любой новой версии, так как он не использует "грязных хаков", от которых в основном и уходят с развитием языка. А какая версия php сейчас в моде абсолютно не влияет на бизнес-логику.

Не уверен что возможность типизации скаляров, которая появилась в PHP7, это "грязный хак". А назвать нормальным код, в котором нет типизации, уже сложновато. Работать то он будет, только поддерживать и развивать его будет становиться все дороже и дороже.

Вы мой ответ прочитали, но смысла не поняли, к сожалению

А какая версия php сейчас в моде абсолютно не влияет на бизнес-логику.

В php 5.6 не было Throwable и было много утечек памяти в ядре (хотя вроде в 5.6 большинство как раз подлатали), следовательно надёжное websocket приложение (чат, например), реализовать практически невозможно. Ну или страдать и постоянно перезапускать его.


Или, например, задача по сложным (в т.ч. матричным) вычислениям — без компьютед-шейдеров и/или AVX через FFI в php 7.4 эффективно реализовать простыми силами не получится.


Да кучу примеров можно привести, где реализация чего-либо на "не модной" версии языка просто невозможна без дописывания этой версии языка до функционала более "модной")

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

Новые возможности -- хорошо, но они не мешают апгрейдиться :)

Вы говорите о том, что адекватный код на PHP 5.x запустится и на PHP 8.x. А автор цитаты говорил о любой совместимости, включая обратную. Мол, не надо тащить фичи 8.х, т.к. всё тоже самое можно запилить и на 5ке, которая никак "не влияет на бизнес-логику" (с).


По крайней мере я так понял его комментарий.

Нет, вы поняли не правильно. Там есть специальное слово "новой". Для вас я уточню, что его следует читать как "более новой" ))

Да, перечитал с этими пояснениями — вы правы.

Если бы больше над проектированием языка думали а не за модными фишками гонялись,то не пришлось бы поддержку ленами тащить.

TCL уже сколько лет, а с обратной совместимостью проблем нет. MS в пример приводить не будем, у них ресурсы совсем другие …

А почему просто не начать разбивать монолит на микросервисы постепенно? Обновить пыху чтобы потом все равно отказаться от монолита?

Неспортивно
> Воодушевлённые вызовом, мы взялись за работу и составили план действий:
> 1. Обновляем все бандлы и библиотеки

Это уже было:
> Да взять всё и поделить! (с) Шариков

  • Так как большинство разработчиков должны быть более свободны в это время, мы собрали всех тимлидов, у которых есть ребята, пишущие на PHP, и попросили нам помочь.

В следующий раз зовите и меня тоже. Я в "Яндекс Крауд". Большой опыт работы с PHP.

Ого, огромная работа была проделана, вы молодцы :)

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

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

Когда читал про отмирание подов по cpu раз в 5 часов - сразу понял что это opcache) По поводу опкеша - вы можете сделать прелоад всех файлов при старте контейнера, займёт до полу гига памяти, нагрузка цпу снизится.

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

А меня в яндекс еду не взяли - не умею потоково парсить гигабайтные csv файлы в бд, а потом отдавать через api ручки с пагинацией и без :facepalm:. Самый тупой собес в моей жизни. Но я теперь понял почему чувак спрашивал и про монолиты и микросервисы =)

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

Вот тоже подумалось - а будь все написано на ASP.NET - было бы столько геморроя?

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

Но например был опыт поднятия с версии .NET Core 5 до 6, а затем до 7. Ушло около получаса на каждый сервис.

"На решение этой проблемы я потратил все майские праздники."

Самая грустная строчка в статье :)

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

Планировали 2 месяца, делали 12.ну норм че.а всем в яндексе так можно?

Ну слушайте, у вас никогда не всплывало трудностей, о которых вы понятия не имели, пока не приступили к задаче? Если так, то, вероятно, вы занимаетесь только рутинными, хорошо изученными задачами, но не у всех это так.

Привет от зелёного банка, мы полгода так легаси проект на yii2 с mysql на целевой постгрес. Пыха правда пока 7.4)

Овер 10000 файлов, 7 команд и 1 ночь даунтайма))

о как знакомо

22й год, PHP 7.0, ZF2, PHPUnit 5, кода поменьше, % покрытия тестами примерно такой же

Обновлялись постепенно.
На первом этапе относительно безболезненно сначала phpunit5 -> phpunit6, затем php7.0 -> php7.3 (макс что поддерживает phpunit6). Обновлять сразу и то и то я очканул. В коде правок не было, только тесты (phpunit переехал на неймспейсы).
Затем обновление phpunit6 -> phpunit9 (исправление сигнатур унаследованных методов TestCase и того что стало deprecated типа @expectedExceptionи MockObject\Matcher ) и, судя по логу, безболезненное переключение на php 7.4. После с небольшими, но грязными правками прям в vendor, на php 8.0.

На 8.1 ZF2 сыпал тоннами ошибок ((

Через полгода после предварительной подготовки исходников ZF2 -> ZF3 -> Laminas.
Тут были изменения интерфейсов фабрик и слушателей, избавление от сервислокатора в коде (оставили только в контроллерах), регистрозависимость ключей в сервис локаторе. Отдельная подстава была от zend session, который в сессии хранит \Zend\Stdlib\ArrayObject.

С ужасем прочитал статью. У нас Yii 2.0.45, php7.4+Postgres13.3. На следующей неделе собираемся апгрейдиться на php 8+, времени нам на это дали максимум месяц. Покрытие тестами строк: 65.21% (13408/20561)

Пожелайте нам удачи, пожалуйста

Ну, Yii 2 проблем скорее всего не создаст - там давно фичефриз и очень широкий диапазон поддерживаемых версий PHP.

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

Согласен с тем, что лучше обновлять поэтапно. Каждый этап - это `composer up` + `composer why-not php x.x`. Если есть блокеры - разбираться с ними, потом с кодом проекта.

Удачи.

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

В остальном - в месяц уложились, вместе с тестированием и прохождением стендов. Основной рефактор занял примерно 2 недели работы одного меня. Больше всего времени заняло пройтись по всему проекту и расставить везде проверки на null - в php 8+ теперь нельзя отдавать null в те функции, которые работают со строкой. Их миллион - начиная от json_en(de)code и заканчивая всеми mb_*, str*.

Из минусов - остались без рассчёта процентов покрытия кода тестами - codeception 5 почему-то падает при попытке рассчитать процент покрытия. Не было времени раскурить эту проблему, чуть попозже (после НГ видимо) займёмся. Ну и вообще 5 версия немного отличается по работе, пришлось переписывать кучу тестов.

Без особых проблем переехали на 8.0. Главное, чтобы используемые сторонние либы имели актуальные версии.

Спасибо, что откровенно рассказали. Было интересно почитать, как оно у других проходит.

Свои пять копеек: 190к строк кода (282к строк всего) по данным плагина Statistics для PHPStorm. Каждое обновление занимает 1-2 дня максимум, но мы всегда обновляемся итерационно. Считаю, что обновляться постепенно не только проще, но в итоге и быстрее будет, т.к. меньше надо в голове держать на каждом этапе.

Кстати, интересно, у вас 500к строк именно кода или строк всего? Тут могут быть нюансы, как оказалось )

Если кода, то очень интересно, чего понапихали туда. Со стороны кажется, что бэк для приложения заказа еды не такой уж большой, даже с учетом каких-нибудь админок.

P.S. Количество подключенных пакетов, конечно, фантастическое. У нас всего 41 в require и 9 в require-dev. Laravel.

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

Вот если ничего не исключать

Если исключить все Юнит тесты

Dto и другие вещи которые не нужно отслеживать, я уже исключать не буду.
А что исключили вы? Интересно что бы сравнить.

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

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

чем конкретно вы до этого считали? 

PHPunit + Xdebug - подсчет покрытия кода тестами. В отчете есть данные по количеству строк кода, классов, методов и функций.

При том подсчете мы исключили все что смогли.

Спасибо! Тоже сгенерировал coverage report, и теперь у меня тоже вопросы к плагину Statistics. По отчету phpunit, у нас всего лишь 60k строк. Это без тестов, миграций и всего подобного: только логика.

В любом подсчете, у нас примерно в 8 раз меньше кода получилось. Хотелось бы одним глазком в ваш монолит заглянуть, конечно )

Меня одного напрягает, что авторы поста критикуют стартап, который Яндекс выкупил как потенциального конкурента? Почему нельзя проявить уважение к людям, которые навелосипедили то, что Яндекс захотел купить? Имея дальше для развития ресурсы, критиковать то что было написано в других условиях,как минимум, проявление непрофессионализма. Ребята, у вас другая точка отсчета. Берете бизнес, который выстрелил, делаете его лучше. В идеале тех кто вам подарил работу в виде этого проекта надо благодарить.

Да вроде не было хейта. Все проблемы связаны с апгрейдом, негатива к старому коду и к его разработчикам не видно

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

Подскажите, какой конкретно текст вызвал такое ощущение? Возможно стоит его подкорректировать.

Могу только предположить что вас смутила эта строчка

Это легаси-монолит, доставшийся Яндекс Еде после объединения со стартапом Foodfox

или эта

Монолит написан на PHP 7.2 разработчиками разного уровня и в разное время. Мы подумали, что так больше нельзя, и решили навести порядок.

Но это не про разработчиков, это про объективную реальность
Легаси - означает что код старый и уже нет овнеров кода. Любой код устаревает и становится легаси, и разработчики тут не причем.
Разработчиками разного уровня - это включает как разработчиков стартапа, так и разработчиков уже внутри яндекс еды, и это тоже просто факт без какого-то негативного оттенка.

Sign up to leave a comment.