Однажды ты просыпаешься и понимаешь: избыточность компонентов и рассинхронизация в твоём приложении начинают вредить пользователям. Однажды ты смотришь на написанное давным-давно ядро, плачешь горькими слезами, и приходит это некомфортное, но вместе с тем немного соблазнительное ощущение — что рефакторинг назрел. Добро пожаловать на экскурсию по рефакторингу Музыки, начиная с ресёрча и заканчивая эксплуатацией! Я покажу вам реальный код и постараюсь в деталях вспомнить, как мы формировали требования к механизмам и разрабатывали их, рисовали у себя в голове и в коде границы ядра, по одной переделывали очереди и внедряли то, что получилось, в SDK.

Из чего состоит Музыка


Приложение Музыки — это ансамбль из разных и довольно самостоятельных сущностей. Как и во всяком уважающем себя ансамбле, все его части должны работать сообща. У нас эти части выглядят так:

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

Собственно, как раз плеер, очереди и всё, что связывает эти сущности в единое целое, я и переделывал. Главной проблемой всегда была именно связность, ядро приложения писалось довольно давно (по меркам сервиса), функциональность приложения нарастала внутри него годами, и для адекватного рефакторинга пришлось довольно тщательно всё это распутывать. Все годы, любые требования, которые ровно не укладывались в изначальную реализацию механизма управления воспроизведением, скрупулезно раскладывались по всему приложению, чтобы достичь нужного эффекта. В этом вопросе ни о каких принципах SOLID и архитектуре в целом речи, в общем-то, и не шло. Так часто бывает с God-сущностями, которых все стараются избегать, но всё равно время от времени дописывают.

На схеме изображено далеко не всё, но и без того видно, как сущность раньше была перегружена. Различные условные переходы в каждом методе здесь также не изображены.



А ещё состояние плеера и очередей исторически было рассинхронизировано. Было много гонок. Например, в пульт Алисы или Chromecast (устройство Google, через которое можно транслировать контент на ТВ или умные колонки) мог ненадолго попасть прошлый или следующий трек. Что-то могло криво нарисоваться в UI.

В коде можно было временами встретить что-то такое (упрощено):

combine(queueFlow, playerFlow) { queueState, playerState ->
    if (queueState.current == playerState.playable) {
        Pair(queueState, playerState)
    } else {
        null
    }
}

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

Теперь представьте, что будет, если внести в подобные надёжные решения больше двух переменных… Конечно, изредка wake-lock и вырывался на свободу, вынуждая разработчиков порождать еще больше разных if и synchronized, чтобы загнать его обратно.

У нас был план, и мы его придерживались


Все работы разделилась на три крупных этапа.

Первый этап — исследование и защита проекта


Небольшой оффтоп. Я не случайно называю этот рефакторинг проектом. Уже при первичной оценке объёма работ — на основе того, что знаем, — было понятно, что рефакторинг будет нетривиальным, сопряженным с существенными рисками. Поэтому и подходить к его исполнению нужно было серьезно. Некоторые стандарты по управлению проектами (из того самого PMBOK и не только) всплыли в моей голове. Формировать план проекта с уставом и ТЗ по ГОСТ’у, я, конечно, не собирался, но соблюдение базовых последовательностей показалось весьма полезным.

Итак, образовалась, казалось бы, банальная, но выверенная временем последовательность выполнения: инициализация, планирование, анализ, проектирование, разработка, тестирование, ввод в эксплуатацию.
Всё это не конфликтует (и не должно — just to clarify) с инкрементальным процессом создания ценности, который сформировался в нашей команде.

Начинаем инициализацию.

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

Зафиксировав всё это в виде изначальных требований (с продуктовым уклоном) с горсткой диаграмм, можно было двигаться дальше — выявлять заинтересованных в проекте людей и общаться с ними. К счастью, этот список был в большей степени понятен: разработчики, которым предстоит учиться работать с новым механизмом, тестировщики, которым предстоит новый механизм тестировать, и руководители/менеджеры.

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

К этому моменту мы знали, что требуется:

  1. Перенять новым механизмом всю функциональность старого: координацию того самого ансамбля разнородных сущностей, которые делают Музыку такой, какая она есть.
  2. Повысить качество приложения и сервиса в целом. Исправить ошибки, которые ранее исправить не могли. Оценивать общее качество мы сможем по количеству положительных и отрицательных отзывов во внешних и внутренних каналах коммуникации, крешам, ANR’ам, показателям производительности и прочему.
  3. Раскатывать новый механизм постепенно. Иначе качество приложения на заметное время сильно просядет и наши пользователи расстроятся. Или вообще временно не сможем выпускать релизы. Ошибки в первоначальной реализации нового механизма такого масштаба и его интеграции со старым кодом, как показывает опыт, неизбежны.
  4. Повысить качество кода: сделать его гибким, расширяемым, понятным, предсказуемым, тестируемым — в общем, хорошим. Должно получиться. Согласуем моё собственное видение и накопленную экспертизу с видением и экспертизой команды, обсуждая реализацию на архитектурных ревью, рабочих местах и за кружкой кофе на кофепоинте.
  5. Получить новые возможности по внесению изменений в ту часть функциональности, которая относится к воспроизведению музыки. Учесть потребности параллельно разрабатывающихся и планирующихся проектов. Упростить поддержку текущей функциональности и внедрение новой.
  6. Переиспользовать новый механизм в приложении и распространяемом SDK. Значит, сделать новый механизм в форме набора модулей. И, желательно, с этими модулями лишние зависимости в SDK не притащить, чтобы сильно не увеличить его размер.

