Обновить
12

Пользователь

2
Подписчики
Отправить сообщение

О какой жизни речь в статье?

Slackware 15.0 х86 с Xfce. 350 Мб потребления на Aser Aspire One 1 GB DDR2 Ram, оставшееся - контроллер умного дома на Java в Docker.

Windows 11 IoT х64 на Asus M50Vn - Core2Duo+4GB DDR3. 1-5 вкладок в Хроме вполне рабочие для серфинга. Больше - свопает.

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

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

Понял, спасибо.

Именно так. Ну и не смущаясь утащу из вики "Microsoft announced in November 2005 that it would co-sponsor standardization of the new version of their XML-based formats through Ecma International as "Office Open XML".

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

Когда принимали OOXML все радовались, что избавятся от бинарных форматов MS Office, а по факту выяснилось, что внутри XML - бинарные блобы. Ну так стандарт то надо не только на презентациях оценивать, а например по референсной реализации, пусть медленной и неоптимальной, но полной. Тут конечно еще играет роль размер стандарта - 5к страниц не каждый осилит. Но что мешало декомпозировать до управляемого размера и принимать частями.

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

К слову - я сторонник ребейзов. И полезность мерджей в повседневной работе для меня сомнительна. Есть там специальные случаи, но в дев ветку - ребейз ван лав.

 Получается, что описание диффа старое, а код в нем новый, но это является нормой в классическом подходе.

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

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

Вот тут я не понимаю. В чем разница в целях разных ребейзов?

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

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

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

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

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

Ребейзы делают с какой-то конкретной целью. Чаще всего аккуратно и воспроизводимо слить атомарные изменения, чтобы сохранить историю. Это очень веская причина не создавать сломанные состояния проекта по дороге, которые починены последним искусственным обратным-дифф коммитом.

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

P.S. Да не оскорбятся хранители чистоты языка за использование заимствований...

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

CMake достаточно многословный, и от проекта к проекту, от компонента к компоненты одни и те же функции будут использоваться постоянно. Я не вижу смысла в добавлении анемичной абстракции, и сопутствующего инструментария, если можно просто 100 раз использовать add_target, target_include_directories, etc... Боязнь дублирующихся параграфов - это не DRY. А в больших проектах, рано или поздно появится тот черный лебедь, на который эта абстракция не налезет из-за одного специального флага под Макось. И с этого момента начнется разложение и вонь системы сборки через добавление флагов, опций, аргументов и прочего тюнинга.

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

Если хочется все-таки загнать себя в рамки предопределенной сборки компонентов, я бы использовал внешний лаунчер как точку входа для системы сборки, например шелл, или даже минимальный мейкфайл, который используя предложенные json описания сгенерирует нормальные CMakeLists.txt для каждого компонента используя более удобный инструмент - Jinja, Python, выберите любой приятный генератор по шаблонам. CMakeLists.txt верхнего уровня можно вручную написать с нужными опциями, или тоже генерировать. И только потом передавать сборку в руки собственно CMake, например даже с СMakePresets.txt. Использовать CMake для развертывания самого себя изнутри собственно проекта - это будет очень больно при поддержке кроссплатформенной сборки, создаст трудности по декомпозиции компонентов проекта от компонентов системы сборки, и увеличивает сложность в поддержке.

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

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

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

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

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

Время      -----------Past--------------<----Present---->-----------Future-------

