Это вторая часть статьи по книге Роберта Мартина «Идеальный программист». В первой части статьи мы начали изучать, чем идеальный программист отличается от не идеального. Рассмотрели ответственность, научились говорить «нет» нереальным задачам и говорить «да» так, чтобы заказчик был, уверен, что всё будет готово вовремя. Мы определились, как писать код, принимать помощь и помогать другим. Продолжим.

7. Разработка через тестирование


Про TDD говорят много всякого разного, например, вот статья на хабре. Роберт Мартин, однако, говорит, что эта методика очень хороша.

Короткий рабочий цикл. Чем короче временной интервал от написания кода до его запуска, тем производительнее получается ваша работа. Вы можете запускать код каждый час (долго), а можете каждые пару минут (отлично!). Автотесты способствуют увеличению скорости. Написал > запустил тесты.

Три закона TDD:

  1. Рабочий код пишется только после того, как будет написан модульный тест, который не проходит.
  2. Вы пишете ровно такой объем кода модульного теста, какой необходим для того, чтобы этот тест не проходил (не компилируется = не проходит).
  3. Вы пишете ровно такой объем рабочего кода, какой необходим для прохождения модульного теста, который в данный момент не проходит.

Преимущества:

  1. Вы уверены в написанном коде
  2. Багов становится меньше
  3. Вы смелее вносите изменения. Когда весь код покрыт тестами, рефакторинг делается безболезненно.
  4. Тесты — отличная документация. Ваши тесты — прекрасные примеры использования кода.
  5. Хорошая архитектура. Только хорошо изолированный и слабо связанный код поддаётся тестированию. С TDD вы уже не напишете метод, который вызывает другой метод, который вызывает другой метод, который вызывает другой метод.

8. Тренировка