На основе этой информации можно было приступить к планированию и сформировать хотя бы черновой скоуп работ.

Изначальный оптимистичный план еще до начала активных работ по проекту был таков, что за квартал новый механизм полностью заменит собой старый, и, желательно, не только в приложении, а ещё и в SDK. И что бóльшую часть остатков старого механизма мы успеем вычистить.

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

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

Рассмотрев различные модели согласованности, я предположил, что в конечном счёте от механизма требуется только Sequential consistency. Почему?

  • Первая мысль. Старый механизм пытался предложить Strict consistency. В основном за счет серьёзнейшего ограничения — все обращения к нему должны были быть выполнены исключительно из главного потока (UI). Но даже так у него не всё получалось. Этим ограничением затрагивались сколько-либо тяжёлые операции, такие как работа с файловой системой, сетью, обработка больших списков. Например, треков в одной очереди может быть до 10 тысяч, все взаимодействия со старым механизмом (и старыми очередями) обязаны происходить на главном потоке, а значит, должны укладываться в 16 мс (говоря о 60 fps), чтобы не тормозить отрисовку интерфейса. Ну вы поняли: иногда могло и притормозить. Где-то это почти незаметно, а где-то заметно, где-то это ошибка программиста.

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

Можно использовать блокирующие средства синхронизации, вроде mutex’ов. В уже изученных реалиях это зазвучало крайне неэффективно и неудобно для использования в конечных точках, да ещё и не решало толком никаких фундаментальных проблем, справиться с которыми был неспособен старый механизм (об этом позже). А любые, даже безобидные, которые не должны занимать много времени, обращения к такому механизму из главного потока всё так же могут затормозить UI, если попадут на блокировку из параллельной долгой операции.

А как реализовывать отмену долгих операций? Что делать со старым Java-кодом, в котором нет тех самых корутин? В общем, реализация со строгой консистентностью на блокировках не выглядела для нас хорошим вариантом.

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

Остриём встал вопрос: что делать с кодом, который на строгую консистентность рассчитывает? И не забываем: он вызывается из главного потока. Такой, например (упрощён для понимания):

val contentType = playbackControl.getCurrentQueue().getContentType()
if (contentType is SomeConentType) {
   val currentPlayable = playbackControl.getCurrentPlayable()
   val duration = playbackControl.getCurrentPlayableDuration()
   val position = playbackControl.getCurrentPlaybackPosition()
   val shouldRewind = someControl.shoudRewind(duration, position, currentPlayable)
   if (shouldRewind) {
      playbackControl.seekTo(position - 2.seconds)
   }
}

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

Здесь, к слову, скрывается и другая проблема, помимо вопроса о строгой консистентности. В старом механизме возможен рассинхрон между тем, что окажется в поле contentType, и тем, что окажется в поле currentPlayable (подробнее об этом позже). Подробное технического решение по миграции вышеупомянутого кода на новый механизм ещё предстояло спроектировать. Но главное уже было понятно: оно существует.

Итого, сформировалась новая версия требований к механизму, уже с учётом технической части.

  1. Реализовать новый механизм нужно таким образом, чтобы он был совместим со старым кодом. Раскатка нового механизма должна проходить постепенно. Иначе шанс застопорить релизный процесс на несколько недель (а может, и больше) и расстроить множество пользователей стремился бы к 100% из-за допущенных при реализации ошибок.
  2. Из первого требования плавно вытекает второе. Новый механизм должен перенять всю функциональность старого: координацию того самого ансамбля разнородных сущностей, которые делают Музыку такой, какая она есть. Всё перечислять не буду: это задачи от реагирования на нажатие кнопки плей/пауза до реагирования на переключение треков через Яндекс Станцию (в режиме сопряжения с колонкой).
  3. Из первого требования плавно вытекает и третье. Раз весь код приложения ходит в старый механизм воспроизведения из главного потока, ходить таким образом в новый тоже должно быть допустимо и безопасно. Более того, новый механизм должен быть синхронизирован так, чтобы любой поток мог к нему обратиться и не породить этим новые баги.
  4. Обеспечить в новом механизме sequential consistency. То есть сделать так, чтобы выдаваемое наружу состояние ансамбля координируемых механизмом сущностей было согласованным. Но не так, чтобы результат желаемых операций по изменению состояния механизма был всегда виден при последующем чтении состояния незамедлительно.
  5. Новый механизм должен быть многомодульным и собираться как конструктор. Это значит, что каждая очередь, каждый плеер, непосредственно ядро и прочие вспомогательные сущности, должны, в идеале, быть вынесены в модули. Пульт от Алисы, Chromecast, различные модификаторы для немузыкального контента (подкастов, книг и прочего) тоже должны быть лишь частями конструктора. Это требуется для сборки различающихся по функциональности версий механизма для SDK и основного приложения. В SDK на текущий момент требуются не все типы очередей, не все типы плееров и тому подобного. К тому же SDK, просто-напросто будучи распространяемой библиотекой, а не приложением, обладает некоторой собственной спецификой, и это нужно учитывать.
  6. Должно быть легко реализовать, например, такой продуктовый сценарий, происходящий по желанию пользователя или автоматически: постановка текущего трека на паузу → запуск новой очереди с конкретного трека и конкретной секунды → начало воспроизведения этого трека. То есть требуется некая возможность конструировать произвольные последовательности операций и выполнять их. И, конечно, нужно сохранять отзывчивость на действия пользователя, не портить UX. Но всё должно работать согласованно, и ни в какой комбинации действий не приводить к тому, что пользователь увидел или услышал то, чего не ожидал.

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

