Лирическое отступление
Однажды много лет назад я решил почитать "Искусство войны" Сунь Цзы. Ведь это произведение до сих пор является самой влиятельной книгой по стратегии в мире. Его принципы применимы не только в военной сфере, но и в бизнесе, юриспруденции, спорте и даже программном обеспечении. Но когда я открыл его и начал читать, то обнаружил, что многие его утверждения настолько очевидны и банальны, что о них не имеет смысла даже говорить:
Кто – еще до сражения – побеждает предварительным расчетом, у того шансов много; кто – еще до сражения – не побеждает расчетом, у того шансов мало. У кого шансов много – побеждает; у кого шансов мало – не побеждает; тем более же тот, у кого шансов нет вовсе.
Я был разочарован. И только гораздо позже смог осознать, что в этих банальных, простых и очевидных утверждениях кроется вся суть. И самое сложное в том, чтобы полностью осознать их и только после этого применить на практике.
Данная статья ни в коем случае не претендует на уровень "Искусства войны", но содержит много банальных и очевидных советов. Так сказать, сборник граблей правил, облегчающий разработку корпоративного программного обеспечения, которым я и хочу поделиться.
Дисклеймер
Я не претендую на истину в последней инстанции. Если вы не согласны с чем-либо - это ваше личное мнение, и я его уважаю. Надеюсь, вы будете уважать мое.
Все советы и указания в статье опциональны и носят рекомендательный характер.
Некоторые советы могут противоречить нюансам корпоративной этики или политикам, принятым в вашей компании. Будьте внимательны и помните, что правилам, установленным в компании, лучше следовать (все иное - на ваш страх и риск).
Кто же такой Воин?
UPD (спасибо @Sergey-Titkov):
Воин (в контексте статьи) - отличный специалист с точки зрения его технических и прочих навыков. Он отлично знает свой стек технологий и предметную область, в совершенстве владеет софт-скиллами. Его единственный минус: воин действует как изолированная единица, не учитывая нюансы работы в команде.
У воина есть Честь и Кодекс. Следуя им и не принимая никаких компромиссов, воин огнем и мечом искореняет любую несправедливость, встреченную на его пути. Воин не пытается навредить, он стремится сделать проект идеальным. Но, к сожалению, такой "Путь Воина" может привести к проблемам.
Воин в команде
Выделим четыре категории участников разработки:
Разработчик
QA-инженер
DevOps-инженер
Менеджер
Причем, под менеджером будем понимать не только непосредственное руководство, но и product-, project-менеджеров, а также все сопутствующие обязанности по руководству и организации бизнес-процессов: team- и tech-lead, scrum-мастер и различные менторские активности.
Разработчик-воин
Разработчик-воин является адептом совершенного кода, не приемлет legacy и временные решения и не готов идти на компромисс с собственным чувством прекрасного. Именно поэтому из лучших побуждений он переписывает критичный участок кода, полностью и безоговорочно "нанося непоправимое добро" (от автора: большое спасибо коллеге за весьма точное выражение).
Пример
У вас есть система аренды транспортных средств, в которой есть описание транспорта:
public class Transport {
Wheels[] Wheels { get; }
CarBodyStyle BodyStyle { get; }
float EngineVolume { get; }
float BinVolume { get; }
}
Представьте, что код был написан в те далекие времена, когда электромобили и прочий современный транспорт не были популярны или вообще отсутствовали на рынке. Поэтому в описании транспорта есть понятие объема двигателя и объема бензобака.
Относительно электромобилей мы можем договориться, что объем бака = емкости аккумулятора, а объем двигателя = номинальной максимальной мощности в режиме длительной нагрузки. Однако, это вызывает множество вопросов:
как разница в единицах измерения повлияет на валидацию, расчеты стоимости, рисков и прочее?
как избежать пересечения логик? Например, как при наличии скидок на заправках не позволить арендовавшему электромобиль купить бензин по скидке? Или, например, не распространится ли скидка на электротранспорт на остальные виды?
при разнице в аренде (тарифных планах), как понять, какой тариф применим к арендованному транспорту?
как вообще отличить электромобиль от автомобиля на бензиновом двигателе?
что делать с гибридами?
и т.д.
А теперь допустим, что компания решает помимо электромобилей предоставлять в аренду прочий электрический транспорт: электросамокаты, гироскутеры, моноколеса, велосипеды с электроколесом и т.д.
В данном случае есть несколько компромиссных вариантов:
аккуратно расширить старые сущности новыми полями и расширить механизм добавлением обработки новых полей таким образом, чтобы старая логика не была затронута и не ломалась при получении расширенного объекта, а новая логика не пыталась обработать старый объект
добавить новый более универсальный механизм обработки параллельно старому, чтобы со временем плавно "пересадить" на него обработку всех сущностей, а старый вывести из использования
Однако, это все компромиссы. разработчик-воин не готов мириться и ждать, поэтому переписывает все и сразу.
Код стал более гибким, более качественным. Задача выполнена "наилучшим образом". Почему же никто не рад?
QA-инженеры вместо проверки конкретных сценариев конкретной части бизнес-логики вынуждены перепроверить множество пользовательских кейсов (а возможно, даже провести полный регресс-тест всей системы)
UPD (спасибо @sshmakov): Регулярный полный регресс системы - хорошая практика, когда он запланирован и выполняется как отдельная задача. Плохо, когда команда вынуждена проводить его незапланированно и после каждой задачи.DevOps вынуждены изменить CI/CD проекты для доставки вашего кода на production
Менеджеры, которые ожидали небольшое изменение, которое придет на production в течение короткого периода времени, вынуждены ждать его несколько месяцев и извиняться перед клиентами и соседними командами разработки, которым оно было заранее обещано.
QA-воин
QA-воин точно так же, как и разработчик, в стремлении к прекрасному способен упустить реальную потребность компании в максимально быстрой доставке изменений конечному пользователю.
покрыть автоматизированными тестами все возможные и невозможные кейсы (особенно это касается ситуаций, которые потенциально возможны на dev- и qa-окружении, но из-за определенной специфики никогда не возникнут на production)
переписать базовые механизмы работы с тестами в рамках тестирования определенной задачи (что тоже потребует отдельного review и тестирования)
посчитать все найденные баги сверхкритичными ошибками, блокирующими продвижение изменений дальше
UPD (спасибо @Mike-M): Для потребителя качество важнее скорости доставки изменений. Быстрая доставка изменений пользователю - требование не пользователя, а бизнеса. Здесь лишь описана ситуация, когда применима поговорка "лучшее - враг хорошего" и QA-воин теряет слишком много времени в стремлении изменить проект от "хорошего" к "лучшему".
DevOps-воин
DevOps-воин действует аналогично QA, задерживая доставку изменений, занимаясь следующими задачами:
полная переделка существующей инфраструктуры под новые реалии
перенос логики развертывания на последние технологии и паттерны, без учета того, что текущий бизнес-процесс не рассчитан на них и тоже потребует изменения
слишком рано обновляет версии используемого ПО, получая ошибки сборки, несоответствие версиям кода, а также малый объем документации и решений встреченных на последних версиях проблем (впрочем, это замечание относится ко всем "видам" воинов)
Менеджер-воин
В отличие от предыдущих участников, менеджер сопровождает проект на всех этапах разработки, следит за общей картиной, координирует взаимодействие внутри команды и между командами, старается соблюсти баланс ресурсов.
Менеджер-воин в стремлении все контролировать может броситься в крайности, что приведет к следующим результатам:
излишнее погружение в разработку проекта (вплоть до контроля кода на уровне каждого разработчика), в том числе самостоятельное участие в активностях, которые можно делегировать другим (например, самостоятельно участвовать во всех процессах вместо создания набора понятных правил, позволяющих организовать самоконтроль или взаимный контроль задач коллегами)
излишнее количество организаторских активностей (митинги и совещания, обсуждение проблем с участием людей, не вовлеченных в проект на данном этапе, излишне частая синхронизация знаний между командами и внутри нее)
обсуждение специфичных для определенного этапа вопросов на активностях, не предназначенных для этого (например, мозговой штурм проблем, возникших у разработчиков внутри команды, на демонстрационном митинге между командами)
излишнее повышение приоритета возникших проблем (например, вместо краткой переписки в формате "вопрос-ответ" в общем чате, назначить совещание и выдернуть на него всех членов команды)
Суть проблемы
Вы работаете в команде, где кроме вас есть другие специалисты, с которыми вы работаете над решением общей задачи вместе. И время выполнения задачи складывается из времени, затраченного всей командой, а не только вами.
Поэтому перед тем, как внедрять ваше безусловно гениальное решение, задайте себе следующие вопросы:
Какую проблему я решаю?
Как я могу решить задачу, оказав минимум влияния на систему?
Какую логику я затрону своими изменениями?
Какие изменения затрагивают общие механизмы? Могу ли я доставить их отдельно и заранее?
Что делать с прочими проблемами, обнаруженными в ходе решения текущей проблемы?
Что я могу изменить, не выходя за рамки затронутой бизнес-логики?
На первый взгляд все эти вопросы заданы с точки зрения разработчика, но на самом деле подойдут любой из вышеуказанных категорий. Разработчик планирует и вносит изменения непосредственно в код, QA-инженер - в автоматизированные тесты и процесс тестирования, DevOps - аналогично, в развертывание, а менеджер ставит задачи перед командой и организует взаимодействие (т.е. с точки зрения менеджера под "системой" понимается не только проект, но и сама команда).
Какую проблему я решаю?
Воин всегда хочет как можно меньше времени потратить на понимание задачи и как можно быстрее броситься в бой с шашкой наголо приступить к ее выполнению.
В простой задаче он не ищет подводных камней ("да здесь все понятно, все очевидно"), а в сложной не хочет разбираться ("ничего не понятно, сделаю по примеру, так быстрее и эффективнее").
Решение в том виде, в котором мы понимаем задачу без глубокого погружения, чаще всего неэффективно, а иногда даже неправильно.
Пример 1
Чаще всего хороший разработчик остановится на третьем или даже четвертом шаге, т.е. откатит изменения кода или накатит изменения для БД, если это возможно. Но вот до последнего шага без ретроспективы или вопросов от менеджера скорее всего не дойдет.
Мы привыкли писать код, а не налаживать процесс разработки. Зачем, если и так работает? В следующий раз будем внимательнее.
Вот только, если есть правила или, еще лучше, какой-то механизм синхронизации, то не понадобится быть внимательнее, все будет работать в любом случае.
Пример 2
Задачи от пользователя идут к разработчику через менеджеров и могут быть искажены на любом этапе (как пользователем, так и менеджером или самим разработчиком).
Пользователь и менеджер могут не знать возможностей и нюансов реализации систем, поэтому могут попросить то, что сделать невозможно, или выбрать не самый оптимальный путь.
Задача разработчика не в том, чтобы взять и сделать, что сказано, а в том, чтобы понять, что требуется, и предложить наиболее оптимальный вариант решения.
Как я могу решить задачу, оказав минимум влияния на систему?
Когда вы работаете над крупным проектом, который уже есть и работает на production, любое внесение изменений приводит к затратам ресурсов всей команды: тестирование, изменения со стороны DevOps, продвижение изменений через окружения до production с тестированием на каждом. Чем больше изменений, тем больше ресурсов команды будет потрачено.
Чаще всего мы вынуждены выбирать между более точечным исправление и более общим.
Общее исправление
Мы находим корень проблемы и правим именно его.
Плюсы
полноценное исправление: исправляет большинство сценариев, даже необнаруженные ранее, поэтому не приводит к затратам ресурсов команды в будущем;
не приводит к росту технического долга (при полноценном исправлении без заглушек и "оставим на потом"), а в редких случаях может уменьшить его;
гарантированное исправление: исправляется корень проблемы, а не "симптомы"
Минусы
занимает больше времени: внесение изменения в механизм может привести к необходимости изменения в местах его использования;
затрагивает много бизнес-логики: приводит к большим затратам ресурсов команды в ближайшей перспективе;
Точечное исправление
Проблема правится только в месте возникновения и(или) только для конкретного случая.
Плюсы
выполняется быстро, может быть использован в качестве hotfix;
затрагивает минимум бизнес-логики, что приводит к минимальным затратам ресурсов команды "здесь и сейчас"
Минусы
неполноценное исправление: прочие аналогичные ошибочные сценарии остаются неисправленными или даже необнаруженными, в будущем потребуется снова тратить ресурсы команды на их исправление;
негарантированное исправление: конкретный случай может оказаться лишь проявлением более крупной проблемы, требующей правки общего механизма, которая приводит к значительным затратам ресурсов команды;
рост технического долга: "пока что исправим так, а потом сделаем, как надо". Также стоит помнить, что технический долг увеличивает сам себя (накручивание костылей вокруг костылей), а также растет со временем.
Что же выбрать
Из всех вариантов решения нужно выбирать тот, который приводит к наименьшим суммарным затратам ресурсов команды как в текущее время, так и в перспективе.
Именно такой компромисс позволит вам максимально быстро доставлять код до production и занимать для этого минимум ресурсов команды.
Какую логику я затрону своими изменениями?
Каждая роль в команде предполагает определенный уровень знания о системе (проекте), но не больше.
Менеджеры должны знать систему с точки зрения бизнес логики
DevOps-инженеры должны знать систему с точки зрения ее развертывания плюс бизнес логику
QA-инженеры должны знать систему с точки зрения бизнес-логики плюс базовые нюансы реализации (некоторые таблицы в БД и их связи, Private и Public API, разметка UI для написания UI-тестов и так далее). Помимо этого QA-инженеры - эксперты в области тестирования системы
Разработчики должны знать систему практически полностью от бизнес-логики до архитектуры и реализации
Воин - самостоятельный боец. Он не задумывается о взаимодействии внутри команды и о том, чтобы облегчить выполнение задач остальным. Он считает, что на других ролях тоже должны быть воины, которые со всем справятся самостоятельно.
Каждый член команды может, но не обязан знать больше. Отсюда следующие выводы:
Разработчик
Только вы знаете, какая бизнес-логика затронута вашими изменениями.
Разработчик-воин выполнит задачу и отдаст ее на тестирование без пояснений. В итоге QA-инженер протестирует только те кейсы, которые описаны в задаче, хотя изменениями могли задеть и другие части системы.
После внесения изменения, разработчик должен выполнить следующие действия:
Сообщить менеджерам об изменении в бизнес логике или появлении определенных нюансов;
Сообщить QA-инженерам, какая логика задета, в идеале, уточнить кейсы, которые более критичны или появились в процессе изменения;
Сообщить DevOps-инженерам, какие изменения нужно внести в процесс развертывания (переменные, конфиги, настройки доступов);
Передать знания о внесенных изменениях коллегам-разработчикам (code review + документация)
Также хочется заметить, что существует особая каста разработчиков-воинов - святое воинство. Их Кодекс гласит, что тестированием должны заниматься только QA-инженеры, а для истинного dev-воина это тяжкий грех. Они выполняют задачу и передают ее дальше, ни разу не проверив свои изменения. И только "святостью" можно оправдать непоколебимую веру в их безошибочную непогрешимость.
QA-инженер
Только вы владеете все информацией по процессу тестирования и можете сказать, какие изменения нужно внести в тесты для поддержки изменений от разработчиков.
После получения информации от разработчиков, QA-инженеры должны выполнить следующие действия:
Сообщить менеджерам об объеме изменений в тестировании.
Помните, что технический долг для QA более критичен, чем технический долг для DEV;Запросить у разработчиков недостающую информацию.
Нужно заниматься не механическим тестированием задачи, а разобраться в ней, понять все бизнес- и тест-кейсы. Если не хватает каких-либо знаний о системе или не понимаете задачу (или ее решение) до конца, нужно обратиться к разработчикам.Передать полученные от разработчиков знания и внесенные в тестирование изменения своим коллегам QA-инженерам (code review + документация)
Среди QA-воинов тоже есть приверженцы своего "святого воинства" - экстрасенсы. Это воины, которые найдя проблему, не дают никаких описаний и пояснений, видимо, транслируя эту информацию напрямую в мозг разработчика. Однако, простые разработчики не способны воспринимать информацию таким образом и поэтому вынуждены гадать на кофейной гуще пытаться спрогнозировать условия возникновения ошибки и проводить собственное независимое расследование.
DevOps-инженер
Только вы владеете все информацией по процессу развертывания системы.
Однако, все нюансы и проблемы с развертыванием должны быть запрошены разработчиком до начала внесения изменений, т.к. влияют на решение задачи. Поэтому из обязательных действий после внесения изменений разработчиком DevOps-инженер должен выполнить следующие:
Внести изменение в развертывание системы в соответствие с предоставленными разработчиком данными
Передать полученные от разработчиков знания и внесенные в тестирование изменения своим коллегам DevOps-инженерам (review + документация)
Менеджер
Только вы владеете информацией о сопряженных задачах в других командах, приоритетах и организации проекта на высоком уровне.
Поэтому после внесения изменений от менеджера требуются следующие действия:
Запустить оповещение всех заинтересованных лиц об изменениях (менеджеров других команд, конечных пользователей и так далее)
Скоординировать процесс и запустить связанные с выполненной задачи
Простимулировать обмен знаниями (обновления, изменения, дополнения) внутри команды и между командами
Какие изменения затрагивают общие механизмы? Могу ли я доставить их отдельно и заранее?
Данный вопрос рассмотрим для всех категорий вместе, но под общим механизмом для них будем понимать разное: для разработчиков это будет некая общая часть кода/системы; для QA - общая часть системы тестирования; DevOps - развертывания, а для менеджера - это сами задачи уровня бизнес-логики и сами бизнес-процессы.
Под основным продуктом можно понимать как саму систему в целом, так и, например, общую ветку в системе контроля версий.
Допустим, есть две задачи, которые необходимо выполнить. Также понятно, что необходимо внести изменения (или создать) в некую общую часть, которая понадобится в обоих случаях.
Есть несколько путей, которым можно следовать:
Выполнить задачи последовательно
Это хороший вариант, который не требует никаких дополнительных действий. Но он не всегда возможен. Приоритетные задачи в большинстве своем могут выполняться параллельно за исключением синхронизации общих участков.-
Выполнить задачи параллельно и синхронизировать их итоги при добавлении в основной продукт
Это самый неприятный, но часто выполняемый вариант. Он приводит к множеству проблем:Конфликт изменений
Чем дольше вы удерживаете критичные изменения, тем больше шанс возникновения конфликтов с изменениями ваших коллег как в коде, так и в самой бизнес-логике.Невозможность совместного использования
Если вы вносите какое-то исправление в общий механизм, оно может быть полезным для ваших коллег в рамках решения других задач. Но пока вы его не добавите в основной продукт, оно будет недоступно для них.Объединение независимых изменений (увеличение объема изменений)
Чем меньше объем единовременных изменений, тем проще их протестировать, проще с ними ознакомиться и начать их использовать.
Внесение общих изменений в рамках частного решения увеличивает объем изменений, а объем покрываемых кейсов выходит за рамки задачи.Ассоциация общего с частным
Внедряя общее изменение в рамках определенной крупной задачи, вы не только заставляете коллег дольше его ждать, но и вносите определенное когнитивное искажение, приводящее к ассоциации общего механизм с частной задачей, хотя область его использования гораздо шире.
Вынести общую часть как отдельное изменение, а затем продолжить выполнение задач
Это наиболее оптимальный вариант в случае, когда последовательное выполнение невозможно. Конфликт изменений становится менее вероятным, общий кусок можно использовать совместно, причем он будет обработан, доставлен и воспринят отдельно, что уменьшит объем изменений по задаче и избавит от когнитивного искажения.
Что делать с прочими обнаруженными проблемами?
Иногда в ходе решения проблемы можно обнаружить другую, не связанную с ней, проблему. Например, разработчик, изучая участок кода, может подметить какую-то ошибку или опечатку; QA-инженер может придумать какой-то нетривиальный кейс, который не был рассмотрен ранее и так далее.
Воин стремится решить все наши проблемы, поэтому он готов сразу же броситься грудью на амбразуру начать решать новую проблему в рамках старой. Однако, такой подход чреват следующими проблемами:
Неотделимость изменений
Как только вы внесли изменения в рамках задачи, эти изменения становятся неотделимыми от нее. Вы не сможете доставить эти изменения на production раньше, чем доставите изменения по вашей задаче.Параллельное решение
Ваши коллеги также могут заметить эту проблему. Тогда вы рискуете не только получить дублирующее исправление, которое приведет к конфликтам изменений, но и потратите время нескольких человек на параллельное решение одной и той же задачи.Дороговизна исправления
Вы сами не всегда можете определить критичность проблемы и все условия ее возникновения, а также реальность совпадения всех этих условий. Поэтому вы можете потратить много времени, исправляя несущественную ошибку (например, ошибочный кейс, который никогда не возникнет на production) и, одновременно, отложите решение поставленной задачи. Также, так как на исследование побочной проблемы не выделено время, вы можете поправить только частичный случай, а проблема может оказаться глобальнее.Точечное исправление
Так как вы решаете побочную проблему в рамках текущей, вряд ли вы захотите тратить много времени на изучение ошибочного кейса. Поэтому вы вполне можете поправить частный случай или симптом вместо поиска и исправления глобальной проблемы. Например, вы исправите ошибку, приводящую к некорректной записи в базу данных, но не станете выявлять записи, уже сохраненные с ошибкой.
Что же делать? Просто заведите задачу (баг), а потом сообщите о задаче менеджерам. Укажите максимум доступной для вас информации: примерные шаги воспроизведения, кейсы, значения, конфигурацию, ветки, где это скорее всего воспроизводится и так далее.
В рамках заведенной задачи QA-инженеры попытаются воспроизвести проблему и дополнят задачу (шаги воспроизведения, stacktrace, настройки и так далее). Менеджеры по описанию проблемы, вероятности и частоте ее появления на production определят приоритет. Если проблема критичная, то она сразу же поступит разработчикам на исправление и будет устранена независимо от вашей задачи.
Что я могу изменить, не выходя за рамки затронутой бизнес-логики?
Данный вопрос может противоречить всему вышесказанному, но иногда необходимо пойти на компромисс, чтобы поддержать или улучшить качество системы
Итак, вы выполнили задачу и уже затронули определенную логику в вашей системе. Это означает, что часть системы уже требует тестирования.
Именно эту часть вы можете изменить дополнительно:
провести рефакторинг;
внести изменения, чтобы уменьшить существующий технический долг;
добавить комментарии к коду, с пониманием которого возникли вопросы;
Главное - всегда оценивайте, сколько ресурсов команды потребует ваше изменение.
Заключение
Кратко о главном
Благими намерениями...
Не всегда хорошие поступки и стремления приводят к хорошему результату. Правила разработки и взаимодействия в команде написаныкровью из глазна основе реального опыта множества людей. Да, обязательность некоторых правил очевидна не сразу. Но чаще всего соблюдать эти правила не сложно, а положительный эффект от них значителен, особенно в далекой перспективе.Группа воинов - не команда
Каждый воин - отдельная самостоятельная единица. Он действует независимо, сводя взаимодействие внутри группы до минимума. Группа воинов - сила, но не команда. Группа солдат, работающих в команде способна работать гораздо эффективнее группы воинов, даже если их индивидуальные навыки ниже.Работа за других понижает эффективность команды в целом
Помощь другим - правильный и полезный поступок. Но ровно до тех пор, пока оказывается не в ущерб своей деятельности. Если помощь другим затягивает решение текущей задачи, это повлияет на время выполнения задачи все командой.Попытка охватить все аспекты разработки с полным погружением в каждый из них уничтожит эффективность команды полностью
Один человек будет работать за всех. Речь уже не будет идти о команде. Каждый будет являться командой-в-себе и играть все роли. Подобная команда из семи человек на самом деле будет являться семью командами из одного человека каждая.
Выводы
У каждого своя роль
У каждой категории свой набор возможностей и ответственностей, своя экспертиза в определенной части системы. Понимать чуть больше, чем положено, полезно для команды. Но не нужно пытаться отвечать за все и сразу. Попытка сыграть чужую роль должна приводить к ответственности за любое действие в этой роли.У каждой роли должен быть регламент
Каждый должен понимать, что входит в его роль и что он должен делать в том или ином случае. Тогда разработчику будет точно понятно, как внести изменения, QA-инженеру понятно, как тестировать и покрывать тестами, а менеджеру удобно управлять командой, руководствуясь регламентами каждой роли.В команде должно быть взаимодействие
Поведение воина в стиле "каждый сам за себя" ведет к имитации "итальянской забастовки" и понижению эффективности команды. Каждый член команды должен делиться знаниями самым эффективным путем с фиксацией всей информации с возможностью ее воспроизведения. Т.е. заведенная задача и(или) документация с возможностью поиска будет гораздо лучше видеозаписи митинга без тайм-кодов, зато с помехами (отступления от темы, неточность формулировок из-за объяснения "на ходу", прерывания связи).
P.S. от автора
Данная статья не призывает вас писать плохой код, лепить костыли и изобретать велосипеды. Я лишь хочу напомнить, что мы живем не в вакууме и разработка - это не только написание кода. Особенно в корпоративном секторе. Корпоративный работник действует в команде, где каждый выполняет свою роль, и его действия влияют на на остальных.
Если есть возможность написать хорошо и не задержать выход новой версии на месяц - отлично. Если нет, возможно, стоит написать компромиссное решение, но запланировать и согласовать его улучшение на будущее.
Ну, и документация - наше все. Если на все ваши действия есть задачи, а на все части системы - документация, то вы всегда сможете восстановить ход событий и пояснить, что, зачем и когда было сделано.
Интересные ссылки
Комментарии (20)
sshmakov
04.10.2021 13:39+1(а возможно, даже провести полный регресс-тест всей системы)
Будто это так плохо. Регресс надо делать регулярно.
fadeinmad Автор
04.10.2021 13:51Будто это так плохо. Регресс надо делать регулярно.
Плохо, когда вынуждены делать его незапланированно. Регулярный регресс системы - хорошая практика, когда он запланирован и выполняется как отдельная задача.
А если QA-инженеры помимо проверки конкретной задачи вынуждены в рамках нее еще и регресс всей системы делать, то доставка изменений на прод будет занимать огромное количество времени. Вот это уже плохо.
А если таких задач будет две? три? Делать полный регресс после каждой задачи, конечно, можно, но это явный оверхед.
sshmakov
04.10.2021 14:30Не очевидно, что регресс столь необходимо делать незапланированно. Почему не проверить отдельно каждую доработку, а затем перед релизом полный регресс?
fadeinmad Автор
04.10.2021 15:15Я найду время и сделаю "работу над ошибками" (поправлю неочевидные моменты).
Чтобы проверить каждую доработку, нужно знать, какие изменения сделаны и какая бизнес-логика затронута. Если же затронули больше, чем надо, то и проверить нужно больше.
(а возможно, даже провести полный регресс-тест всей системы)
Здесь говорится даже больше не о самом регрессе, а о том, что тестирование фичи при таких изменениях, а именно негативное тестирование, становится эквивалетно полному регресс-тесту системы.
Согласен, сформулировано неочевидно.
sshmakov
04.10.2021 16:08Сформулировано у вас нормально. Я имею в виду, что не всегда регресс нужно проводить немедленно. Если этап регресса все равно есть в процессе разработки, то качество будет проверено, просто позже. За это время разработчик может исправить свои ошибки, наведенные предыдущим своим же исправлением.
fadeinmad Автор
04.10.2021 16:36Да, может, но ошибки нужно выявить, а их выявит регресс позже. В рамках задачи ошибка, не входящая в скоуп задачи, выявлена не будет. А если расширять критерии приемки задачи с учетом затронутой логики, получим "полный регресс", как я писал выше.
Мало того, сталкивался со случаями, когда в относительно сложной логике поверх одних измений, содержащих ошибку, накручивалась логика, эти изменения использующая. В этом случае исправление становится весьма нетривиальным.
В любом случае, если можно избежать сложностей, их стоит избежать.
sshmakov
04.10.2021 16:49А если расширять критерии приемки задачи с учетом затронутой логики, получим "полный регресс", как я писал выше.
А зачем расширять? Да, другая логика, возможно, затронута. Но тестировщик не знает, что было или могло быть затронуто. Так куда расширять?
В рамках задачи ошибка, не входящая в скоуп задачи, выявлена не будет
А должна? На мой взгляд, она должна выявляться не на этом этапе. Либо раньше, на этапе PR, юнит-тестов, либо позже, на регрессе релиза. Хорошо, если есть автотесты, делающие регресс основной функциональности. Если не при каждом билде, то хотя бы регулярно.
Короче, я хочу сказать, что такая ситуация есть и часто. Но решение её - не замена разработчика "воина" на "солдата". А организация процесса такое, чтобы в конце вы были уверены в качестве релиза.
fadeinmad Автор
04.10.2021 17:07А зачем расширять? Да, другая логика, возможно, затронута. Но тестировщик не знает, что было или могло быть затронуто.
Именно поэтому ему стоит сообщить о том, что ты задел другую логику, и на нее тоже стоит взглянуть.
Хорошо, если есть автотесты, делающие регресс основной функциональности. Если не при каждом билде, то хотя бы регулярно.
Это да, хорошо, но автотесты - не панацея. Вы могли изменить логику таким образом, что ранее невозможный кейс стал актуальным. На него не будет автотестов.
На мой взгляд, она должна выявляться не на этом этапе. Либо раньше, на этапе PR, юнит-тестов, либо позже, на регрессе релиза
Это все хорошо опять же для ранее существовавших кейсов. Если вы изменили критичную логику и создали "новый" кейс для "старой" логики, то никто, кроме вас этого не знает.
Юнит тесты вы сами поправите в соответствие с измененной логикой (хорошие тесты и так падают при изменении логики). Если это выявится на уровне PR, то хорошо. Но дальше, если никто не знает, то QA- инженер не протестирует и регресс тоже особо не выявит (некто ж не знает, что регресс надо расширить на ранее невозможный кейс). Код уйдет на прод.
Я согласен, что это перестраховка. Но если действовать так, то при малых затратах можно получить более высокую надежность.
А по поводу воина и солдата здесь смысл один. Воин действует "сам за себя", а солдат работает в команде. Командная работа, когда каждый действует не изолированно, а вместе, дает значительный профит. И да, это относится именно к организации процесса. ни в коем случае не говорю о том, что воина надо заменять.
Mike-M
04.10.2021 14:27QA-воин точно так же, как и разработчик, в стремлении к прекрасному способен упустить реальную потребность компании в максимально быстрой доставке изменений конечному пользователю
Вот этот момент мне совершенно непонятен.
Откуда у компаний такая прочная уверенность в том, что для потребителя скорость изменений важнее их качества?
Кто-нибудь этот вопрос изучал вообще? Покажите мне результаты этих исследований.fadeinmad Автор
04.10.2021 14:37для потребителя скорость изменений важнее их качества
Видимо, мне и правда нужно обдумать формулировки.
Для потребителя качество важнее, с этим спорить невозможно (да и не нужно)
Максимально быстрая доставка изменений пользователю - требование не пользователя, а бизнеса (потребность компании). Чем динамичнее развивается продукт и предоставляет новые фичи пользователю и закрывает ошибки в уже имеющемся, тем проще ему удержаться на рынке
Под максимально быстрой доставкой я понимаю доставку без ущерба качеству, но с учетом реального мира (когда "лучшее - враг хорошего"). Компромисс с бизнес потребностями такой: лучше доставить изменения хорошего качества быстро, чем идеальные, но намного позже. Особенно это касается исправления ошибок, в этом случае скорость доставки исправлений играет серьёзную роль.
Ekstrem
04.10.2021 19:26Статья круто началась, жизненно) Закончилась не про войну - про потасовки школоты на перемене)
Я бы докопался до того, что это описание взаимодействия команды ремесленников, которые стучат своими особенными молоточками, чтобы получить конечную заготовку (как булавка у Смита). У команды инженеров вышедший на индустриальный уровень "воинов" не бывает - в худшем случае банка пауков))
ksbes
Если говорить про Сунь Цзы, то самый дельный его совет (в моей искажённой интерпретации): «бей по полному, подставляй под удар пустое».
В плане разработки это звучит так:
fadeinmad Автор
Это правильный и логичный подход. Это не "путь воина", о котором я говорил выше. Воин, скорее, наооборот, полезет оптимизировать все из лучших побуждений.
Путь воина - категорично исправить все и сразу. Что может привести к задержкам доставки кода на прод.
Если изменение критично, всегда можно сообщить об этом команде. И после того, как задача будет обсуждена и приоритезирована, а менджер даст добро, можно внести правки. Так проект станет более управляемым и будет иметь понятные сроки реализации.
Sergey-Titkov
Даже если это приводит к потерям?
В статье ничего не сказано, про то что субоптимизация зло
fadeinmad Автор
Да, даже в этом случае. Критичные изменения можно и следует пустить отдельной задачей (веткой и так далее). Они так дойдут быстрее (пункт "Что делать с прочими обнаруженными проблемами?")
А если твоя задача и есть в том, чтобы исправить возникшую проблему, то тут уже другой вопрос (ситуация с точечным и общим исправлением). Можно сделать быстрый хотфикс с точечным исправлением, а потом уже спокойно отдельной задачей продумать оптимизацию критичного участка. И опять же отдельной задачей.
Sergey-Titkov
Вместо получения прибыли компания начинает получать убытки.
Тогда вопрос уже другой, а зачем это бизнесу нужно?
fadeinmad Автор
Похоже мы друг друга не до конца не понимаем, возможно, я неверно формулирую.
Бизнес несет убытки от ошибок в любом случае. Вопрос в том, как это быстро и эффективно поправить.
Воин перепишет все, никого не спрашивая, что приведет к тому, что код дольше будет идти на прод, увеличивая потери бизнеса.
Я же говорю о том, что нужно подходить к решению организованно и рассматривать затраченные ресурсы не только свои, а всей команды. Чтобы все сделать правильно.
Smytjan
Похоже у Вас смешались значения воина - по восточному и рыцаря из европы. Воины востока вряд ли будут делать что-то лишнее, что не прописано в кодексе, или как там оно у них называется.
fadeinmad Автор
Возможно. Но я имел в виду немного другое:
В Кодексе воина (западного или восточного) прописано стремление к перфекционизму и неприятие компромиссов. Исправить все и сразу.
У самураев есть интересное правило, которое может помочь в принятии решений в жизни:
Но вот только "не думать" в разработке и идти любыми силами к идеальному коду зачастую приводит к большим проблемам.