Pull to refresh
26
Александр Дербенёв@alexac

Senior Software Engineer

6
Subscribers
Send message

А не лучше в таком случае написать простенький shell скрипт, который будет запускать именно те таски, что вам нужны, вместо того чтобы поддерживать makefile/makesurefile и проверять, что необходимый task runner установлен там, где вы это запускаете?

Я не очень понимаю идею делать отдельную программу таск-раннер. В CI/CD скорее всего понадобится несколько более сложный скрипт, который должен выполнять действия в необходимом порядке. Для запуска сервисов таск-раннеры обычно гораздо более сложные — там либо начинается упаковка в контейнеры, либо много конфигурации про то, как именно софт должен быть запущен, перезапущен, остановлен, etc. (то-есть это уже всякие конфигурационные скрипты для init что-то вроде Procman/supervisord). В сборке нужна полноценная система, отслеживающая зависимости, запускающая команды параллельно, и пересобирающая то, что необходимо, когда необходимо. В обычной работе полезнее сделать так, чтобы необходимые задачи можно было спокойно запускать без вороха дополнительных опций и тогда сложность запуска чего-то вручную или с помощью таск-раннера становится одинаковой.

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

Ninja решает эту проблему тем, что записывает хэш от команды в специальный файлик вместе с другой информацией. Если хеш не совпадает — команда изменилась и надо пересобрать конкретный таргет и то, что от него зависит.

1. Есть довольно известный однострочник, который можно вставить, например в таргет help, для того чтобы полистить таргеты и описать что они делают из комментариев.
2. И это хорошо. Потому что иначе у вас начинаются коллиззии между целями для сборки и вспомогательными целями.
3. Как правило, поставить ; \ в конце строки — не проблема. А во многих случаях это и вовсе не нужно.
4. Небольшой коллапс в синтаксисах makefile/shell, но в целом ничего страшного в этом нет.
5. Настройте себе текстовый редактор. Это никогда не было аргументом ни за, ни против какого-то инструмента.
6. Вот это реальная проблема. Однако многие фичи поддерживаются всеми реализациями, которые вы в здравом уме можете встретить (мы же не говорим о поддержке nmake?), а в большинстве случаев можно достаточно смело делать предположение о том, что будет использоваться исключительно gnu make (да, мне тоже это не нравится).

Гораздо более важной проблемой make, на самом деле является то, что там очень нетривиально сделать так, чтобы изменение команды в Makefile приводило к тому чтобы инвалидировались и пересобирались таргеты, которые собираются этой командой. Ну и производительность так себе. Поэтому все больше и больше вместо make используют связку ninja+генератор (например cmake). Использование отдельного генератора убирает проблемы с совместимостью и синтаксисом, а использование ninja, очень положительно влияет на производительность, решает проблему инвалидации таргетов при модификации команды, а также убирает проблемы совместимости (имплементаций ninja гораздо меньше, и фич там тоже меньше, гораздо сложнее сделать что-то несовместимое).

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

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

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

Мне кажется, автор изначально описал модель, в которой не нужны черри-пики. Если есть feature-бранчи, то и работу надо вести в feature-бранчах, а не в мастере, и потом черри-пикать. Соответственно фиксы делать в релизных бранчах и подмердживать их в мастер, а оттуда уже в фича-бранчи. Получается классический git flow.


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

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


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

type(foo)

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


PEP484 ввел Type hints, которые указывают, что в конкретной переменной ожидаются объекты конкретного типа, но type hints не влияют на то, что происходит в рантайме. Интерпретатор практически полностью их игнорирует. И появились они в языке только в угоду тому, чтобы можно было сделать линтеры вроде mypy, которые их проверяют. Но при этом нет гарантий, что в переменную с type hint будет записан объект тип которого соответствует type hint.

Можно купить в штате, где налог на продажу равен нулю и привезти куда угодно, и возвращать ничего не придется. Только в условиях повсеместных карантинов сложно это сделать. Много есть вариантов. Я вот только сегодня заказал ноут из британского apple store, потому что курс фунта по отношению к евро сейчас упал, а пересылка из UK в Ирландию стоит копейки. ~€150 экономии на пустом месте.

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

1. Цены для штатов указаны в долларах и без налога, так как налог зависит от штата, в котором производится покупка. При оплате к ним добавляется налог, американцы к этому привыкли.
2. Цены для европы указаны в евро, с добавлением пошлины на ввоз и VAT.
3. Цены для россии указаны в рублях, с добавлением пошлины на ввоз и НДС.

Если брать цену в долларах, вручную конвертировать в евро, добавлять пошлины и налоги, то получаются цены из европейского магазина с очень маленькой погрешностью (в пределах 50-80€), что легко объясняется ошибками округления и неправильно выбранными курсами конвертации и декларированной стоимости для расчета пошлин и налогов.

Так что сама компания не берет больше в разных страннах за один и тот же товар. Она просто честно удерживает и уплачивает все пошлины и налоги, установленные в соответствующих странах.
Для iOS 12 все еще регулярно выходят обновления безопасности. Но да, мажорных обновлений больше нет.
Ну уж называть AF_UNIX костылем… Имхо, сейчас это очень недооцененная технология. По факту он:
1. Производительнее любого другого стека, так как ни при каких случаях не покидает пределов хоста.
2. Безопаснее, так как к нему невозможно получить доступ извне. Ни прослушать, ни взломать вас через него не смогут.
3. Имеет встроенное разграничение доступа на уровне fs. Мало иметь доступ к системе, чтобы получить доступ к сокету нужно еще и исполнять код от имени пользователя/группы, которым этот доступ разрешен.