Концептуально Playback (механизм управления воспроизведением) теперь выглядит так:


Диаграмма 1

До рефакторинга Playback был частью монолита, теперь же мы вынесли его в отдельные несколько модулей. А вместе с ним — и все очереди. Каждый из этих модулей мы планируем переиспользовать в SDK, который отдаём Кинопоиску, Алисе, Навигатору и основному Поиску. Всё и сразу там, конечно, не понадобится, но итеративно будем двигаться именно в эту сторону.

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

Очень большая часть логики приложения строилась на паттерне “Visitor”. Не хотелось терять все его преимущества. Пришли к такому решению:


Диаграмма 2

Внутри extension-метода мы через when проходимся по всем наследникам и пишем else-ветку. Но при этом мы пишем тест, который проверяет, что все наследники класса в этом when учтены. Таким образом мы не теряем преимуществ паттерна, заменяя compile-time-проверку на тест.

В основе механизма было решено заложить три не самые хитрые, но и не самые банальные структуры:

  1. Расширяемый дополнительными executor’ами процессор команд, где команда содержит только параметры для её исполнения, но не содержит логики исполнения, как это предполагается в распространенном паттерне «Команда». Так обеспечим модульную расширяемость и возможность конструировать произвольные последовательности команд.
  2. Буфер команд, благодаря которому мы можем не беспокоиться о том, с какого потока обращаться к механизму. Бонусом получаем возможность осознанно приоритизировать команды (и их последовательности), управлять их отменой, а также избавляться от вырождающих друг друга команд.
  3. Разделение команд и executor’ов на две иерархии: те, что запускают новые очереди, и те, что не запускают. Для Музыки это очень большая разница. Для Playback'а тоже. Чуть позже расскажу, почему.
  4. Машину состояний, которая управляет состоянием механизма и обеспечивает консистентность внешнего состояния при любых входных данных. Входными данными являются потоки событий и состояний от плеера, очередей и разных вспомогательных сущностей.

Так мы и должны были получить то, чего желали: настоящую sequential consistency, адекватную работу с потоками, удобный конструктор последовательностей команд и многое другое.

Верхнеуровнево схема нового Playback’а выглядит так, как на картинке. Есть модуль с ядром механизма, координирующего связь между всеми составляющими системы воспроизведения. Очереди и плееры могут находиться (и бóльшая часть уже находится) в модулях. Ещё есть несколько вспомогательных модулей, но это лишние подробности.


Диаграмма 3

Более подробная и точная схема ядра Playback’а показана на рисунке ниже. Эта схема соответствует центру диаграммы 1 и середине диаграммы 3.


Диаграмма 4

Второй этап — разработка и внедрение в основное приложение


В вышеописанном виде проект перешёл на стадию разработки. В первой итерации мы должны были реализовать:

  1. Стейт-машину состояний.
  2. Реестр очередей.
  3. Владельцев состояния очередей, Playback'а и ещё пары менее значительных сущностей. Коротко говоря, это такие классы, которые в удобном виде поставляют информацию наружу.
  4. Процессор команд.

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

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

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

Хорошо: ядро есть. Но оно работает со старыми очередями и старыми сущностями через адаптеры.

Четвёртая итерация. Новые очереди я разрабатывал по одной. Можно было плавно переходить на их использование благодаря экспериментам и архитектуре «конструктора», которая у нас получилась.

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

Во время второй и третьей итераций я параллельно — где-то вынужденно, где–то довольно хаотично — занимался переписыванием всех использований старого механизма на новый. Это долгий процесс, в него постепенно будет втягиваться вся команда, но с чего-то надо начинать. Такой рефакторинг можно было делать постепенно: не забываем требование про совместимость нового механизма со старым кодом. Но совместимость через адаптеры к старым сущностям и множественные оборачивания, разворачивания классов — это «грязновато». Будем постепенно дочищать все остатки.

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

С новым механизмом стало легко реализовать, например, такой сценарий: пауза текущей очереди → запуск новой очереди → ожидание сходимости с плеером → запуск новой очереди. И такой сценарий будет исполняться всегда последовательно, как единое целое. Если в обработку прилетят новые команды, они встанут в очередь за этим сценарием. Внутри механизма выстраиваются чёткие цепочки команд и осуществляется регулирование их исполнения по некоторым правилам. Например, одна цепочка может «перетереть» другую, если предыдущая стала несущественной для пользователя.