Если мы не развиваемся, значит, мы деградируем. Музыканты играют гаммы, Ф.Г. Углов в своей книге «Сердце хирурга» (http://fb2bookdownload.ru/modern-prose/213-serdce-hirurga.html) рассказывает, как он всю свою жизнь (а прожил он 104 года) тренировался в наложении швов. Адвокаты тренируют речь, военные участвуют в учениях. А как быть программистам? Им тоже нужно тренироваться?

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

Ката. Вы тренируетесь реализовывать определённый алгоритм (например, быструю сортировку). Вы не решаете задачу, а тренируетесь в выполнении действий, необходимых для решения. Это помогает запомнить горячие клавиши, закрепить в подсознании пары «задача-решение».

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

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

9. Приёмочное тестирование


В требованиях всегда будут неточности и изменения. Заказчик будет менять решение, а исполнитель будет менять реализацию. Исполнитель будет додумывать за заказчика и неправильно интерпретировать его слова. Я лично видел три крупных проекта, которые сдохли по этой причине. Но есть решение: введите точные и всем понятные приёмочные испытания.

У разных людей совершенно разное понимание слова «сделать». У нас на предприятии принято пользоваться вот этим, когда сделать — значит сделать и сдать. Однако, не все принимают такое определение. Я видел случаи, когда разработчик что-то закодил и решил, что сделал. Вроде, формальные требования выполнены, однако, заказчик недоволен. Это фрилансерский подход к жизни.

Проблему решит приёмочное тестирование со строгими алгоритмами. Это TDD, только на более высоком уровне. Пишете тест на любом языке (можно на русском) и согласовываете его с заказчиком. Задача должна быть покрыта приёмочными тестами на 100%. Автор книги пишет, что эти тесты должны быть понятными заказчику и автоматизированными. Лично я не знаю, как это сделать на ранней стадии: можно писать модульные тесты, но они непонятны заказчику. А можно писать тесты в Селениуме, но это уже более поздняя стадия. Если кто поделится рецептами для .NET, буду благодарен.

Что делать, если тест написан неправильно? Вы разработчик и у вас есть мозги. С их помощью вы можете увидеть ошибки в приёмочном тесте. Позиция «сделаю как написано» — это худшее, что можно придумать: вы сделаете хуже и себе и людям, поэтому единственный вариант исправления ситуации — это поговорить с разработчиком теста.

Интерфейс будет меняться. Чтобы смена интерфейса не ломала селениумовские тесты, думайте об этом во время разработки. Используйте id элементов для тестирования (ok_button, select_tour) или БЭМ-нотацию.

Непрерывная интеграция. Сделайте так, чтобы тесты запускались сами после каждого пуша в репозиторий. Если вдруг вам пришло оповещение, что тесты загорелись красным, — работа всей группы должна остановиться. Это очень важный момент, который пришёл из бережливого производства: вы увидите такую методику на заводе Toyota или Tesla. Если на контроле качества обнаруживается дефект, весь конвейер останавливается и начинается поиск проблемы. Станки перенастраиваются или чинятся и процесс запускается дальше. Цена ошибок слишком высока, чтобы их игнорировать.

10. Стратегии тестирования


Тестировщики не должны противостоять разработчикам. Хотя и кажется, что их роли антагонистичны, такое противостояние контрпродуктивно. Хорошо, когда тестировщик всеми силами помогает разработчику: ищет баги и описывает их так, чтобы разработчик максимально быстро понял, в чём дело, как воспроизвести и как починить.
Автор описывает пирамиду автоматизации тестирования



Про модульные тесты мы всё знаем, а про остальные чуть подробнее.

Компонентные тесты проверяют отдельный кусок системы. Аналитики описывают бизнес-правила как раз на уровне компонентов, и компонентные тесты становятся приёмочными тестами для бизнес-правил. Пример: тестирование системы поиска пациентов.

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

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

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

11. Планирование


Роберт Мартин пишет о своём распорядке. Он говорит, что встаёт в 5 утра, едет на велосипеде в офис, пишет расписание рабочего дня на доске. Расписание делит на 15-минутные интервалы, оставляя каждый час по 15 минут на отвлечения. После 15:00 хаос достигает апогея и дальнейшее планирование бессмысленно: идёт разгребание накопившихся дел.

Получается, автор использует буфер, который описан в статье «Сделать завтра». Такая схема может давать сбои, но в целом, позволяет навести порядок в рабочем времени.

Встречи — зло и только иногда добро.

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

Автор пишет, что в США совещание стоит 200 долларов в час на каждого участника (зарплаты, премии, помещения). А посчитал и получилось, что в России сильно дешевле: ?13 долларов в час на каждого. Но всё равно дороговато.

Отказ от участия и уход со встречи
Вы можете отказаться от участия. Если совещание бесполезно, не несёт пользы для вашего текущего проекта, не окупится в будущем — смело отказывайтесь. Нормальный руководитель будет защищать ваше право отказа: для него ваше время столь же ценно, как и для вас.

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

Повестка дня
Я не участвую во встречах без повестки дня. Это сжирает ваше время и не несёт полезного действия. Когда вас приглашают на встречу, уточните о её цели и повестке дня. Если мне говорят, что «обсудить текущие вопросы», я говорю так: «Для встречи нужна цель и повестка. Давайте уточним эти вещи и будем делать встречу, если она действительно требуется». Чаще всего повестка не образуется и такие встречи проходят без меня. Ну и слава Богу.

Пятиминутка — добро
Это часть гибкой методологии и без неё никуда. Каждый участник по очереди говорит:

1. Что я сделал вчера?
2. Что я буду делать сегодня?
3. Какие сложности мне предстоит решить?

Это быстро и не занимает много времени. Однако, есть компании, в которых пятиминутка превращается в сорокоминутку. Так делать не нужно.

12. Концентрация




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

Нормальный ночной сон. Управляйте временем сна таким образом, чтобы нормально высыпаться и иметь максимальную производительность днём. Чересчур много тоже не нужно спать. Берите пример с великих.

Кофеин. Автор пишет, что можно поглощать умеренные дозы кофеина, но призывает быть осторожным. Я с ним не согласен и отношу кофе и чай к интоксикациям, которые лучше не употреблять. По этому поводу есть книжка «Полезная вредная привычка». Сам не читал, но вот аннотация.

Физические упражнения. Тело нуждается в упражнениях. Погоняйте кровь и лимфу, проехавшись на велосипеде или присев 20 раз прямо в кабинете. Я отмеряю время помидорками и в паузах приседаю, отжимаюсь, делаю «Сурью Намаскар».

Ввод и вывод. Чтобы из вас вышло что-то хорошее, нужно, чтобы в вас вошло что-то хорошее. Стимулировать собственное творчество помогает чужое творчество. Хорошо подходит научная фантастика.

13. Уклонение от работы


Инверсия приоритетов
Несколько раз я замечал за собой такую штуку: есть задача с первым приоритетом, однако, она мне не нравится, и я ищу любой повод, чтобы заняться чем-то ещё. Когда я был маленький, мне как-то дали задачу по актуализации тестовых сценариев уже почти сдохшей системы. Эта задача была для меня настолько неинтересной, что я находил любой повод, чтобы отвлечься. Такое поведение называется инверсией приоритетов: менее важным задачам мы присваиваем высший приоритет. Для профессионалов такое поведение не годится. Мы должны решать задачи в порядке приоритетов, а не по личным предпочтениям.

Тупик — это когда вы принимаете решение, а оно оказывается не очень хорошим и чем дальше вы углубляетесь, тем хуже. Нужно отпустить кактус. Говорят, что, если вы оказались в яме, прежде всего перестаньте копать. Наберитесь смелости и откажитесь от тупиковой ветки. Признайтесь, что вы были неправы, выслушайте альтернативные мнения и отступите. Между прочим, для отступления тоже нужна смелость.

Грязь в коде снижает производительность до нуля. Все мы хотим писать чистый совершенный код. Однако, приходит время и к нам приходит заказчик с изменившимися требованиями. Тут у вас есть два варианта: вернуться назад и изменить архитектуру или прикрутить костыль. Костыли в коде имеют привычку плодиться очень быстро. Как только вы прикрутили первый, — ждите второй, третий и двадцатый. Так рождается система, которую невозможно поддерживать и, после того, как вы уйдёте, те, кто придут на ваше место скажут: «Это полное дерьмо. Тут нужно всё переписать». Так ваш проект неминуемо идёт к провалу.

14. Оценка


Бизнес считает оценку обязательством, а разработчик — предположением. В этом есть принципиальное различие. Я надеюсь, всем понятно, чем обязательство отличается от предположения. Менеджер всегда будет добиваться от разработчика обязательства:

— Ты сделаешь переход на ESB за две недели?
— Можем, но, думаю, мне нужно три недели. Я никогда не работал с шинами.
— Тогда пишем три недели?
— Нет, может уйти и 10-11 недель, если наши партнёры не смогут быстро перестроиться на ESB.
Автор книги пишет, что для оценки можно использовать методику PERT и давать три оценки оптимистичную, номинальную и пессимистичную.

Оптимистичная оценка даётся максимально оптимистично. Это тот случай, когда всё идёт идеально и нет никаких проблем. Вероятность низкая, но её нужно учесть. Номинальная оценка — это стандартная ситуация, когда всё идёт более-менее хорошо. Есть небольшие ожидаемые трудности. Пессимистичная оценка — это когда всё идёт плохо: партнёры не понимают, что мы от них хотим, техподдержка долго отвечает, шина теряет пакеты, а документации на вашем родном арабском языке нет.

Часто, чтобы оценить вашу задачу недостаточно только вашего мнения. Хорошо, когда задачу оценит ещё кто-нибудь. Автор предлагает собрать группу экспертов и обсуждать задачу, пока не будет достигнуто согласие в её оценке. Методик голосования множество: от устного волеизъявления до распределения задач по срокам на доске.

Прочитайте оригинал книги: там даются формулы и математика, которой нет в статье.

15. Работа под давлением


Если вы работаете под давлением, — это, скорее всего, непродуктивно. Когда на вас кричат, всё время чего-то требуют, стучат кулаком об стол, краснеют, зеленеют и лишают премии, — это не самый лучший стимул к работе.

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

Ещё руководитель может сказать: «Нам нужно срочно-срочно, поэтому сейчас писать тесты не нужно. Потом допишем». Не ведитесь и отстаивайте свою точку зрения. Даже в кризисных ситуациях нужно применять TDD или TLD, но ни в коем случае не отказываться от тестирования. Это обернётся большими проблемами в будущем.

16. Программисты


Оставшуюся часть книги я перескажу краткими тезисами без подробных расшифровок.

  • Программисты не любят работать с людьми. Именно поэтому они и программисты: они предпочитают работать с предсказуемыми машинами, чем с непредсказуемыми людьми.
  • Программист принимает правила работодателя. Если программист не принимает правил, он увольняется или его увольняют.
  • Программист пишет код, который принадлежит команде. Любой другой член команды может внести изменения в ваш код и вы можете внести изменения в чужой кусок кода. Это накладывает ответственность за то, как вы пишете.
  • Программисты работают парами. Если не всегда, то хотя бы иногда. Иногда очень полезно подсмотреть за тем, как кто-то работает. Программисты-одиночки вместо парного программирования смотрят скринкасты.
  • Программисты работают в группах. А хорошие группы формируются не сразу. Процесс притирания может занять полгода или даже год. Лучше отдавать проект группе, чем временно формировать группу для проекта, а потом расформировывать и перераспределять.
  • У программиста есть наставники. Лучше всего, если это живые люди. Но, возможно, это авторы книг, статей, блогов и видеоуроков. Почти все наши знания мы получаем по парампаре и только иногда придумываем что-то сами и при этом частенько изобретаем велосипед.
  • Программисты пользуются современными инструментами. Используют систему управления исходным кодом, постановкой задач, непрерывную сборку, инструменты тестирования.

Заключение


Книга перевернула моё понимание о профессионализме и дала понимание, куда можно стремиться. Кто-то в комментах к первой части пишет, что всё это написано про сферического программиста в вакууме. Но взгляните на заголовок статьи. Там написано «идеальный», так что тут описано то, к чему нужно идти. Начните с двух-трёх пунктов и постоянно возвращайтесь к книге, вспоминая, что ещё вы можете улучшить.
Счастья вам!

Иллюстрации Александра Корнилова

< Первая часть статьи
Поделиться с друзьями
-->

Комментарии (18)


  1. worldmind
    18.12.2016 15:02
    +2

    > Автор книги пишет, что эти тесты должны быть понятными заказчику и автоматизированными.

    похоже на BDD

    > Инверсия приоритетов

    ИМХО это проблема менеджмента, если задачу не охота делать, это обычно означает что не тому задачу дали или задача вообще никому не нужна или задача криво поставлена, а интуиция сигналит об этом.


    1. MonkAlex
      18.12.2016 17:55

      BDD не мешает TDD же, они по моему не пересекаются особо даже.


    1. deadyshk
      18.12.2016 18:42
      +2

      Простите, а что делать, если задача никому не нравится? Закрывать проект? Ещё никогда не сталкивался с проектами, где сплошь и рядом интересные задачи…


      1. worldmind
        18.12.2016 19:13
        +2

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


      1. igorch96
        19.12.2016 00:27

        Творчески подойти к задаче: либо разбить на более мелкие и легкие или спихнуть компьютеру (или не компьютеру). На крайняк, придумать сильную аргументацию, почему её не надо делать. Ну и последний рубеж, когда ничего не помогает — «сделаю завтра». :)


      1. sentyaev
        19.12.2016 06:34
        -1

        Простите, а что делать, если задача никому не нравится?

        В идеале нужно, что-бы в команде были junior'ы, им все задачи интересны, тк для них почти все вновинку.

        Можно поменяться разработчиками с соседней командой.

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


    1. navff
      19.12.2016 08:01

      Простите, а что делать, если задача никому не нравится?

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

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


  1. kogoia
    18.12.2016 18:42
    +4

    Помню как то менеджеру скинул эту книгу, месяц за ним гнался, спрашивая прочситал ли что-нибудь :D
    Кароче, нужна вторая книга «Как заставить менеджера прочитать <<Идеальный Программист>>»


  1. vadim1406
    19.12.2016 07:45
    +1

    Я бы еще добавил «Не усложняют систему без необходимости»… А то посмотришь на примитивную web-отображалку БД, а там… Слой DAL (все в интерфейсах как положено конечно же, но ни намека на unit-тесты или другую реализацию интерфейсов), бизнес-логика (ничего, что она «пока» только перекидывает модели данных выше), слой UI (конечно на web api 2, ведь мы же слишком круты для простого MVC), и такая же сопля на фронт-энде (реакт, ангуляр, контроллеры, сервисы). И добавление нового поля в БД (и на UI) занимает неделю — надо его везде прописать, потом конечно исправить баги (где-то не прописали), немного порефакторить (а тут мы применим Inversion of Control — это ж круто). А менеджер бегает вокруг заказчика и объясняет, почему он должен еще немного подождать, а пока попользоваться Экселем, попутно теряя деньги :)


    1. navff
      19.12.2016 07:53

      Да. Я совсем недавно смотрел код очень интересной системы. Там всё, прям, как вы пишете. Там, где можно было обойтись тремя слоями, разработчики использовали восемь. Там, где можно было обойтись стандартными средствами, подтянута куча доп. пакетов. Такое впечатление, что они тренировались за деньги заказчика: «А давайте используем это, это и это».

      В результате плёвый проект превратился в нечто неподъёмное, разрабатывался два года и так и не был запущен: на рынке появились сильные конкуренты и проект потерял актуальность. Заказчик выкинул код и стартовал другой проект, надеясь на профессионализм новой команды.


  1. tolik89u
    19.12.2016 07:46

    опечатка: смелось


    1. navff
      19.12.2016 07:47

      Благодарю, поправил


      1. tolik89u
        19.12.2016 11:57

        Мне показалось, или Вы заодно исправили рядом опечатку на -ться/-тся? :) Вчера, вроде, заметил, и хотел сообщить, но мой предыдущий комменатрий был на премодерации, и сайт не позволил мне сообщить. А сегодня уже не нахожу её. :)


        1. navff
          19.12.2016 12:59

          Да, всё верно. Ошибка была, а теперь её нет.


  1. Iudicium
    19.12.2016 10:18

    Спасибо вам за статью!


  1. Shamov
    19.12.2016 10:57

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


  1. eshirshov
    19.12.2016 11:31
    +2

    Блок схема процесса разработки
    1. Предчувствие тупика
    2. Инверсия приоритетов
    3. Работа под давлением
    4. Тупик

    Инверсия приоритетов. Бывает такое, чаще к вечеру, развивается состояние нестояния. Что-бы не делать чтобы ничего не делать. Заставлять себя — только хуже будет. Переключаюсь на что-нибудь низко интеллектуальное — рефакторинг например.


  1. MOTORIST
    19.12.2016 11:37

    Отличная статья. Мантра для программиста =)