97 этюдов для программистов. Опыт ведущих экспертов — страница 11 из 41

Не ищите себе оправданий, если ваш код C# состоит из длинного метода Main и преимущественно статических вспомогательных методов. Лучше разберитесь, почему имеет смысл применять классы. Не избегайте малопонятных лямбда-выражений в функциональных языках, заставьте себя пользоваться ими.

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

Я научился эффективно использовать делегирование в C# после того, как освоил Ruby; раскрытие всех возможностей обобщений. NET (generics) навело меня на мысли о том, как с большей пользой применять обобщения в Java; после LINQ мне было легко изучать Scala.

Переход с одного языка на другой помогает также лучше понять шаблоны проектирования. Программисты на C обнаруживают, что в C# и Java одинаково широко употребляется шаблон итератора. В Ruby и других динамических языках можно все еще пользоваться шаблоном посетителя (visitor), но ваша реализация не будет похожа на пример из книги Банды Четырех (The Gang of Four).

Одни утверждают, что «Поминки по Финнегану» невозможно читать, другие восторгаются стилистической красотой книги. Чтобы облегчить чтение книги, были сделаны ее моноязычные переводы. Забавно, что первый перевод был французским.

С кодом ситуация во многом аналогична. Если писать код в стиле «Поминок», чтобы в нем было чуть-чуть Python, немного Java и примесь Erlang, проект превращается в месиво. Но если вы изучаете новые языки, чтобы расширить свой кругозор и встретить новые идеи для решения задач разными способами, вы обнаружите, что код, который вы пишете на старом проверенном языке, становится более красивым с каждым новым изученным языком.

Не прибивайте программу гвоздями к стенеВерити Стоб

Однажды я написала опрос-розыгрыш по C++, в котором в шутку предложила такую стратегию обработки исключений:

Путем размещения в коде многочисленных конструкций try…catch иногда удается избежать аварийного завершения программы. О полученном в результате состоянии можно сказать, что «тело прибито в вертикальном положении».

Несмотря на легкомыслие, я всего лишь излагала урок, извлеченный из Его Величества Горького Опыта.

То был базовый класс приложения в нашей самописной библиотеке C++. В коде класса многие годы ковырялись шаловливыми ручонками то один программист, то другой. Класс содержал код обработки исключений, ускользнувших от всех других обработчиков. Взяв пример с Йоссариана из «Уловки-22», мы решили или, скорее, нам показалось (слово «решили» предполагает больше мыслительных усилий, чем ушло на создание этого монстра), что экземпляр этого класса должен жить вечно или умереть в попытках это сделать.

С этой целью мы сплели воедино множество обработчиков исключений. Мы смешали обработку структурированных исключений Windows с собственными исключениями (помните __try…__except в C++? Я тоже не помню). Когда неожиданно возникало исключение, мы вызывали методы снова, запихивая в них те же параметры. Когда я вспоминаю это, мне нравится думать, что, создавая вложенный обработчик try…catch внутри предложения catch другого обработчика, я испытывала смутное подозрение, что как-то случайно съехала с надежного шоссе хорошей практики на ароматную, но нездоровую дорогу к безумию. Впрочем, это я понимаю, скорее, задним умом.

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

Я не стала бы отнимать у вас время этой историей, ибо трудно представить, что кто-то еще мог бы соперничать с нашей глупостью, но недавно в сети у меня случилась дискуссия с типом, академический чин которого предполагает большее понимание подобных вопросов. Обсуждался код на Java в удаленных транзакциях. Тип утверждал, что если в коде случился сбой, исключение должно быть перехвачено и блокировано на месте. («И что же с ним тогда делать? — спросила я. — Приготовить его на ужин?»)

Он процитировал правило проектировщиков пользовательских интерфейсов: ПОЛЬЗОВАТЕЛЬ НИКОГДА НЕ ДОЛЖЕН ВИДЕТЬ СООБЩЕНИЕ ОБ ИСКЛЮЧИТЕЛЬНОЙ СИТУАЦИИ, как будто это правило решает проблему, напиши его прописными буквами или как-то еще. Интересно, может, это он автор кода для банкоматов, прославившихся своими синими экранами смерти в некоторых чахлых блогах, и не получил ли он душевную травму на всю жизнь.

