не совсем представляю, как из Java на бэкенде напрямую работать с DevTools-протоколом — с этой темой нужно срочно разбираться.
Рекомендую посмотреть на проект github.com/webfolderio/cdp4j (правда он под AGPL лицензией и вроде как они хотят денежку, если нужно вставлять в проприетарщину). Мой опыт говорит за то, что для нужд парсинга WebDriver не годен, нужно работать с DevTools Protocol.
В этой статье даются вредные советы новичкам, я считаю.
В гите можно делать сотнями разных способов, а новичкам надо рассказывать, как делать правильно. А то ведь и вправду начнут мёржить изменения во все стороны.
На мой взгляд, до новичков очень важно доносить следующее:
Говорить о Git нужно всегда в контексте принятого у вас процесса разработки и CI/CD. Git работает в синергии с CI/CD. Если в компании есть Git и нет CI/CD, то это неэффективность в квадрате, т. к. тогда уж лучше применять более простой SVN.
Процесс должен быть построен так, что главная ветка должна быть защищённой от пуша. В неё можно только мёржить, и только такой код из других веток, который прошёл quality gates вашей CI/CD системы. Таким образом, в вашем мастере должен быть гарантированно стабильный код, и фичи, разработка которых гарантированно завершена.
Ни в коем случае не надо мёржить во все стороны (впрочем, если у вас правильный процесс с защищённым мастером, то не очень-то вы и хаотично помёржите в мастер). Не надо бояться rebase. Отведя локальную ветку с выполняемой вами задачей, работайте с ней и выполняйте rebase часто, пере-отводясь от верхушки мастера по мере поступления новых стабильных коммитов в мастер.
Выполняя частый rebase, вы «переносите боль на начало». Откладывая всё до финального merge, вы «откладываете боль на потом». Как и в других аналогичных инженерных практиках (например, связанных с автотестированием), общее количество боли будет меньше в первом случае.
Завершив работу, открывайте Pull Request, успешное закрытие которого сопровождается слиянием с мастером. Условием возможности слияния обязательно должно быть прохождение quality gates вашей CI/CD системы и желательно code review / approval от других разработчиков
Ничего монструозного в rebase не нахожу. Просто многие почему-то пугаются этой операции, слабо понимая её семантику. Частый rebase локальной ветки по основной ветке — это «гигиеническая процедура». Делай его часто, каждый раз, когда в основной ветке появляются новые коммиты и 1) меньше будет конфликтов, 2) возникающие конфликты будут выявляться и устраняться на ранней стадии
По-сути, выбор rebase vs merge — это аналогично тому, как с автотестами/ручными тестами: «перенести боль на начало» vs «отложить боль на потом» (в первом случае общее кол-во боли будет меньше).
Естественно, надо понимать, что rebase — это то, что ты делаешь в локальном репозитории, merge — это вливание готовой ветки в мастер по завершении фичи.
А ребэйз — считай, по черри-пику на каждый коммит исходной ветки на новый корень. И каждый чреват конфликтами.
Ну так надо как можно чаще рибейзить свою ветку — тогда меньше будет проблем.
например, дописывается в конец один и тот же файл. У меня это скрипт миграции.
Мне кажется, что это общая проблема, связанная именно со скриптами миграции. Они плохо версионируются, потому что скрипт миграции — не исходный код, а лог изменений. Его или принципиально по-другому версионировать надо (но я не слышал, чтобы какие-то системы контроля версий специально поддерживали такие логи), либо идемпотентный DDL мог бы сильно выручить (но он тоже пока нигде хорошо не реализован)
Конкретно в нашем случае лучший вариант — это использование in-memory СУБД H2, которая умеет моментально стартовать. К счастью, мы специально поддерживаем совместимость с базой H2 для юнит-тестов, но UI-тесты мы гоняем на PostgreSQL, что неверно. Мне подсказали, что совершенно нормальный вариант — заиметь дамп H2-базы с тестовыми данными и восстанавливать его перед каждым UI тестом.
Иногда совместимость с H2 невозможна. В этом случае, как я слышал, хорошим решением является использование RAM-дисков: их образ можно довольно быстро восстанавливать из файла и уже с RAM-диска запускать настоящую СУБД типа PostgreSQL или Oracle — говорят, это работает.
И я тоже скажу в защиту Jenkins! Написанное в секции про выступление Олега — написано с точки зрения очень базового пользователя Jenkins, стремящегося к улучшению своего CI-сетапа, и ни в коем случае не претендует на экспертную оценку Jenkins как такового или уровня доклада Олега как такового.
Потому, что куда-то я мышью ткнул не туда, вот почему) я изначально ставил хаб «тестирование», но сегодня его не обнаружил и только что даже с администратором говорил, не они ли с хаба сняли. Нет, не они. Поправил, есть теперь хаб «тестирование» )
Будете ли вы пользоваться TestContainers? Понравилась идея, есть сомнения?
В этом году мы довольно быстро внедрили TestContainers для проекта github.com/CourseOrchestra/celesta. Сергей про нас уже знает, общались на конференциях :-) Мы делаем систему, которая должна себя одинаково вести на разных типах СУБД. Соответственно, у нас есть набор тестов, который надо прогонять, по очереди присоединяясь к реальным SQLServer, Oracle и PostgreSQL (сама суть нашего проекта делает использование H2 для полной проверки невозможным). До TestContainers эти тесты требовали долгой ручной настройки среды (установка баз, прописывание конфигураций в бесконечных пропертях), и в полном объёме выполнялись (если выполнялись) на машине у единственного разработчика, где всё хозяйство было настроено. На CI выполнялся только H2. Ну и периодически у пользователей выплывали баги, которые мы могли бы поймать на имеющихся тестах, если бы они выполнялись.
После внедрения TestContainers требования к среде, где должна запускаться Maven-сборка проекта, сводятся к трём пунктам: JDK, Maven, Docker. Всё! Мы гоняем их всех на CI и горя не знаем.
Может быть, подойдёт не всем, но для нашего кейса TestContainers оказались тем, «что доктор прописал».
По-моему громкость была просто запредельная. Желающие пообщаться на темы программирования были вынуждены выйти в лобби ) Потише был бы звук — лучше бы пошло, имхо)
1) Не так плох был гарнир, как тот факт, что замешкавшимся к началу второй очереди обеда остался лишь один голый гарнир! Этот баг точно следует пофиксить :-)
2) Оба доклада Хорстманна мне понравились. Хотя его манера и лишена «зажигательности», но чувствуется очень твёрдая рука опытного преподавателя. Я был бы рад его видеть на ваших конференциях.
Относительно дропа: я об этом в статье не написал, но на мой взгляд, самым лучшим решением было бы во время выполнения CONVERGE дропать только такой столбец, который содержит NULL (или DEFAULT-константу) для всех строк. Иначе — ошибка CONVERGE, как и для всякой иной ситуации, когда наличествующие данные не позволяют произвести изменение структуры.
Именно такая логика, например, реализована в ERP-системе MS Dynamics NAV при «импорте таблиц» в базу данных. Таким образом ты в NAV новую версию структуры таблицы не заимпортируешь, пока в старой версии данные не подготовишь к миграции. В Celesta реализовано так: ничего не дропается. Но так как Celesta идёт в паре с фреймворком для доступа к данным, там просто столбец и таблица пропадают из API для доступа к данным. Т. е. в базе они остаются, но из кода ты ими пользоваться уже не сможешь. Уже постфактум ты их можешь отмигрировать и дропнуть.
Относительно begin-after-converge: если сделать как Вы предлагаете, то произойдёт в одном месте смешение идемпотентного (декларативного) и императивного кода. Декларативный код — он для всех сценариев один и тот же, а императивный — при одном сценарии нужен один код миграции, в другом случае — другой код… в итоге потеряется стройность DDL-скрипта, он забьётся всё разрастающимся кодом миграции. Их надо как минимум разделять. Мне кажется, задача совмещения changeset- и идемпотентного подхода ещё ждёт своего изящного решения.
Чем больше в этой отрасли, тем больше понимаю, насколько у всех всё по-разному)) У нас например без юнит-тестов было бы совсем кисло, при правильном подходе они довольно легки для написания и запуска. Но, опять же: у всех всё по-разному, разные сценарии, разные потребности. Наше нынешнее состояние — это результат многолетних мучений и эволюции и в итоге мы наполовину работаем на «доморощенных» инструментах.
Мы живём на shared-базе. Если наш гипотетический Дима не взял код с утра (а shared-база уже сконвертировалась в более свежую ревизию), уже при запуске приложения у Димы свалится: «Дима, твоя база имеет более свежую ревизию, чем приложение, которое ты пытаешься запустить»). Дима делает адейт с контроля версий и ок.
Ясно, значит у вас проблема миграций решена в такой комбинации: MSSQL, Entity Framework (подсмотрел в википедии, что это ORM для .NET — следовательно, видимо, приложение пишете на .NET), плюс свои собственные наработки по поводу того, чтобы определить правильный порядок накатки.
Интересно узнать вот что: как у вас обстоит дело с модульным тестированием процедур, изменяющих данные в базе? Какой подход используете или не делаете юнит-тесты таких процедур вообще? Потому что история про «несовместимый код», возникающий в базе «в середине дня» — это история про отсутствие юнит-тестов, выполняемых в локальном в development environment-е программиста прежде, чем он выкатит изменения на персистентную базу.
В Java-мире есть великий и ужасный H2 in-memory, но на ней не потестируешь процедуры. Хотя вот у нас, например, по определению процедур и нет, поэтому мы активно для юнит-тестов юзаем H2. Есть TestContainers, но они появились относительно недавно и я сам только планирую их попробовать. Что-то слышал про запуск СУБД на RAM-дисках. Все эти подходы предполагают, что в момент запуска юнит-тестов у программиста поднимается «быстрая и пустая» копия базы на основе самого свежего DDL, поэтому мигрировать ничего не надо, она существует в течение выполнения юнит-теста и «забывается».
> Ну и вьюшки и прочие хранимки мы не кладем в миграции.
А с ними как поступаете — периодически прогоняете полные «CREATE OR REPLACE VIEW»-скрипты?
> И говорим остальным 10-ти девелоперам типа «когда вольете к себе последний код, вот этот скриптик накатите, а то у вас всё крешится будет. Так что-ли?
А у вас 10 девелоперов сидят на 10 копиях базы? Хмм, везде где я работал, обычно development-база одна и shared, и периодически копируется с прода. Ну вот так вот всё у всех по-разному.
Рекомендую посмотреть на проект github.com/webfolderio/cdp4j (правда он под AGPL лицензией и вроде как они хотят денежку, если нужно вставлять в проприетарщину). Мой опыт говорит за то, что для нужд парсинга WebDriver не годен, нужно работать с DevTools Protocol.
В гите можно делать сотнями разных способов, а новичкам надо рассказывать, как делать правильно. А то ведь и вправду начнут мёржить изменения во все стороны.
На мой взгляд, до новичков очень важно доносить следующее:
По-сути, выбор rebase vs merge — это аналогично тому, как с автотестами/ручными тестами: «перенести боль на начало» vs «отложить боль на потом» (в первом случае общее кол-во боли будет меньше).
Естественно, надо понимать, что rebase — это то, что ты делаешь в локальном репозитории, merge — это вливание готовой ветки в мастер по завершении фичи.
Ну так надо как можно чаще рибейзить свою ветку — тогда меньше будет проблем.
Мне кажется, что это общая проблема, связанная именно со скриптами миграции. Они плохо версионируются, потому что скрипт миграции — не исходный код, а лог изменений. Его или принципиально по-другому версионировать надо (но я не слышал, чтобы какие-то системы контроля версий специально поддерживали такие логи), либо идемпотентный DDL мог бы сильно выручить (но он тоже пока нигде хорошо не реализован)
Да, наверное, это сложнее, чем ракету Falcon Heavy создать ))
www.cnews.ru/news/top/2018-01-30_schetnaya_palata_gis_zhkh_ne_gotova_k_zapusku
Можете назвать медианные значения для этих параметров? Ведь когда речь идёт о рейтингах, интереснее не средние, а медианные значения.
Иногда совместимость с H2 невозможна. В этом случае, как я слышал, хорошим решением является использование RAM-дисков: их образ можно довольно быстро восстанавливать из файла и уже с RAM-диска запускать настоящую СУБД типа PostgreSQL или Oracle — говорят, это работает.
В этом году мы довольно быстро внедрили TestContainers для проекта github.com/CourseOrchestra/celesta. Сергей про нас уже знает, общались на конференциях :-) Мы делаем систему, которая должна себя одинаково вести на разных типах СУБД. Соответственно, у нас есть набор тестов, который надо прогонять, по очереди присоединяясь к реальным SQLServer, Oracle и PostgreSQL (сама суть нашего проекта делает использование H2 для полной проверки невозможным). До TestContainers эти тесты требовали долгой ручной настройки среды (установка баз, прописывание конфигураций в бесконечных пропертях), и в полном объёме выполнялись (если выполнялись) на машине у единственного разработчика, где всё хозяйство было настроено. На CI выполнялся только H2. Ну и периодически у пользователей выплывали баги, которые мы могли бы поймать на имеющихся тестах, если бы они выполнялись.
После внедрения TestContainers требования к среде, где должна запускаться Maven-сборка проекта, сводятся к трём пунктам: JDK, Maven, Docker. Всё! Мы гоняем их всех на CI и горя не знаем.
Может быть, подойдёт не всем, но для нашего кейса TestContainers оказались тем, «что доктор прописал».
2) Оба доклада Хорстманна мне понравились. Хотя его манера и лишена «зажигательности», но чувствуется очень твёрдая рука опытного преподавателя. Я был бы рад его видеть на ваших конференциях.
Именно такая логика, например, реализована в ERP-системе MS Dynamics NAV при «импорте таблиц» в базу данных. Таким образом ты в NAV новую версию структуры таблицы не заимпортируешь, пока в старой версии данные не подготовишь к миграции. В Celesta реализовано так: ничего не дропается. Но так как Celesta идёт в паре с фреймворком для доступа к данным, там просто столбец и таблица пропадают из API для доступа к данным. Т. е. в базе они остаются, но из кода ты ими пользоваться уже не сможешь. Уже постфактум ты их можешь отмигрировать и дропнуть.
Относительно begin-after-converge: если сделать как Вы предлагаете, то произойдёт в одном месте смешение идемпотентного (декларативного) и императивного кода. Декларативный код — он для всех сценариев один и тот же, а императивный — при одном сценарии нужен один код миграции, в другом случае — другой код… в итоге потеряется стройность DDL-скрипта, он забьётся всё разрастающимся кодом миграции. Их надо как минимум разделять. Мне кажется, задача совмещения changeset- и идемпотентного подхода ещё ждёт своего изящного решения.
Мы живём на shared-базе. Если наш гипотетический Дима не взял код с утра (а shared-база уже сконвертировалась в более свежую ревизию), уже при запуске приложения у Димы свалится: «Дима, твоя база имеет более свежую ревизию, чем приложение, которое ты пытаешься запустить»). Дима делает адейт с контроля версий и ок.
Интересно узнать вот что: как у вас обстоит дело с модульным тестированием процедур, изменяющих данные в базе? Какой подход используете или не делаете юнит-тесты таких процедур вообще? Потому что история про «несовместимый код», возникающий в базе «в середине дня» — это история про отсутствие юнит-тестов, выполняемых в локальном в development environment-е программиста прежде, чем он выкатит изменения на персистентную базу.
В Java-мире есть великий и ужасный H2 in-memory, но на ней не потестируешь процедуры. Хотя вот у нас, например, по определению процедур и нет, поэтому мы активно для юнит-тестов юзаем H2. Есть TestContainers, но они появились относительно недавно и я сам только планирую их попробовать. Что-то слышал про запуск СУБД на RAM-дисках. Все эти подходы предполагают, что в момент запуска юнит-тестов у программиста поднимается «быстрая и пустая» копия базы на основе самого свежего DDL, поэтому мигрировать ничего не надо, она существует в течение выполнения юнит-теста и «забывается».
А с ними как поступаете — периодически прогоняете полные «CREATE OR REPLACE VIEW»-скрипты?
> И говорим остальным 10-ти девелоперам типа «когда вольете к себе последний код, вот этот скриптик накатите, а то у вас всё крешится будет. Так что-ли?
А у вас 10 девелоперов сидят на 10 копиях базы? Хмм, везде где я работал, обычно development-база одна и shared, и периодически копируется с прода. Ну вот так вот всё у всех по-разному.
А кстати какая у вас СУБД?