97 этюдов для программистов. Опыт ведущих экспертов - Пит Гудлиф
Можно пойти еще дальше. Будучи тестировщиком, я могу изложить свои соображения по тестированию еще до того, как программисты начнут писать код новой функции. Если я интересуюсь соображениями программистов, они почти всегда предоставляют мне сведения, позволяющие мне добиться лучшего покрытия кода или сократить затраты времени на ненужные тесты. Часто нам удавалось предотвратить появление дефектов за счет того, что тесты проясняют многие первоначальные идеи. Например, в одном из проектов, где я участвовала, я передала программистам Fit-тесты, которые показывали, какие результаты ожидаются при поиске по маске. Программист до этого твердо намеревался реализовать только поиск по конкретным словам. Нам удалось пообщаться с заказчиком, и мы смогли договориться о правильной интерпретации поиска до того, как начать писать код. В результате мы предотвратили возникновение дефекта и сэкономили всем уйму времени.
Программисты могут сотрудничать с тестировщиками и в деле автоматизации. Они знакомы с хорошей практикой написания кода и способны помочь тестировщикам создать надежный комплекс автоматизированных тестов, что послужит интересам всей команды. Мне часто приходилось видеть, как проекты по автоматизации тестирования завершались неудачей из-за неумелого проектирования тестов. Либо тесты пытаются проверить слишком многое, либо тестировщики недостаточно разбираются в технологии, чтобы сделать тесты независимыми от кода. Тестировщики часто создают узкие места, поэтому полезно, когда программисты работают с ними вместе над такими задачами, как автоматизация. Определив вместе с тестировщиками, что можно протестировать на раннем этапе — возможно, с помощью какого-нибудь простого инструмента, — программисты получают дополнительный канал обратной связи, что в конечном итоге позволяет им создать более качественный код.
Если тестировщики перестанут думать лишь о том, как бы им сломать программу или найти ошибки в коде разработчиков, то и программисты перестанут считать, что тестировщики стараются только «достать» их, и будут более склонны к сотрудничеству. Когда программисты понимают, что они отвечают за качество своего кода, легкость его тестирования становится естественным дополнительным качеством, и команда может совместно автоматизировать больше регрессионных тестов. Таково чудо успешной групповой работы.
Пишите код так, как будто вам предстоит сопровождать его всю оставшуюся жизнь
Юрий Зубарев
Можно задать вопрос о том, что должен знать и уметь любой программист, 97 разным людям и получить 97 разных ответов. Это может одновременно ошеломить и напугать. Все советы хороши, все принципы здравы, все истории убедительны, но с чего начать? И, что еще более важно, как, однажды начав применять лучшие практики, оставаться на должном уровне и сделать их составной частью своей практики программирования?
Я думаю, что ответ — в вашем настрое или просто в вашем подходе. Если вам безразличны ваши коллеги-разработчики, тестировщики, менеджеры, сотрудники отделов продаж и маркетинга, а также конечные пользователи, у вас не возникнет побуждения вести, к примеру, разработку на основе тестов или писать понятные комментарии в коде. Думаю, что есть простой способ изменить свое отношение и развить в себе стремление выпускать продукты самого лучшего качества:
Пишите код так, как будто вам предстоит сопровождать его всю оставшуюся жизнь.
Вот и все. Если вы примете эту мысль, начнут происходить удивительные вещи. Согласившись с тем, что любой из ваших прежних или нынешних работодателей имеет право позвонить вам среди ночи и попросить объяснить, на чем основаны решения, сделанные вами при написании некоего метода ТооВаг, вы начнете свой путь к мастерству в программировании. Вам самим захочется придумывать лучшие имена для переменных и методов. Вы постараетесь не допускать, чтобы блоки кода состояли из сотен строк. Вы будете искать, изучать и применять шаблоны проектирования. Вы станете писать комментарии, тестировать код и непрерывно осуществлять его рефакторинг. Поддерживать весь написанный вами код в течение всей оставшейся жизни? Эта задача будет становиться все более грандиозной. У вас просто не останется иного выбора, кроме как работать лучше, изобретательнее и эффективнее.
Если вдуматься, то код, написанный вами много лет назад, продолжает влиять на вашу карьеру, нравится вам это или нет. Каждый метод, класс или модуль, который вы спроектировали или написали, хранит отпечаток ваших знаний, отношения к работе, упорства, профессионализма, степени вовлеченности и уровня удовольствия. Люди формируют о вас свое мнение на основе кода, который они видят. Если это мнение постоянно оказывается отрицательным, ваша карьера не будет развиваться так быстро, как вам хотелось бы. Каждая строка вашего кода должна быть на благо вашей карьере, ваших клиентов и ваших пользователей — пишите код так, как если бы вам пришлось сопровождать его всю оставшуюся жизнь.
Пишите маленькие функции на основе примеров
Кейт Брэйтуэйт
Мы хотим писать правильный код и иметь на руках свидетельство его правильности. В обоих случаях будет полезным принять во внимание «размер» функции. Не в смысле объема кода, который реализует функцию — хотя и это интересно, — а как размер математической функции, которую демонстрирует наш код.
Например, в игре го есть положение, называемое атари, в котором фишки игрока могут быть захвачены противником: фишка с двумя и более свободными соседними клетками (называемыми степенями свободы), не находится в положении атари. Подсчитать количество степеней свободы у фишки бывает нелегко, но, когда оно известно, определить атари легко. Можно для начала написать такую функцию:
boolean atari(int libertyCount)
libertyCount < 2
Здесь спрятано больше, чем кажется на первый взгляд. Математическую функцию можно рассматривать как множество — некоторое подмножество декартова произведения области определения (здесь это int) и области принимаемых значений (здесь — boolean). Будь эти множества одинакового размера, как в Java, в множестве int х boolean было бы 2L*(Integer.MAX_VALUE+(—1L*Integer.MIN_VALUE)+1L), или 8589934592 элементов. Половина из них принадлежит подмножеству, являющемуся нашей функцией, поэтому для полного доказательства корректности нашей функции нужно проверить около 4,3 х 109 случаев.
На этом и основывается утверждение, что тестами нельзя доказать отсутствие дефектов. Тесты способны продемонстрировать, что функциональность реализована. Но проблема размера сохраняется.
Выход подсказывает предметная область. Природа го такова, что число степеней свободы фишки является не любым целым числом, а одним из чисел {1,2,3,4}. Поэтому можно написать другой вариант кода:
LibertyCount = {1,2,3,4}
boolean atari(LibertyCount libertyCount)