Simple     -----o-----------------------------------o------------------------o--- 
Continious ---------xxxxxxx---------------------xxxxxx---------------xxxx--------
Perfect    ------------xxxx]---------------------xxxx]------------------xxx]-----
Perf.Cont. ---------[xxxxxx------------------[xxx-----------------[xxxx----------

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

И в обратную сторону аналогично, видя would had been drinking, понимает, что тут условность продолжающегося процесса, который тем не менее уже в прошлом и почти забыт.

Что только не придумают, лишь бы TOTP не внедрять.

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

Чтобы не тратить всуе лишнее процессороне время и не писать лишний код на разворот байтов это многобайтовое поле следует передавать в формате little-endian.

А микроконтроллеры чаще little-endian? Контринтуитивно передавать куда-то байты не в сетевом порядке байт.

pyscaffold? Да сотни их для питона...

Для себя нашел следующее решение, не зависящее от вчено-изменяющейся инфраструктуры инструментов. environment.yaml для независимого от хоста окружения и не Pip зависимостей или Pip пакетов, но с бинарными запчастями. Потому что например использовать numpy в Ubuntu AMD CPU, а девелопить в MacOS M4 - то еще развлечение со сборкой из исходников. setup.cfg где отдельно прописаны пакеты для основного модуля, и дополнительные, подлежащих установке через package[extra-name] синтаксис, например pip install -e .[test] сделает текущий модуль доступным для редактирования на месте, установит все нужные запчасти. DevOps (или пользователь) берет модуль, выясняет своими путями какие версии пакетов его устраивают и делает requirements.txt из 10 строк + constaints.txt для своего конкретного деплоя.

Автор, как же ты хорош. Ждем раскрутку новости в СМИ без фактчекинга. LLMки уже отравлены.

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

Миниджек только для ушей, или контакт микрофона тоже имеется?

Поясните следующие моменты, пожалуйста.

Раз 3,5мм джек отсутствует, можно ли авиапереходник использовать вместо него для подключения к обычному выходу гарнитуры\наушников. Что по функционалу в таком подключении - работает в режиме гарнитуры или только как наушники? Можно ли обычный USB-С на Джек адаптер использовать?

При подключении через USB, только подзарядка, или распознается как аудиоустройство? Что по функционалу оного?

При любом проводном подключении - что по активному шумодаву, работает ли вообще вся электронная начинка, или уши переходят в пассивный режим тупой гарнитуры(или вообще просто наушники) за 200 рублей?

При использовании, происходили ли баги, когда наушники переходят из аудиорежима со всеми наворотами в режим гарнитуры, портя качество звука в целом(известная родовая травма драйверов и аудиотракта Bluetooth), и застревают в нем до перезапуска. У меня на XM5 такое на MacBook происходит, если в видеозвонок подключаться, во время прослушивания музыки.

Что по влагозащищенности? XM5 даже под небольшим дождем нельзя носить, они дырявые.

Уши потеют, если спортом заниматься в наушниках? Насколько прочно сидят на голове для бега или наклонов например.

Заменить стандартный SQL вот на это - shared_trip_rate: (_.shared_match_flag == 'Y').mean() ? Онбординг новых сотрудников сразу перестает быть томным....

Начну с второго вопроса.

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

Более практические проблемы конкретно с YAML включают в себя трудности форматирования (например как тут https://stackoverflow.com/questions/3790454/how-do-i-break-a-string-in-yaml-over-multiple-lines, 63 способа выстрелить себе в ногу блоком текста); отсутствие предсказуемости и автоматической валидации(линтер\компилятор\любой другой способ избавить меня от рутины проверки каждого отступа и структуры); неуправляемая гибкость по комбинированию типов данных: в вашем же примере для опции require_unimplemented_servers: может возникнуть false, "false", False; аналогичная история с числами в кавычках (гиперболизированно, но по делу https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell, перевод https://habr.com/ru/articles/710414/, дополнительно https://habr.com/ru/companies/redhatrussia/articles/462125/, хотя есть контрпример https://habr.com/ru/articles/834270/). Как альтернативу продвигают TOML, который те же яйца только в профиль. Статьи на Хабре за и против вроде были, но не смог найти, извините.

Хватит про сам формат, он все-таки лучше чем ничего или XML. Перейду к сути критики: кодогенерация из proto файлов как отдельный процесс и инструмент для него.

Тут есть несколько проблем. Для начала, искусственное отделение самого процесса кодогенерации от процесса сборки. proto файлы представляют собой интерфейс взаимодействия, и по определению будут использоваться двумя сторонами взаимодействия. Раз уж мы тут про gRPC, то ограничиваться только Go мы не будем. Мы же можем генерировать и для Python тоже, как вы и указали в возможностях утилиты.

Для Python проектов сборка может включать тривиальный Makefile, environment.yaml для Conda, один или несколько requirements.txt. Генерацию вроде бы имеет смысл положить прямо в Makefile. Тогда разработка становится прямолинейным процессом - сделать окружение, разрешить зависимости, кодогенерация, код, тест, упаковка. Например как в этом иллюстративном примере, собранном из двух разных реальных проектов, за минусом пляски вокруг относительных путей генерированного и основного кода):

generate:
 mkdir -p gen/compiled_protos/
 python -m grpc_tools.protoc --proto_path=$(proj_dir)/protos/protobuf-spec/api --python_out=gen/compiled_protos/api --grpc_python_out=./gen/compiled_protos/api $(proj_dir)/protos/protobuf-spec/api/.proto 
... 
dist/fancy-named-package-.whl: generate
 (cd fancy-named-package && pip install -r reqs/devel.txt && pip install -e '.[testing]' && pytest .)
 (cd fancy-named-package && pip install -r reqs/build.txt && python -m build --no-isolation  --outdir ../dist)

Собрали для Python, вернемся к Go.

Опять же, скорее всего у нас красиво огранизованный проект, pkg, cmd, vendor вот это вот все. Скорее всего мы даже можем go build ./... и go test ./... прямо в процессе написания кода. Чтобы это работало как надо, все зависимости мы корректно прописываем в go.mod через go get, и вообще не стесняемся использовать доступный из коробки инструментарий, который и автоматически иногда запускается, а чтобы каждый раз в командную строку не лазить, или скорее, чтобы CI/CD не переизобретать, сваяем тривиальный Makefile:

dependencies:
 go install github.com/golang/mock/mockgen@v1.6.0
 go install github.com/golang/protobuf/protoc-gen-go@v1.5.4
 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
 go install github.com/vektra/mockery/v2@v2.52.2
generate: FORCE dependencies
 protoc --go_out=plugins=grpc:api/grpc-protos/api_1 -I api/grpc-protos/api_1/ api/grpc-protos/api_1/*.proto
 protoc --go_out=plugins=grpc:api/grpc-protos/api_2 -I api/grpc-protos/api_2/ api/grpc-protos/api_2/*.proto
 protoc --go_out=plugins=grpc:api/protobuf-spec/api_3 -I api/protobuf-spec/api_3 api/protobuf-spec/api_3/*.proto

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

Важным моментом на этом этапе является, что управление proto файлами происходит независимо от любого кода, их использующего, но генерация происходит по месту использования, и сразу со всеми запчастями. В моем примере api_2 без всяких проблем может использовать запчасти api_1, они как-то связаны и это отражено в их взаимном расположении, а api_3 - самодостаточный, как они к нам в репозиторий приехали, уже не важно на этом этапе. Git submodules, subrepo, отдельные загрузки, подложили вручную, curl http://*.tgz, любой вариант, который для вас работает. Мы где-то между git submodule и git subrepo пока.

Переходя к пристальному рассмотрению обсуждаемого инструмента, обнаруживаем, что секция с зависимостями частично забирает на себя работу либо go get ..., либо настройки окружения сборки, которая для Python совсем не совместима с Go. Как в вашем YAML указать пакеты для pip в deps, а если у меня функциональные тесты API на C#, winget поддержку стоит добавлять?

Далее, многоуровневая система конфигурации консольного инструмента, на мой субъективный взгляд, сложнее чем 3-5 аргументов командой строки, значения которых не меняются все время жизни проекта, а искусственное введение абстракции не добавляет ценности к использованию. А при смене мажорной версии генератора, преобразование YAML тэгов в командлайн потребует обновления easyp. Я не жду и не требую 100% поддержки опен-сорсного проекта, но и зависеть от инструмента, который для меня всего лишь трансформирует один текст в другой не видится мне рациональным.

Отдельно упомяну про линтер - не критикую, не комментирую. Не имею опыта и необходимости в линтинге proto файлов. Как-то встроенных в редактор возможностей и ошибок компиляции или тестов хватало для поддержки вменяемости содержания. Опять же, API-first предполагает усиленное внимание на содержание и формальность протокола. Тут может и есть смысл во внешнем инструменте, который делает хорошо свою работу.

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

Банально допускаю крайний случай, когда proto файлы отдельно обрабатываются до генерированного бойлерплейта, который как отдельный пакет живет и притаскивается через go get, или pip install. Такое явное игнорирование неписаного правила не хранить генерированный код может быть полезным для строгого отслеживания версий, когда на каждый релиз надо точно знать какие версии API реализованы и поддерживаются, и обновлять API независимо. go get example.com/api_1/client-boilerplate@v2.1.1 в зависимостях отлично отслеживается разными инструментами сканирования целостности артефактов(BlackDuck, DependaBot, тысячи их...) для разных целей.

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

Вот это утверждение не совсем понял, попробую ответить, если не угадал, поясните вопрос, пожалуйста.

Если под зависимостью здесь понимается не go/Python модуль/пакет, а стопка proto файлов, которой нужно еще 5 разных стопок, то да, такими зависимостями надо как-то управлять, а из коробки такого инструмента нет. Но тут, я бы пересмотрел саму организацию proto файлов и изучил причину случившегося. Не произошло ли чрезмерное или надуманное разделение связанных запчастей, не введены ли лишние слои абстракций, которые не добавляют ценности, и прочие организационные и архитектурные проблемы, которые все равно рано или поздно аукнутся. Логически, proto файлы, сколько бы их не было, представляют то, с чем более полезному рабочему коду взаимодействовать, и если нельзя из них быстро и дешево получить бойлерплейт, то что-то пошло не так. Может и внешняя генерация ВСЕГО бойлерплейта одним махом для конкретного языка и хранение как отдельного артефакта имеет смысл. А уж каждый отдельный репозиторий импортирует нужную себе часть.

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

1
23 ...

Информация

В рейтинге
7 474-й
Зарегистрирован
Активность