Третий этап — внедрение в SDK


Здесь работы идут полным ходом. Концептуально они похожи на работы по внедрению механизма в приложение, так что не буду дополнительно их описывать.

Интеграция нового механизма в SDK уже идёт полным ходом. Стало понятно, что внутренности SDK, касающиеся воспроизведения, будут заменены новыми модулями практически полностью — останутся только AIDL-интерфейсы для межпроцессного общения с хостами (Кинопоиском, Алисой, Навигатором и Поиском), адаптеры и небольшая специфика этих самых хостов.

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

Закрытые баги


Рефакторинг помог закрыть самые частые и самые раздражающие пользователей баги. Например, были проблемы с работой в фоне. Android к этому довольно критично относится, поэтому работа программистов тут как работа сапёра — без права на ошибку. Ибо если ты допустил ошибку в коде, а потом приложение из-за этого в фоновом режиме сделало что-то не то, например, отпустило wake-lock, то исход будет весьма предсказуемым:



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

Ещё были проблемы с уведомлениями — это тот самый баг, который очень сильно зависит непосредственно от устройства. Если в случае с iOS мы с вами имеем набор айфонов с плюс-минус одинаковыми ТТХ, просто у кого-то чёлка, а у кого-то — Touch ID, то в случае с Android весь зоопарк устройств даёт о себе знать. Например, на ряде устройств уведомление от плеера можно быстро и логично смахнуть, а на других устройствах — нельзя. Вдобавок некоторые девайсы время от времени предпочитали правильно отображать пользователю само уведомление, но отображать в нём старый текст. Тоже починили.

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

Итог


Активная фаза разработки нового механизма заняла около трёх месяцев. Почти месяц он был включён только на сотрудников Яндекса, а затем мы постепенно подняли уровень раскатки на внешних пользователей до 50%. В тот момент нашли досадную ошибку с валидацией возможности запустить трек — сообщения о невозможности запуска стали отображаться у пользователей иначе. Раскатку механизма пришлось снова вернуть в состояние «на сотрудников».

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

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

