Вступление в виде басни "Бэкендер, фронтендер и аналитик"
Когда в коллегах согласья нет,
На лад проект их не пойдет,
И выйдет из него не profit, только cost.
Однажды Бэкендер, Фронтендер да Аналитик
Везти с тасками US взялись,
И вместе трое все в него впряглись;
Из кожи лезут вон, а US всё нет ходу!
Таски бы для них казались и легки:
Да Фронт рвется в Cloud-решения,
Бэк пятится назад, а Аналитик тянет в воду.
Кто виноват из них, кто прав, — судить не нам;
Да только UserStory и ныне там.
Привет, друг!
Меня зовут Сергей Павлов — тот, который любит погамать в VR, порубиться в настолки и ещё, оказывается, тот, который начальник отдела развития в банке «Открытие».
Давай немного отвлечемся от привычного формата технических и научных текстов. А вместо этого одну простую сказку, а может и не сказку, а может не простую … в общем будем вспоминать сочинять.
Сегодня я пришел поделиться с тобой очередной практикой эффективного (сейчас будет умное слово) Cycle Time.
Cycle Time — время, которое задача находилась в разработке от момента, когда ей начали заниматься, до момента, когда она прошла фазу конечной поставки.
Но речь пойдет не конкретно про Cycle Time, поэтому я не буду заострять на этом внимание.
Перейду к сути — уверен, многие узнали всем известную басню про трёх товарищей, которые пытаются затащить одну общую хотелку (некий воз). Только вот каждый тянет эту задачу в свою сторону, игнорируя усилия других.
Задача
Сейчас будет описание крайне сложной задачи! Т-с-с! Никому не рассказывай эту идею… это идея на миллион (чего-нибудь, возможно, ценного).
«Нам нужно реализовать сбор уникальных слов от пользователей»
Также давай не будем обращать внимание на бизнес-значение текущего запроса. Как я сказал, эта идея — бомба, она выстрелит сразу. Да и вообще будем считать, что на старте проекта уже будет пройдена ТБУ (точка безубыточности).
Ну что, всё предельно ясно, можно начинать реализацию.
Го разрабатывать, я создал!
Круглое таскать, квадратное — катить
ПОНЕДЕЛЬНИК: берем задачу в аналитику
Думаю, тут будет всё просто. Накидаем тзшку на разработку.
Введение
Наименование программы — "Словособиралка". Система предназначена для коллекционирования уникальных слов от пользователей.
Данные о введенных словах хранятся в базе данных (СУБД). Обязательное условие — исключаем дубликаты.
Входные параметры
POST/word
Параметр |
Тип |
Обязательность |
Описание |
word |
string |
да |
новое слово |
Выходные параметры
Код |
Описание |
200 |
слово уже имеется в базе |
201 |
новое слово добавлено |
400 |
некорректное значение параметров |
Сценарий пользователя
Для добавления нового слова пользователь заполняет поле ввода и нажимает кнопку "Отправить".
Выдерживаю паузу … Держу паузу для того, чтобы ты, мой дорогой читатель, успел принять решение о том, всё ли ок в ТЗ и готовы ли мы двигаться дальше. Если пауза затянулась, то я приму решение двигаться дальше, т.к. задача простая, тут особо не разгуляешься. Есть описание сценария пользователя, есть описание запроса и ответа. Разработчику понятно, что делать — это главное!
ВТОРНИК: ну как тут без оптимизации? Работаем по Кайдзен! Во как!
Кайдзен (Kaizen) — ключевая концепция менеджмента. Это японская философия, система с фокусом на непрерывном совершенствовании всех производственных процессов, нашего образа жизни и всех аспектов жизни. Kai — перемены, изменения, Zen — к лучшему.
Поэтому можно смело запустить два процесса в параллель (реализация бэкенд и фронтенд части).
Реализуем фронтенд
У фронта тут будет самая простая часть. Вот бездельник!
Таак, посмотрим, что там у нас пришло по ТЗ: "Нужна форма для отправки запроса по нажатию на кнопку. Форма, в свою очередь, состоит только из одного поля для ввода текста и той самой кнопки".
Раз-два, тяп-ляп и формочка готова:
Чтобы было ещё проще форма будет выглядеть так:
<form action="/word" method="post">
<input type="text" value="" name=”word”/>
<input type="submit" value="Отправить!"/>
</form>
Форму сабмитим одноименным инпутом типа=”submit”
На этом, как говорится, "здесь наши полномочия всё".
Реализуем бэкенд
Первым делом создаем таблицу для хранения слов:
Поле |
Тип |
Обязательность |
Описание |
word |
string |
да |
слово |
Далее пишем маппинг на входящие параметры для сохранения в таблицу. Чтобы исключить дубликаты, пишем вставку в таблицу через INSERT IGNORE.
Возвращаем ответ согласно поставленному ТЗ.
Всё готово! Довольный разработчик запускает доту и продолжает рубить, пока нет других задач.
Задача выполнена, все счастливы!
Казалось бы, каждый выполнил своё дело и даже успел получить талоны на бесплатные обеды! Но давай рассмотрим, что мы имеем при таком подходе.
СРЕДА
Город засыпает, просыпается мафия тестировщик. На этапе функционального тестирования совместной dev-сборки выясняется, что запрос с фронта уходит, но данные в БД не появляются. Причем мы ещё и получаем в ответ статус 400. Смотрим в ТЗ, сравниваем исходящие параметры с фронта на бек и снова удивляемся — "Почему 400?! Почему так?". Закрываем глаза, нажимаем кнопку "отправить", открываем глаза … увы, картина не поменялась … даже при таком секретном подходе с закрытыми глазами. Всё так же ошибка 400.
Ок, я же крутой тестировщик, сейчас во всём разберусь! Беру HAR-файл, иду к бэкенд-разработчику с вопросами:
Тэк бэт, смотри, запрос на бэк приходит, всё по ТЗ, но почему-то данные в таблице не появляются, а в ответ я получаю 400.
Смотрим на бэк и понимаем, что мы ожидаем application/json, а приходит application/x-www-form-urlencoded. Итог — крах, тлен, уныние, приём депрессантов.
Что мы делаем дальше — отправляем таску на доработку, т.к. дальнейшее тестирование в целом невозможно.
За кем закрепляем? Хм… да конечно же за разработчиком бэкенда! Ведь он же, такой неумёха, не сохраняет данные!
Тестировщик засыпает...
ЧЕТВЕРГ
Слово предоставляется BE-разработчику:
Представим, что наш бэкенд-разработчик само спокойствие и пример умиротворения. Спокойно открывает задачу, читает, анализирует, открывает код и всё такое. И выдает вполне себе ожидаемую фразу — "Товарищи по цеху, а причем тут я?!". Далее ласково и красноречиво отписывает в комментариях просьбу переделать отправку с фронта в json-формате. Закрепляет задачу на фронт-разработчике, при этом делает акцент, как бы оправдывая себя: "Вы же видели ошибку 400! Всё должно быть понятно по ней. Значит, что-то с параметрами".
Свою работу я выполнил, сделайте, пожалуйста, свою!
Слово предоставляется FE-разработчику:
— Уважаемый, прошу обратить внимание на то, что вообще-то это я инициатор запроса, что собственно означает, что ваша обязанность — подстраиваться под меня!
Речь фронта была краткая и понятная. Ну что тут говорить… инициатор диктует правила.
— В любом случае я так и не понял, как мне обрабатывать ошибки. Давайте повесим какие-нибудь нотификации исходя из статусов ответов. Они же для чего-то есть. В общем, передаю задачу системному аналитику.
Дружище, пиши нормальное ТЗ!
ПЯТНИЦА
Во всем как всегда виноват аналитик...
Вообще любой баг в большинстве случаев довольно просто повесить на системного аналитика, опираясь на любую из подобных фраз:
— Ты не собрал до конца требования;
— Ты не продумал полностью интеграцию;
— Ты не указал формат передачи данных (О, наш вариант!);
— Ты не спроектировал хранение данных;
— Ты не описал описание описания;
— В какое время года наступает новый год на Северном полюсе?;
— И т.д....
Итак, системному аналитику прилетела задача (баг) из-за того (как показалось), что он не описал формат передачи данных. Штош, подсудимый, отвечайте!
Господа присяжные! Дело в том, что при проектировании ТЗ я пользовался здравым смыслом. И в надежде на то, что у разработчиков есть здравый смысл, не стал указывать формат отправки данных с фронтенда на бэкенд. Тем более, вы — оба разработчики и должны понимать, как отправить запрос с фронта на бэк. Не прави ли я? И самый главный встречный вопрос к вам: "Вы пользуетесь здравым смыслом?"
Давайте разбираться
Подведу предварительный итог, к чему это всё было написано.
В этой ситуации каждый прав и неправ одновременно. Каждый участник проделал свою работу над задачей. А когда возникла проблема — тут началась игра "Переложи проблему на другого".
Каждый пытался переложить текущую проблему с себя на своего коллегу. Хотя вот тут я бы вступил в холивар на тему "Кто есть коллега?". Потому что для меня коллега — это надежный партнер по работе, на которого можно смело рассчитывать и с кем можно планировать реализацию задачи любой сложности.
Аналитик
Пошел по пути наименьшего сопротивления для реализации задачи. Он составил ТЗ быстро и кратко. Ровно для того, чтобы на этом этапе задача задержалась как можно меньше, чтобы можно было её уже передать в разработку. В целом он аргументировал это решение тем, что его так называемые “коллеги” вполне себе адекватные синьор-специалисты и смогут совместно решить аспекты отправки данных.
Бэкенд
Строго реализовал задачу согласно поставленному ТЗ. Он не отклонялся в сторону, не пытался видоизменить ход мысли аналитика. К тому же unit-тесты успешно выполняются на 100%.
Фронтенд
Задача была крайне простая. Нужно просто отправить форму с данными. Имена переменных озвучены в ТЗ, собственно, эти данные и уходят на бэк, где он в свою очередь должен был их обработать.
Прошла неделя. Вот только ТЗ и ныне там...
Забудем, что было и начнем с начала
А теперь давай разберем, к чему мы пришли у нас в «Открытии».
В первую очередь, мы — команда! Перед нами стоял ряд объективных проблем:
Задача проходит несколько раз по одному и тому же этапу;
Некоторые задачи, хотя и реализуются по скраму, но их исполнение очень похоже на вотерфлоу;
Ресурсы разработки простаивают из-за ожидания выполнения этапов;
Уровень напряжения и недоверия в командах растет;
Отсутствует единое понимание цели выводимой задачи, также рассинхрон в техническом понимании задачи, т.е. в том, как она "выглядит изнутри";
И т.д....
Очевидно, что все эти проблемы надо решать. Можно бесконечно искать оправдания и откладывать изменение уже устоявшихся процессов, но я считаю — лучше начать делать хоть что-то, чем ничего не делать.
Итак, самое основное — убрать барьеры. Убрать преграды между коллегами, когда кто-то боится, кто-то стесняется, кто-то не хочет что-либо говорить. Внутри команды и даже между командами мы всегда открыты к диалогу и обсуждению каких-то задач, вопросов, да и просто поболтать на свободные от работы темы — разумеется, не во вред текущему рабочему процессу:)
Чтобы описать сам процесс подхода к изменению коммуникаций, нужна будет отдельная тема. Поэтому я вернусь к текущей теме и опишу, как оно работает у нас сейчас.
Процесс работы над задачей построен так, что сотрудник не остаётся с ней один на один бесконечное время.
Отменяем 1:1 митинги между задачей и исполнителем!
Будь то аналитика или разработка (бэк или фронт), всегда происходит активное взаимодействие со всеми участниками текущей задачи. Решение, которое сейчас выполняет сотрудник, обязательно обсуждается с другими исполнителями.
Этот подход, кстати, позволяет нам работать эффективно со специалистами разного уровня (Junior, Middle, Senior). Поэтому ошибки при реализации из-за отсутствия компетенций не пройдут мимо из-за общего груминга. И коллега обязательно сделает акцент на то, где, как и что лучше исправить. Тем самым мы ускоряем прокачку и рост специалистов от Junior до Senior.
Вернемся к нашей абстрактной задаче про "Словособиратор". Мы пойдем по той реализации, которая была заложена изначально. Возьмем то ТЗ, которое подготовил наш системный аналитик.
Далее мы подключаем важный этап, который был упущен — коммуникацию!
Что мы получаем? До передачи ТЗ на разработку оно должно пройти груминг, т.е. исполнители задачи должны ознакомиться с тем, что нужно будет сделать. Далее в режиме открытого диалога происходит обсуждение возникших вопросов. Как раз в этот момент и должны появиться вопросы из серии "Воу-воу, ребят, а в каком формате данные будут ходить?".
Чтобы не останавливать процесс (в банке мы же не бюрократы:)), ТЗ уже можно отдать в разработку с пометкой "поправить момент отправки и обработки данных". Ведь на груминге все услышали и зафиксировали решение. Будем отправлять и принимать JSON.
Кстати, хочу добавить, что на груминге необходимо присутствие и тестировщика, потому что ему тоже нужно понимать, как это всё работает, чтобы качественно провести тесты.
Итак, вернемся к нашему условному понедельнику.
ПОНЕДЕЛЬНИК: берем задачу в аналитику
Думаю, тут будет всё просто. Накидаем задачку на разработку. Введение, Входные параметры, Выходные параметры, Сценарий пользователя оставим без изменений, как описывали в начале.
ВТОРНИК
Грумим задачу, собираем фидбек, понимаем, что нужно указать формат передачи данных и запускаем два процесса в параллель (реализация бэкенд и фронтенд частей). В этот же день дописываем формат передачи данных, но получаем момент, на который стоит обратить внимание — ТЗ обновлено в момент разработки! Поэтому обязательно уведомляем об этом разработчиков, подсвечивая те места, где были изменения в ТЗ.
Вот теперь задача выполнена, все счастливы!
СРЕДА
Тестируем задачу, поскольку она чересчур простая, а формат передачи данных мы уже обсудили, ошибок на этом этапе не должно быть обнаружено. Итого — в среду наша задача уже имеет статус RFR (ready for release).
Profit!
Подведем итоги
К:
Команда
КоммуникацияКапризы
Клевета
Работа над задачей должна идти коллективно, каждый член команды должен держать в голове мысль о том, что задача исполняется в первую очередь для клиента, а не для списка к отчету релиза. Нужно понимать, как твои действия над задачей повлияют на вывод её в прод.
Отклонения от ТЗ допустимы, но должны быть согласованы между всеми исполнителями. Также в обязательном порядке изменения должны быть зафиксированы до вывода задачи в прод.
Если есть вопросы — СПРАШИВАЙ!
Adios!
Комментарии (22)
kredis31
00.00.0000 00:00+1Все в итоге свелось к "здравый смысл" во время груминга. Т.е. это хорошо если разработчики на момент груминга это заметят и обсудят. А может получиться так, что собрались обсуждать ТЗ, а всем все ясно, и формат данных так и не обсудили. Т.е. груминг не решает полностью проблему, хоть и помогает ее минимизировать.
Если в команде началась игра "Переложи проблему на другого" то тут явно проблемы. Аналитик должен вовремя получить обратную связь по ТЗ, во вторник при разработке или в среду от тестировщика. А дальше скорректировать ТЗ и оповестить исполнителей.
Так же тестировщик должен тестировать фронт и бэк отдельно. Тогда бы сам тестировщик заметил пробел в ТЗ и невозможность тестировать бэк
isergirud Автор
00.00.0000 00:00+1Рад что основная мысль дошла верно! Всё так, здравый смысл имеет место быть. Но, к сожалению, такие моменты надо отлавливать как можно раньше. Вот, кстати, вариант про вовремя полученную обратную связь по ТЗ тоже хороший инструмент, я бы даже сказал сильный!
Идея в том, что не именно груминг решит проблему, а в том, что это всё не "однопользовательский геймплей", тут нужно работать в команде. К сожалению "переложи проблему на другого" довольно частые кейсы, и я бы хотел чтобы читатели обратили на это внимание, и вовремя констатировали такой факт если что-то подобное увидят в своих командах.
Vorchun
00.00.0000 00:00Два раза перечитал статью. Стиль изложения оригинальный, но сложный. Спасибо, что в конце есть "Подведем итоги".
isergirud Автор
00.00.0000 00:00Справедливое замечание по поводу того что стиль изложения слегка, назовем это так, необычный :) Возьму на заметку - нужно будет упростить. Понимая это я и завершил статью подведением итогов. Но в любом случае я премного благодарен за двойное чтение. Так же буду рад если что-то из этого пригодится на практике.
b00b1ik
00.00.0000 00:00аналитик реально плохо составил тз, оба разраба вместо того чтобы остановится когда непонятно в каком формате передавать нафигачили код как вздумалось и решили это все ... введением коммуникации)))
боюсь у вас все трое оказались джунами и ваше "решение" прокачает остальных джунов до такого же уровня;)
ну да, и в первой цепочке забыли про существование тестирования требований.
isergirud Автор
00.00.0000 00:00Угу, всё верно. И аналитик плохо заТЗшил и разрабы ушли в самоволку )
Я бы немного похоливарил на тему джуны они или нет ;) Как я вижу градацию от джуна до синьора:
Джун - не знает что делать и не знает как делать
Мидл - не знает что делать, но знает как делать
Синьор - знает что делать и знает как делать
Тут все трое а-ля "молодцы" сами сделали задание :) Это что-то типа около Middle.
Так же я хотел показать что это специалисты характера - "Ой, я сам знаю как лучше". Поэтому они ни с кем не обсуждали своё решение (которое, согласен с вами, упустил аналитик).
Но суть не в этом, мне понравилось ваше замечание про то, что они прокачают других до такого же уровня (делай тяп-ляп). Подскажите пожалуйста где я оставил брешь в системе? Её нужно срочно залатать :D Очень не хотелось бы чтобы экспертиза участников тянулась вниз. Т.е. как по вашему мнению используя груминги и совместную работу над задачей они потянут за собой остальных?
А что касается про тестирование требований - я и так уже переживал что получился слишком лонгрид, надо было сокращать )
Larisa_Dansarunova
00.00.0000 00:00Сергей, статья понравилась бы больше, если бы закончилась чем-то более полезным, чем просто "здравый смысл важен всегда".
Я, как бизнес-аналитик со стажем, могу еще добавить, что было бы неплохо US все-таки писать по принятому формату "Я, как пользователь ... хочу ..., чтобы ...". Это отразило бы бизнес-ценность фичи и дало бы дополнительную почву для вопросов к аналитику со стороны команды, а это поддерживает адекватность и градус "здравого смысла" в команде.
И кстати про US, так и не нашла его в статье(isergirud Автор
00.00.0000 00:00Я немного в растерянности, но "здравый смысл" - это полезная вещь, как бы это странно не звучало :) Возможно я не совсем понял ваш посыл. Расскажите подробнее?
Что касается по принятому формату, я об этом отдельно писал https://habr.com/ru/company/otkritie/blog/648155/ тут всё по полочкам... хотя этих "полочек" я бы добавил побольше, но боюсь что большие тексты тяжело читать.
US в этой статье и есть некий "воз" из басни Крылова. Она тут образно выражаясь так сказать.
rakerunner
00.00.0000 00:00В названии "UserStory", а в тексте речь идет о детальном "ТЗ". ИМХО, бизнес-аналитик не должен в описании требований указывать как их реализовывать. Он пишет ЧТО должна делать система, но не указывает КАК она должна это делать. БА описал требуемое поведение системы и аксептанс-критерии. А в каком формате фронт будет общаться с бэком - решает команда (возможно вместе в архитекторами, если они есть на проекте).
isergirud Автор
00.00.0000 00:00Хм... мне кажется я понял вашу мысль. В целом если бы назвать статью "Почему ТЗ и ныне там?" то выглядело бы гуд. Тогда можно было бы оперировать только тем, что речь идёт именно о техническом задании.
BA_TW
00.00.0000 00:00Я так понимаю, коллега имеет в виду работу бизнес-аналитика, а в статье идет речь о работе системного аналитика. Именно он описывает то, как система должна реализовывать бизнес-требования. Но да, юзер стори надо поменять на ТЗ, тогда вопросов не будет. :-)
BA_TW
00.00.0000 00:00+1Хорошая статья. Мы методом проб и ошибок тоже пришли к такой же схеме взаимодействия. Груминг - вот как называются наши презентации ТЗ разработчикам и тестировщикам! Буду знать. :-)
Мы еще на такие презентации подключаем продакт оунеров. И вот когда от всех приглашенных получен фидбек и апрув, тогда ТЗ передается в разработку. В идеале еще должны быть дизайн-макеты готовы и представлены на таких грумингах.
Тестировщики, кстати, тоже могут давать вполне себе дельные советы по реализации на таких грумингах.
А изменения в ТЗ мы фиксируем в разделе "Изменения" с обязательным описанием причин изменений. Особенно это актуально для сложных задач.
isergirud Автор
00.00.0000 00:00Да, вот эти все ошибки и боли мы проходили. И продакт оунеры должны быть на груминге и тестировщики. Всё верно :) Изначально я и хотел описать полностью как выглядит этот всё дело, но в процессе написания статья получилась оооооооочень длинная. Решил что это будет издевательство на читателями )
Кстати, пока от всех не будет получен апрув - действительно не стоит брать в разработку ТЗ. Это золотое правило! Могут быть ограничения, но это крайне редкие случаи, и они обсуждаются индивидуально к каждой задаче.
MikECOM
00.00.0000 00:00А что за «вотерфлоу»?
А по теме - хотелось бы послушать как у вас решаются задачи без участия аналитика, наверное вообще кровавое рубилово, скинуть ответственность то некуда…
Или аналитиков всегда хватает на все задачи? Какой тогда уровень здравого смысла у разработчиков? Или они в доту только и рубятся?
isergirud Автор
00.00.0000 00:00По поводу "Вотерфлоу" надеюсь это был вопрос с сарказмом про "Вотерфолл" :)
Кстати, интересная тема про "А как же быть без аналитика?" ???? Надо будет попробовать написать про это ) Такой опыт тоже имеется в бардачке. А вот кровавое рубилово мы как раз исключили - об этом и повествует статья ;)
MikECOM
00.00.0000 00:00Да, сарказм присутствует :)
У нас аналитиков хватает не на всех, часть задач, хорошо это или плохо, идут вообще без анализа. Разработчики ваяют в режиме свободного художника.
Я из статьи сделал вывод, что аналитик в итоге сделал правильное ТЗ, уточнил его по результатам обсуждения на дэйлике и всем стало хорошо.
А вот если самого ТЗ нет, уточнять нечего и некому фронт и бэк остаются один на один и … что тогда?
isergirud Автор
00.00.0000 00:00Хм... ну по поводу того хорошо или плохо что задачи идут без анализа я бы сказал что - плохо. Объясню почему.
Я считаю что разработчик, хороший разработчик, должен сам уметь разобраться с задачей и сделать её качественно даже если будет отсутствовать системный аналитик. Так же разработчик не должен 100% расчитывать что тестировщик отловит баги. Разработчик должен понимать что он пишет и как это аффектит на систему. И тут, казалось бы, почему же я считаю плохой ситуацию когда задача выполнялась без системного аналитика? Тут всё просто - отсутствует важный артефакт, отсутсвует документация! Т.е. после системного аналитика остаётся хоть какой-то след, прочитав который можно быстро погрузиться в детали реализации самой задачи. Команда меняется, люди меняются, и вновь прибывшим коллегам на проект очень хотелось бы иметь какую-то информацию по функционалу и т.д.
Если попробовать разобрать вопрос когда фронт и бэк остаются один на один - ну что тут сказать. Ситуация хоть и неприемлемая, но допустимая, такое бывает. В данном случае тут надо идти по пути данных, т.е. от инициатора до исполнителя.
В данном случае инициатором будет фронт разработчик, т.к. он отправляет данные в бэк. И вот на каждом этапе взаимодействия между фронтом и беком от инициатора к исполнителю должно придти предложение как будет выглядеть формат взаимодействия. Далее оба участника либо соглашаются на такое взаимодействие, либо обсуждают и приходят к какому-то совместному решению. Т.е. проще говоря не должно быть ситуации когда данные переходят от фронта к беку или наоборот, а вот формат передачи и перехода данных остался без обсуждения. Это важная составляющая взаимодействия фронта и бека без системного аналитика.
Но опять, в данном случаем мы хоть и получим реализацию, но потеряем в документации :(
hiimluck3r
"Во всем как всегда виноват аналитик..."
Милая статья, но даже она свелась к тому, что гады-аналитики ленятся писать ТЗ подробно :)
isergirud Автор
Я понимаю этот сарказм про "гады-анаитики" на собственном опыте так сказать :) Тут я как раз показал этот стереотип и надеюсь мне удалось описать обратное, что это всего лишь стереотип, а аналитик не во всём виноват ☝️
hiimluck3r
Это правда! Казалось бы, такая простая истина - "слушайте друг друга и давайте фидбек", но, к сожалению, иногда бывает так, что напарник не хочет слышать, не то, что слушать :(
Спасибо за статью!