Для любого взаимодействия внутри машины AF_UNIX будет предпочтительнее, чем AF_INET6/AF_INET. Это просто протоколы с разными целями.
Вот это, кстати, интересный кейс. Было бы интересно его тестировать. В текущем варианте мы этого не можем сделать, так как чтобы протестировать OTA, надо собрать еще одну новую версию и сделать патчи с текущей версии на новую. Я полагаю, этот кейс обязательно входит в финальное ручное тестирование апдейтов, которые уходят пользователям.
У нас в принципе нет механизмов даунгрейда версии. Нужен даунгрейд — бэкап данных/erase-install/восстановление бэкапа. Ну и все прекрасно понимают, что то что мы тестируем — позволяет поймать то, что билд совсем сломан, а не проверить то, что он хороший. Учитывая, что главные каналы обновления получают свежие сборки один раз в день, это просто ответ на вопрос, могут ли разработчики продолжать работать на сегодняшнем билде или лучше остаться на предыдущем.
Ну уж скажите, дичь. Давайте я расскажу вам, как это все живет у нас.

Для начала масштаб проблемы. У нас пяток классов устройств, у каждого — своя система. Одновременно для каждой системы ведется разработка над текущим релизом, следующим мажорным релизом и опционально следующим мажорным релизом + 1. Помимо этого есть минорные релизы, над котороыми работа может начаться одновременно с мажорным. Плюс специальные ветки для бета-версий, фиксов безопасности и отдельные ветки для фабрик, чтобы не показывать им весь софт до релиза. Это все дает примерно с десяток активных каналов разработки для каждого класса устройств. Примерно каждый год выходит несколько новых моделей почти во всех классах, поддержка старых осуществляется в течение нескольких лет. Это дает до нескольких десятков поддерживаемых моделей устройств на класс. У каждой системы есть несколько вариантов, для пользователей, для фабричного тестирования, для разработчиков, etc. Итого мы ежедневно получаем примерно 30-50 сборок систем в день и примерно 100 моделей устройств, на которых нужно проверить, что интересующие нас варианты систем хотя бы базово работают. Сейчас у нас больше 250 устройств, которые висят подключенными на почти трех десятках серверов и работают в CI. Осложняется дело необходимым на все это временем. Сборка всех изменений за сутки занимает примерно 6-8 часов, сборка всего — 13 часов. Еще 2-4 часа на то, чтобы смастерить образы системы для всех вариантов и для всех устройств. Отдельная история про построение OTA патчей и загрузку всего этого дела в архив, это идет в фоне и может занимать до суток. erase-install на одно устройство занимает примерно полчаса. Минимальный набор тестов еще минут 15.

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

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

Ну и да, мы единственная команда, которая проверяет все поддерживаемые устройства. Правда и набор тестов у нас скудный. Чтобы его пройти образ должен успешно установиться на устройство, не жрать 100% cpu, не крешиться в цикле, а процесс UI должен запуститься и не падать. Мы буквально отвечаем на вопрос «а пригоден ли билд к дальнейшему тестированию?», зато для всего.

У других команд есть всевозможные автотесты на функциональность, они работают на том же технологическом стеке, но на другом пулле устройств и они проверяют, как правило, одну модель для каждого SoC. Полностью же покрыть весь софт автотестами не реально — слишком быстро происходят изменения. В ручную тестируется просто большая часть системы.
Понятно, чем вдохновлялись дизайнеры этих роботов… images.app.goo.gl/acEdUL6817wtPx8H8
Весьма не абстрактного, а очень даже популярного и широкоиспользуемого. И этот фреймворк только-только хочет перестать поддерживать компиляцию без C++11. Так что вкоммитить такое в него будет сложно. Разве что под каким-нибудь фиче-флагом. Ну или будет жить в форке.
Прошу прощения, был не знаком с N3599. Если его использовать, то все действительно проще пареной репы.

К сожалению, несмотря на то, что это поддерживается в gcc и clang, насколько я понял, это предложение до сих пор не вошло в стандарт (все, что я смог найти, говорит о том, что это предложение сейчас в статусе Open и вообще не обсуждалось комитетом с 2015 года). Если переключить в вашем примере компилятор на последний доступный msvc, то он не скомпилирует этот код, причем с довольно забавным набором ошибок.

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

Если же использовать тот literal operator, который есть в стандарте, то нужно действительно повозиться с тем, чтобы вывести содержимое этого литерала в аргументы шаблона. Мне кажется, что это все-таки реально сделать в constexpr, но я в этом не уверен.
Я не стал писать эту часть, потому что сами по себе применения получаются очень интересными и стоят отдельного поста :). Ну и прежде чем о них рассказывать хочется сделать так, чтобы было что показывать.

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

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

Information

Rating
6,381-st
Date of birth
Registered
Activity

Specialization

Десктоп разработчик
Старший
From 100,000 €