Комментарии (87)


  1. Pahanini
    15.06.2022 11:01
    -9

    Лучше бы для Apple Watch приложение сделали


    1. smalldron
      15.06.2022 11:37
      +7

      "лучше"- чем что?

      более конструктивный вариант, наверное, был бы такой: было бы здорово, если бы Яндекс сделал свою Музыку приложением для Smart Watches. И, конечно, не с Эпла начинать стоит, а с Андроида.


      1. Pahanini
        15.06.2022 11:54

        Лучше чем тратить время на рефакторинг. Непонятно почему Яндекс не может много лет сделать нормальное приложение для часов которое уже давно есть у конкурентов. Также это один из самых популярных запросов на yandexmusic.userecho.com и уже не первый год. При этом обратной связи от компании 0.


  1. debug45
    15.06.2022 11:06
    +9

    Поставьте уже в App Store галочку о поддержке Mac на M1


    1. iLLuzor
      15.06.2022 12:16
      -5

      Разве не удобней слушать с сайта?


      1. debug45
        15.06.2022 12:24
        +11

        Нет, не удобнее. И вот вам несколько тысяч комментариев об этом в подтверждение. https://yandexmusic.userecho.com/ru/communities/45/topics/191-prilozhenie-dlya-macos


    1. ganzmavag
      16.06.2022 11:05

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


      1. debug45
        16.06.2022 11:37
        +1

        Я вам как iOS-разработчик больше скажу — эта поддержка включена по умолчанию, и компании типа Яндекса, Google, Facebook, ВКонтакте её зачем-то идут и специально отключают


  1. GooG2e
    15.06.2022 11:37

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


    1. daryastarkova
      15.06.2022 21:45

      Здравствуйте! Я работаю в поддержке Яндекс Музыки. Постараемся во всём разобраться, но понадобятся дополнительные данные. Напишите, пожалуйста, моим коллегам ваш логин и подробности. Сделать это можно любым удобным способом: ya.cc/t/veRNvSziSTWp3


      1. VitaliyII
        16.06.2022 10:23
        +1

        Привет, Дарья!

        Уже давно юзеры ЯМы просят добавить в приложение сортировку плейлистов. Она есть во всех иных музлостримингах. Но воз и ныне там.

        У меня несколько десятков плейлистов. Они появились после недавнего массового импорта из других музлостримингов. Юзать их без сортировки муторно и раздражительно.

        --


        1. daryastarkova
          16.06.2022 12:55
          +1

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


          1. VitaliyII
            16.06.2022 15:36

            Дорогая Дарья, самый старый репорт о добавлении сортировки плейлистов, какой я видел, был сделан более двух лет назад. Highly likely, были и более старые репорты, фича ведь нужная многим. Сколько ещё лет нужно для добавления этой простой фичи?

            Мне нравится ЯМа, это мой основной музлостриминг. Радость отравляет только этот недостаток. А ещё вопиющее равнодушие разработчиков к нуждам юзеров. Жаловался множество раз — без толку.

            --


  1. huhen
    15.06.2022 12:09
    +9

    Было бы здорово, если бы Яндекс обратил внимание на просьбы множества пользователей в течении трёх лет Разделить громкость медиа и громкость голоса Алисы. Это касается и приложения. В машине при прослушивании музыки на комфортной громкости, Алиса звучит настолько тихо, что не разобрать.


    1. snnrman
      15.06.2022 17:55
      +4

      Мне кажется 3 года Яндекс просто смеется в лицо всем пользователям Алисы. При этом мне очень интересно как они сами пользуются еле слышной Алисой и орущей музыкой.


  1. turbidit
    15.06.2022 12:36
    +13

    Не знаю что вы там нарефакторили, но при нестабильном интернете все стало плохо. Я часто езжу по трассе ~300 км, из которых около трети связи нет. Раньше (1,5 - 2 года назад), когда кончался кэш, приложение просто ждало появление связи и продолжало с того момента. Сейчас происходит что угодно - пропуск треков (особенно удобно когда слушаешь подкасты или книгу, ага) или просто выключается. Приходится постоянно отвлекаться от дороги и восстанавливать воспроизведение.


    1. turbidit
      15.06.2022 14:09
      +2

      Судя по комментариям, я не один такой страдалец: https://yandexmusic.userecho.com/ru/communities/5/topics/175-nastrojka-keshirovaniya-trekov


    1. Didimus
      16.06.2022 10:21

      А мне посоветуйте, как слушать загруженные аудиокниги с Яндекс-диска. Планируется такая возможность?


      1. daryastarkova
        16.06.2022 13:40

        Здравствуйте! Возможность добавлять для прослушивания файлы с Яндекс Диска раньше была, но мы давно её убрали. Обещаем подумать над альтернативами.


  1. MeetTheBoris
    15.06.2022 13:03
    +1

    А почему скриншот с главной такой не красивый, где прозрачный статусбар?


  1. Al_Pollitruk
    15.06.2022 13:58
    +13

    А еще, уважаемый Яндекс, сделайте уже нормализацию громкости для треков, много раз просили.

    https://yandexmusic.userecho.com/ru/communities/45/topics/774-normalizatsiya-gromkosti-trekov


  1. mikelavr
    15.06.2022 15:02
    +1

    Есть ли шансы заодно получить рефакторинг для работы приложений Яндекс.Музыки и Яндекс.Радио в режиме горизонтального экрана? Я их использую в магнитоле (на Android), которую весьма сложно повернуть в вертикальное положение, разве что вместе с автомобилем :). Хорошо видно, что дизайн для вертикального положения экрана продумывался, а для горизонтального был сделан по остаточному принципу.

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


    1. daryastarkova
      15.06.2022 21:56

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


      1. mikelavr
        16.06.2022 09:50

        Приложение работает на магнитоле нормально, точно так же как и на телефоне. Вопрос только в дизайне. Разрешение экрана магнитолы 1024*600, как это выглядит - на фотографии с Яндекс.Радио.



        Что не нравится:
        1) Слева и справа остаются огромные неиспользуемые поля. Видно, что это просто дизайн для вертикального экрана, который втиснули в горизонтальный.
        2) Если строчка названия трека стала двухстрочной, строчка исполнителя уходит под нижнюю границу поля.

        На скриншоте тоже Яндекс.Радио, но уже на телефоне Mi 10 5G, разрешение 2340*1080.

        Этот вариант сильно лучше (и я бы его выбрал для магнитолы при возможности), но:

        1) Все равно справа огромное пустое поле. Хочется увеличить квадрат картинки альбома до нижней границы экрана, кнопки сдвинуть вправо, а текст немного поднять.
        2) Зачем то появилась кнопка перемотки на следующий трек, которая дублирует свайп влево.


        1. ganzmavag
          16.06.2022 11:06

          А на Яндекс Музыке у вас есть свайп влево для переключения? У меня только на радио


          1. mikelavr
            16.06.2022 11:12

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

            Бестолковый вариант, еще хуже чем любой из Яндекс.Радио.


            1. ganzmavag
              16.06.2022 11:15

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


              1. daryastarkova
                16.06.2022 14:47

                Здравствуйте! Я работаю в поддержке Яндекс Музыки. Спасибо за фидбэк, обязательно подумаем с командой над тем, чтобы улучшить этот момент.


  1. StasPotapov
    15.06.2022 15:31
    +2

    Отличный доклад, спасибо @Rugged! Видно что проделана большая работа.

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


  1. cplKazmin
    15.06.2022 15:32
    +2

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


  1. gdt
    15.06.2022 15:34
    +5

    Молодцы! Раз такой серьёзный проект осилили, групповые операции с треками должно быть плёвое дело добавить, правда?


    1. tvr
      16.06.2022 12:15
      +1

      Мы на мелочи не размениваемся!/s


  1. jericho_code
    15.06.2022 15:35
    +2

    3 месяца из заголовка - это как понимаю реальное время? Если да, то сколько стоил рефакторинг в человеко-часах, если не секрет?)


    1. RA_ZeroTech
      15.06.2022 20:32
      +2

      А так же интересно, сколько времени ушло на этапы: инициализация, планирование, анализ, проектирование.

      Хотя бы в сумме. Но лучше в отдельности :)

      Так три месяца на рефакторинг звучит, конечно, круто и достойно. Но и предыдущие этапы не пару дней заняли? :)


      1. Rugged Автор
        16.06.2022 18:35
        +1

        Лучше чётко про этапы я от ответа воздержусь, а то это будет совсем недостоверная информация.

        Я бы так сказал: в реальном времени на всё про всё от взятия тикета в работу до начала раскатки на сотрудников ушло порядка 2,5 мес., может чуть больше. Это была активная работа, - в первую очередь с моей стороны. Но всё-таки начал потихоньку погружаться в контекст я, конечно, заранее: не было чёткой отсечки, что вот ровно здесь я знать не знал о проекте, вот здесь начал инциализацию, а вот здесь её закончил... Эти периоды перехода тоже оказывают какое-то влияние.

        Соотношение времени анализа и проектирования к разработке по ощущению примерно 1 к 1.

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

        Раскатку механизма на 100% внешних пользователей (со второй попытки) осуществили быстро - порядка одной недели. По трудозатратам на внесение изменений в админку - 15 минут :)


        1. RA_ZeroTech
          16.06.2022 21:23
          +1

          Спасибо за ответ! Конечно, точных цифр не ожидал услышать. Хоты бы порядок. Чтобы иметь представление по Вашему опыту, сколько времени уходит на подготовку к разработке/рефакторингу (непосредственная целенаправленная работа с кодом).
          Так как, повторюсь, для 10-ти летнего легаси рефакторинг за 3 месяца (пусть даже может и не все на самом деле, но большую часть отрефакторили) считаю отличный срок. Значит, подготовка была достаточно основательная. Поэтому и решил задать этот вопрос.


    1. Rugged Автор
      16.06.2022 18:03
      +1

      Время мы не списываем, поэтому ответить сложно.

      Дам очень-очень приблизительную оценку описанного в статье по верхней границе. Здесь точно не более 3(мес)*21(р.д.)*8(ч) = 504 моих часов. Иногда я отвлекался, иногда были выходные, тянулись хвосты и т.п. Плюс накинем суммарно часов 50 времени коллег, когда я вовлекал их в обсуждения и прочее. Ну вот как-то так: не более 554 часов :)

      (Относится к разработке. Тестирование и работа группы поддержки пользователей в оценку не заложены)


  1. konst90
    15.06.2022 17:44
    +5

    Подкасты. Где возможность слушать не с последнего выпуска, а с первого непрослушанного (т.е. от самого раннего к поздним)?

    Как посмотреть список треков, которым я поставил дизлайк, и отменить? Ошибся, нажал не ту кнопку - все, трек сменился на следующий, и где мне его искать?

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

    Музыка в Навигаторе. Почему нельзя слушать сохранённое на устройстве при потере связи? Раздел вообще не работает, рисует "нет связи" и всё.


    1. konst90
      15.06.2022 17:49

      Да, и ещё вопрос. Не по теме, но вдруг.

      Карты в Картах и карты в Навигаторе - это один и тот же файл? Или, если я загружу регион и там и там - у меня на устройстве будет две копии?


    1. daryastarkova
      15.06.2022 23:00

      Здравствуйте! Постараюсь ответить по порядку:

      1. Если верно вас поняла, такая сортировка уже есть в приложении. Откройте необходимый подкаст и перейдите в раздел с выпусками, там сможете найти специальную кнопку сортировки. Если выбрать сортировку выпусков и нажать на «Слушать», у вас включится непрослушанный выпуск: либо свежий (если от новых к старым), либо старый (если сортировка от старых к новым).

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

      3. Записала в пожелания, подумаем о реализации такого способа воспроизведения.

      4. Для этого устройства офлайн-режим не предусмотрен, поэтому слушать треки можно только в сети.


      1. konst90
        16.06.2022 07:09

        1. Навигатор это не устройство, это ваше приложение - Яндекс.Навигатор. Там есть вкладка с музыкой, но работает она только когда есть сеть.


    1. serge-sb
      16.06.2022 16:21

      Насчёт подкастов, возможности слушать в очерёдности выпуска, а также настраиваемого кэширования. Для андроида давно пользуюсь и очень рекомендую Podcast Addict.


  1. Rocker2337
    15.06.2022 18:07
    +3

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


  1. Akr0n
    15.06.2022 18:19
    +3

    Несколько раз писал по поводу неудобств приложения, всегда отвечали что-то типа "так задумано, это архитектура такая", теперь что-то изменилось?

    1. При скачке плейлиста ему автоматом ставится лайк, зачем? Я не отмечал, что мне нравятся все эти треки.

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


    1. daryastarkova
      15.06.2022 23:51

      Здравствуйте!

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

      2. Тут не совсем пока понимаю. У вас повторно скачивается трек, если слушаете скачанный из плейлиста «Мне нравится»? Если да, так быть не должно. Загляните к моим коллегам из поддержки Яндекс Музыки любым удобным способом с подробностями такого поведения и примером, будем разбираться: ya.cc/t/veRNvSziSTWp3


      1. Akr0n
        16.06.2022 01:36
        +4

        1. Я скачиваю, например, плейлист Премьера, просто чтобы послушать оффлайн или без типичных для Я.Музыки тормозов при скачке в процессе прослушивания. Но это же не значит, что мне нравятся ВСЕ треки внутри листа? Ведь это портит мои рекомендации? Мало того, этот плейлист еще и меняется каждую неделю.
        2. Да, при проигрывании потом из плейлиста Мне нравится галочки скачивания нет и по трафику заметно, что оно качает его заново, но это было на версии годичной давности, как сейчас — не проверял.


    1. ganzmavag
      16.06.2022 11:08

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


  1. Vladimir_Chursin
    15.06.2022 21:34

    Есть мнение, что рефакторинг должен быть частью рабочего процесса в плановом режиме.


    1. Rugged Автор
      16.06.2022 00:27
      +2

      Я полностью поддерживаю это мнение. Рефакторинг должен быть частью рабочего процесса в плановом режиме.

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

      Мы не взяли с потолка идею "всё выбросить и написать новое": просто из конкретных проблем мы сформировали конкретный проект, который запланировали на конкретный квартал, на конкретного человека :)

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


  1. Xambey97
    15.06.2022 23:18
    +1

    Подскажите, а процесс создания ф-ционала для миграции с Гугл музыки вообще идет? Я такой что мб и перешел бы к вам, чтобы не гемороиться с оплатой, но без нормальной миграции извольте. Плашка «скоро появится» уже не один месяц висит. Думаю я такой не один

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


    1. daryastarkova
      16.06.2022 13:55

      Здравствуйте! Я работаю в поддержке Яндекс Музыки. Удобный импорт из YouTube Music действительно планировали, но это требует больше времени, чем мы рассчитывали. Как только сделаем, сообщим об этом в соцсетях — следите за обновлениями!

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


  1. Alinaki
    15.06.2022 23:31
    +2

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

    Спасибо за бестолковый эффект "круглой волны", жрущий ресурсы веба и абсолютно ненужный в мобильном приложении.

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


    1. vcKomm
      16.06.2022 12:21

      Эффект прикольный, мне и многим нравится. Интересно, что у вас за устройство, если зацикленное видео так жрет его ресурсы.

      С поиском соглашусь. Причем в КиноПоиске он снизу, в Spotify снизу, а у Яндекса сверху.


      1. Alinaki
        16.06.2022 14:50

        в вебе это не всегда видео, это холст. да и ощущение бестолковости придаёт.


        1. vcKomm
          16.06.2022 15:01
          +1

          А анимации и в целом css вам не придает ощущение бестолковости?


          1. Alinaki
            16.06.2022 15:03
            +1

            Без комментариев, пожалуй. Я ничего более бестолкового в жизни не видел. Даже CSS-анимации приносят чаще пользу, акцентируя внимание. А это даже не MilkDrop, ЕВПОЧЯ.


  1. MrPigamov
    16.06.2022 00:07

    Рефакторинг дело хорошее, молодцы ребята, отличные изменения в лучшую сторону! Спасибо!


  1. AlexGluck
    16.06.2022 03:47
    +3

    Музыку в автомобильные ШГУ обязательно с кешем! Хотя бы в пакете с я.навигатором!


  1. AlexEx70
    16.06.2022 07:11
    +1

    Надо сказать, у вас отличное приложение, на мой взгляд рекомендации работают намного лучше конкурентов, интерфейс приятнее и все под рукой. Но вот эквалайзер, это провал просто! Он может работать, а может и нет в совершенно рандомных ситуациях, например при небольшой перемотке назад — отключается. Или начинает играть композиция, уже прошло секунд 10 и только тогда он начинает работать. Приложение называется «Музыка» и как можно было так налажать с самым основным компонентом — для меня загадка.


    1. Akr0n
      16.06.2022 07:20
      +2

      Подскажите, а где в приложении эквалайзер?


      1. shemm11
        16.06.2022 10:45
        +1

        Коллекция -> Настройки -> Эквалайзер


        1. mikelavr
          16.06.2022 11:17
          +2

          Но это внешнее приложение. Из системы, или установленное пользователем.


        1. Akr0n
          16.06.2022 15:35

          У меня такого нет и никогда не было.


    1. Rugged Автор
      16.06.2022 11:32

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


  1. stone_evil
    16.06.2022 07:42
    +3

    Бро, на тебя вся надежда! Потому что после перехода со Spotify на Яндекс.Музыку я поседел в некоторых местах и мой лексикон обогатился новыми фельдиперстовыми регулярными выражениями. Не подкачай, родненький!


  1. diralik
    16.06.2022 09:48
    +1

    Планируется ли вернуть потоки музыки "под настроение" (спокойное, агрессивное, и т д) и "для занятия" (заснуть, фоновая музыка и т д) которые убрали в обновлении декабря 2021?


    1. daniilshat
      16.06.2022 11:40
      +2

      Странно, но у меня всё из этого есть, поток можно настроить.

      Скриншот


      1. diralik
        16.06.2022 13:03
        +1

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


        1. daniilshat
          16.06.2022 13:20

          В этом случае да, вы правы. Пунктов в меню стало заметно меньше


        1. daryastarkova
          16.06.2022 14:05

          Здравствуйте! Отдельные потоки по настроениям и занятиям в приложении переехали в раздел «Подборки» — нужно пролистать главный экран до самого низа. Там можно выбрать «В настроение» или «Послушать фоном» и запустить потоки на любой вкус.


          1. diralik
            16.06.2022 14:22

            Подборки это к сожалению фиксированный набор треков, который никак не учитывает мои предпочтения. То есть например есть подборка "Заснуть", там 100 треков, они все спокойные, расслабленные, и т.д., но засыпать под них у меня не получается. А под поток "заснуть" который был до обновления отлично получалось


            1. daryastarkova
              16.06.2022 14:38

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


              1. diralik
                16.06.2022 15:22
                +1

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


  1. zeleniy
    16.06.2022 11:12
    +4

    Несколько тысяч пользовательских запросов на "форуме пожеланий" - https://yandexmusic.userecho.com/ - на которые 0 внимания. 2 или 3 года назад писал туда, чтобы фильтр по плейлисту сделали (невероятно сложный функционал). Всё ждём-с. К чему эти бравые посты, если всем очевидно, что сервис не развивается никак? Раньше хоть и с рекламой, но можно было пользоваться бесплатно. Сейчас вообще никак. Плати и наслаждайся убогим плеером, который мы сделали на заре сервиса 10 лет назад. Спасибо, есть другие варианты.


  1. ganzmavag
    16.06.2022 11:14

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


  1. pitt90
    16.06.2022 11:35
    +1

    Красавцы! Жаль большинство комментариев это фича-реквесты не по теме :)


    1. ganzmavag
      16.06.2022 12:37
      +3

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

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

      Вот посмотрите выше про, например, приложение для MacOS - тысячи комментариев и ни одного ответа что мешает просто включить поддержку M1. Про кеширование нескольких треков наперед - много лет обсуждается, не реализовано. Удобный интерфейс в магнитолах, которых все больше - "мы не поддерживаем магнитолы". Вот пытаюсь вспомнить, что изменилось кроме появления видеошотов и текстов песен - и не могу.


  1. blind_oracle
    16.06.2022 12:24

    У меня до сих пор Я.Музыка не может обновить плашку с названием трека в поле нотификаций и экране блокировки при переключении трека.

    Потом асинхронно обновляет, но почти всегда отстаёт на трек. Базовая фича вроде.

    Galaxy S21+


    1. daryastarkova
      16.06.2022 14:14

      Здравствуйте! Я работаю в поддержке Яндекс Музыки и хочу помочь. Напишите, пожалуйста, нам в любой соцсети или в чате ваш логин и подробности (версию ОС и приложения) со ссылкой на этот комментарий. Сделать это можно любым удобным способом: ya.cc/t/veRNvSziSTWp3


  1. KoZzzik
    16.06.2022 12:28
    +2

    Нормализация, и больше ничего не нужно


  1. arTk_ev
    16.06.2022 17:52
    +1

    За 3 месяца - мое почтение. Три раза приходилось через это проходить, меньше чем за 6 месяцев это не сделать. Да и в принципе полностью это сделать невозможно. У людей сдавали нервы, дешевле переписать с нуля.

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

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


    1. Rugged Автор
      16.06.2022 18:55

      Я где-то чуть выше в комментах немного подробнее описал временные вопросы.

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

      Впереди много крутых проектов. Стараемся укладывать проекты в квартал, иначе они расползаются, размываются. Этот кусок вот осилили - отчитались :)


  1. Bjranky
    16.06.2022 18:57

    Сделайте "мою волну" реально моей волной, с более широкой возможностью сортировки и выбора треков. А не просто "русское", "зарубежное" , " Новое" , где выбрать можно что то одно.
    Так, например я слушаю рок в основном, но в моей волне в последнее время абсолютно все, начиная от диско 80 и заканчивая электронной музыкой. Это конечно классно, но музыка повторяется очень часто.
    Было бы классно , что бы в моей волне можно было делать подборку по нескольким жанрам и разным периодами


  1. Paraparapam
    16.06.2022 19:06
    +2

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


    1. Rugged Автор
      16.06.2022 19:08
      +1

      Привет! Это не совсем по теме статьи, с тобой мы в ЛС скоммуницировались


  1. Akr0n
    17.06.2022 11:57

    Индикатор уровня загрузки трека везде убрали или это только у меня отвалилось (так говорила ТП пол года назад)?


    1. Rugged Автор
      17.06.2022 17:26

      Убрали. И убрали довольно давно. Возможно, ты попал как раз в момент, когда поддержка могла отвечать ещё по старому, а эксперимент до тебя уже дошёл :)