Во всяком случае, если вам доведется встретиться с ним, кивайте, улыбайтесь и не слушайте, пока будете бочком пробираться к двери.

Не полагайтесь на «автоматические чудеса»Алан Гриффитс

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

Программирование — некоторое занятие, на которое тратят некоторую часть своего времени некоторые люди. А самая трудная часть работы — мыслительный процесс — менее всего заметна и менее всего ценится непосвященными. Десятилетиями предпринимаются попытки избавиться от потребности в квалифицированных мыслящих кадрах. Одна из наиболее ранних и памятных попыток — усилия Грэйс Хоппер (Grace Hopper) сделать языки программирования не такими таинственными. Благодаря этому, как предсказывали некоторые, потребность в программистах узкой специализации может исчезнуть. Результат (COBOL) способствовал материальному благополучию многих программистов узкой специализации в последующие десятилетия.

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

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

Если вы не заняты активно в каком-то виде деятельности, возникает подсознательное стремление считать, что он прост и происходит «по какому-то волшебству сам по себе». Пока длится это волшебство, все хорошо. Но когда (обычно уместно именно слово «когда», а не «если») волшебство прекращается, проект сталкивается с неприятностями.

Мне встречались проекты, в которых разработчики бесплодно тратили недели своего времени, поскольку никто не осознавал, что их работа зависит от того, «правильная» ли версия DLL загружена. Когда начинались периодические сбои, проверялись все возможные причины, пока кто-то не обращал внимание, что загружалась «неверная» версия DLL.

В другом подразделении все шло гладко: проекты завершались вовремя, без отладок до глубокой ночи и исправлений в последний момент. Настолько гладко, что высшее руководство решило, что все работает «само собой» и можно обойтись без руководителя проекта. Через полгода проекты в этом подразделении стали идти, как везде: с задержками, ошибками и непрерывными заплатками.

Не нужно разбираться во всех «волшебствах», благодаря которым работает ваш проект, но понимать их хотя бы частично не повредит, как и ценить тех, кто разбирается в некоторых вещах лучше вас.

Самое главное, если волшебство вдруг перестанет работать, нужно знать, как его возобновить.

Не повторяй свой кодСтив Смит

«Don’t Repeat Yourself (DRY)» («не повторяйся») является, вероятно, одним из главнейших принципов программирования. Этот принцип сформулировали Энди Хант и Дэйв Томас в книге «Программист-прагматик», и он лежит в основе многих других широко известных правильных подходов и шаблонов проектирования в разработке программного обеспечения. Разработчик, научившийся распознавать дублирование и умеющий устранять его с помощью надлежащих приемов и подходящей абстракции, способен писать гораздо более понятный код, чем тот, кто постоянно загрязняет приложение ненужными повторениями.

Дублирование кода — это балласт

Каждая строка кода приложения требует сопровождения, и она служит источником возможных ошибок в будущем. Дублирование приводит к ненужному увеличению объема кода, что повышает вероятность появления ошибок и делает систему излишне сложной. Увеличение объема системы из-за дублирования, во-первых, мешает разработчикам полностью разобраться в системе, а во-вторых, не позволяет гарантировать, что изменения, внесенные в одном месте, не потребуется повторить в других местах, где дублируется эта логика. Принцип DRY требует, чтобы «каждый элемент информации имел в системе единственное, однозначное и надежное представление».

Повторение в процессах указывает на необходимость автоматизации

Многие процессы в разработке программного обеспечения многократно повторяются и легко автоматизируются. Принцип DRY применим как к исходному коду приложения, так и в подобных контекстах. Ручное тестирование проходит медленно, подвержено ошибкам и повторять его трудно, поэтому по возможности следует применять автоматизированные наборы тестов (test suites