Для обсуждения на этой неделе выбрал следующие темы:
Onboarding нового члена команды;
Процессы разработки;
БД в моб… twitter.com/i/web/status/1…
Сегодня наша команда увеличивается сразу на три человека, поэтому рассказывать буду про анбординг.
Рабочие места готовятся до прихода сотрудников, выглядят они примерно так: pic.twitter.com/dDxa241rSm
У компании есть процесс адаптации новых сотрудников, который включает в себя получение нескольких памяток, коробки… twitter.com/i/web/status/1…
В коробке с печеньками, помимо самих печенек, есть ещё чек-лист с тем, что необходимо сделать за первую неделю, две… twitter.com/i/web/status/1…
фотографию с наставником, фотографию на 27 из 27 этажей российского интернета, что-то пошарить, куда-то сходить и,… twitter.com/i/web/status/1…
Выполнив все пункты вы получаете какой-то сувенир. Никто из коллег не знает что это за сувенир такой. 😏
В масштабе команды, первый день идет примерно по такому сценарию:
тимлид знакомит с командой, рассказывает о проекте, процессах и как пользоваться джирой. Дальше вы получаете все до… twitter.com/i/web/status/1…
В этот же день вы получаете настоящую задачу, а если повезет, то может даже и несколько! Это сильно удивляет, но в то же время закаляет.
Для сравнения, в мой первый день в Рамблере ко мне подошел ведущий разработчик проекта, поставил рядом стул и вмест… twitter.com/i/web/status/1…
После этого еще и рассказал про структуру проекта и как там что устроено, а свою первую задачу я получил только на третий день работы.
Процесс работы, над своей первой и последующими задачами, в Рамблере был выстроен следующим образом:
От дева отпочковывалась новая ветка, в ней выполнялась задача и писались тесты. По окончанию работы – создавалось р… twitter.com/i/web/status/1…
Если во время тестирования находились баги, то задача возвращалась и процесс повторялся заново.
Когда дело доходило до релиза – создавалась релизная ветка, а дальше все тоже самое, только с задачами, которые вхо… twitter.com/i/web/status/1…
В сухом остатке: каждый коммит в мастер-ветку это полностью рабочая (или нет) релизная версия приложение, дев – хранилище идеального кода.
Подробнее, о том, как это все работало можно почитать в образцовом репозитории на гитхабе – github.com/rambler-ios/te… ❤️
А теперь представьте ситуацию:
Вы заканчиваете институт благородных программистов имени Рамблера и идете работать в другую компанию, на руке, вмес… twitter.com/i/web/status/1…
В этот момент все 27 этажей российского интернета уходят из-под ног.
К такому “процессу”, кстати, быстро привыкаешь и начинаешь чувствовать себя в атмосфере стартапа.
Правда, это веселье продлилось недолго. Пришли менеджеры и эффективно прокачали нашу и без того проактивную работу.
На каждую задачу создается отдельная фича-ветка от дева и в ней выполняются все работы.
Появилось кодревью и это,… twitter.com/i/web/status/1…
Начались активные обсуждения принятых решений и споры, которые в свою очередь привели к полному пересмотру ряда важ… twitter.com/i/web/status/1…
После того как ревью пройдено – из этой ветки собирается сборка и отдается на тестирование. Если все ок, то ветка в… twitter.com/i/web/status/1…
Процесс сборки полностью автоматизирован и запускается изменением статуса задачи на “Reviewed”.
Таким образов, в деве находятся полностью протестированные задачи, готовые к тому что из них будет собрана новая версия приложения.
Если во время выпекания релиза обнаруживаются баги, то на них заводятся задачи, создаются фича-ветки, которые прохо… twitter.com/i/web/status/1…
Делаем так пока не получим best quality in the city, my friend.
Твиты на тему работы со звуком в iOS будут выходить при поддержке моего любимого коллеги Вячеслава Редькина.
Входной точкой при работе со звуком в iOS является класс AVAudioSession.
Есть популярная аналогия – аудиосессия это как взлетная полоса для самолета, в каждую единицу времени сессией владе… twitter.com/i/web/status/1…
Какому самолету разрешается использовать взлетную полосу контролируется в авиадиспетчерской вышке, в нашем случае это система iOS.
Успех поставленной задачи, будь то запись и/или проигрывание звука, зависит от правильной настройки аудиосессии. Пе… twitter.com/i/web/status/1…
Категорий несколько: запись, проигрывание, стримминг и тд. Каждая категория это своего рода набор преднастроек для аудиосессии.
Следующий важный момент – выбор режима. Это некое уточнение – вы хотите проигрывать звук потому что вы скайп и устр… twitter.com/i/web/status/1…
Не все режимы совместимы со всеми категориями, поэтому есть вероятность получить ошибку на стадии выполнения програ… twitter.com/i/web/status/1…
Последнее, опции – они нужны для изменения дэфолтного поведения категории.
Например, опция AVAudioSessionCategoryO… twitter.com/i/web/status/1…
В нашем проекте, для записи голосовых сообщения, мы используем категорию AVAudioSessionCategoryPlayAndRecord и опци… twitter.com/i/web/status/1…
Что касается непосредственно самого процесса записи звука, то делаем мы это с помощью низкоуровневого фреймворка AudioUnit.
Происходит это следующим образом:
берем и конфигурируем структуру AudioStreamBasicDescription, она описывает форма… twitter.com/i/web/status/1…
Все эти поля тесно связаны между собой и в выборе их значений необходимо найти баланс между качеством звука и разме… twitter.com/i/web/status/1…
Создаем AudioUnit, передаем ему ранее сконфигурированную структуру и устанавливаем коллбэк, который дергает система… twitter.com/i/web/status/1…
Размер этого буфера тоже настраивается – чем он меньше, тем чаще система дергает коллбэк, чем больше – тем тяжелее… twitter.com/i/web/status/1…
А теперь вместе с Максимом Гордеевым расскажу как мы катились от CoreData до CoreData, SQLite, SQLite.
Было дело так: CoreData, приватный и мэйн контекст, оба смотрят в один координатор, за всеми обновлениями приходило… twitter.com/i/web/status/1…
Для облегчения жизни решили воспользоваться уже готовым решением, которое дает Apple – NSFetchedResultsController,… twitter.com/i/web/status/1…
Вроде ок, а вроде и нет – баги, изменения обрабатывались на главном потоке и куча других причин, поэтому решили написать СВОЕ!
Оставили один контекст, написали кастомный FetchedResultsController, который умеет в фоне отлавливать изменения, ст… twitter.com/i/web/status/1…
Но оставалась другая проблема, ее имя – миграция. Продуктовые требования менялись и это приводило к кардинальным из… twitter.com/i/web/status/1…
Проблему решили миграцией в несколько этапов: на первом этапе мигрировали приоритетную часть данных, которые необхо… twitter.com/i/web/status/1…
Вроде ок, а вроде и нет – на больших объемах данных производительность CoreData оставляет желать лучшего, поэтому решили идти дальше.
Будем использовать SQLite и без всяких там FMDB, а напишем свою обертку на C++, потому что, 🤬, почему нет!
Первым в новое хранилище переехал список контактов. За ним, из CoreData в SQLite, поехали загружаемые пользователем… twitter.com/i/web/status/1…
К этому времени созрела интересная библиотека для работы с SQL – github.com/rbock/sqlpp11, а сами мы здорово напрогр… twitter.com/i/web/status/1…
С помощью sqlpp11 вы можете структурами описать типы полей: pic.twitter.com/AsX7OqpkHS
Которые затем используются для описания таблицы: pic.twitter.com/6mAyu4FDQC
А запрос для получения данных будет выглядеть следующим образом: pic.twitter.com/Vwi9sK828m
На первый взгляд все это может показаться крипово, но из-за такой типизации вы чувствуете себя чуточку безопаснее ч… twitter.com/i/web/status/1…
Сейчас в планах собрать все-таки весь этот зоопарк в одно место и освободиться от плюсов, которые увеличивают время… twitter.com/i/web/status/1…
Вас троллят менеджеры?
Как-то я потратил довольно много времени на то, чтобы отремонтировать работу с клавиатурой, которою сам же и полома… twitter.com/i/web/status/1…
Раньше была проблема – из-за своей тяжести, наше поле для ввода сообщений, инициализировалось так долго, что польз… twitter.com/i/web/status/1…
После оптимизаций пользователь уже быстро открывал чат, но когда хотел написать сообщение, поле ввода оказывалось н… twitter.com/i/web/status/1…
Казалось бы, подписался на клавиатурные уведомление и все должно работать, так из-за чего это было все эти баги?
Во-первых, надо помнить, что инициировать скрытие клавиатуры может не только пользователь, а и всплывающие системны… twitter.com/i/web/status/1…
Если быстро переключаться между приложениями, которые работают с клавиатурой, то можно получить подобную ситуацию. pic.twitter.com/75Y7o2urXR
Здесь, на самом деле, все зависит от ловкости рук пользователя и успеет ли система сделать снэпшот вашего приложени… twitter.com/i/web/status/1…
Другой момент, что будет происходишь когда ваше приложение станет активным?
Система начнет слать уведомления о том, что клавиатура была скрыта (в другом приложении), а потом восстановит вашем… twitter.com/i/web/status/1…
Во-вторых, если вы умеете интерактивно скрывать клавиатуру и используете для этого изменение координат клавиатурног… twitter.com/i/web/status/1…
Система создала второе клавиатурное окно и именно оно отображается на экране. Если ваш код, который ищет клавиатурн… twitter.com/i/web/status/1…
У меня есть еще картинки, но я уже не помню что за приколы на них. pic.twitter.com/eT1318mACL
Другой вариант это не подписываться на уведомления, а использовать inputAccessoryView. Это избавит вас от троллинга… twitter.com/i/web/status/1…
Когда пришел в мэйл мне настоятельно рекомендовали посмотреть сессию за 2016 год по работе с System Trace. Если кто… twitter.com/i/web/status/1…
Через 40 минут у вашего приложения будет 60 fps 🌚
600 подписчиком за три недели – отличное начало!
С вами был Константин Мордань (facebook.com/kn.mrdn) – iOS р… twitter.com/i/web/status/1…
Отдельно хочу поблагодарить Вячеслава Редькина (devslaf@gmail.com) и Максима Гордеева (mail@maxgordeev.ru) за помощь в подготовке тем.
P.S.:
У нас в команде мессенджеров есть открытые вакансии iOS и Android разработчиков, если кому-то интересно – пиш… twitter.com/i/web/status/1…