Статьи

Вещи, которые должен знать каждый программист

На одном из сайтов-участников нашей программы JCG на сайте ui- иногда публикуются статьи «Вещи, которые должен знать каждый программист». Как указано в первом посте автора, проект «97 вещей, которые должен знать каждый программист», жемчужины мудрости для программистов, собранные у ведущих практиков.

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

В этой статье мы представляем краткое изложение первых 27 «вещей, которые должен знать каждый программист»!

Итак, давайте начнем их, без дальнейших церемоний…

1. Закон с осторожностью от Seb Rose

«Что бы вы ни предпринимали, действуйте с осторожностью и учитывайте последствия» Анон

Независимо от того, насколько комфортно выглядит расписание в начале итерации, вы не можете избежать давления в течение некоторого времени. Если вам приходится выбирать между «делать это правильно» и «делать это быстро», часто бывает полезно «сделать это быстро» при том понимании, что вы вернетесь и исправите это позже. Когда вы даете это обещание себе, своей команде и своему клиенту, вы имеете это в виду. Но слишком часто следующая итерация приносит новые проблемы, и вы сосредотачиваетесь на них. Этот вид отложенной работы известен как технический долг, и это не ваш друг. В частности, Мартин Фаулер называет это преднамеренным техническим долгом в своей таксономии технического долга , который не следует путать с непреднамеренным техническим долгом .

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

Бывают случаи, когда вам приходится брать на себя технические долги, чтобы уложиться в срок или реализовать какой-то фрагмент функции. Постарайтесь не оказаться в таком положении, но если ситуация абсолютно этого требует, тогда действуйте. Но (и это большое НО) вы должны отслеживать технические долги и быстро их погашать, или дела идут быстро вниз. Как только вы примете решение пойти на компромисс, напишите карточку задачи или зарегистрируйте ее в своей системе отслеживания ошибок, чтобы не забыть ее.

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

Погасить технический долг как можно скорее. Было бы неблагоразумно поступить иначе.

2. Применить принципы функционального программирования Эдварда Гарсона

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

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

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

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

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

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

Конечно, такой подход не оптимален во всех ситуациях. Например, в объектно-ориентированных системах этот стиль часто дает лучшие результаты при разработке модели предметной области (т. Е., Когда совместные действия служат для устранения сложности бизнес-правил), чем при разработке пользовательского интерфейса.

Овладейте парадигмой функционального программирования, чтобы вы могли разумно применять полученные уроки в других областях. Ваши объектные системы (для одной) будут резонировать с совершенством ссылочной прозрачности и будут намного ближе к своим функциональным аналогам, чем многие, на ваш взгляд, верят. Фактически, некоторые даже утверждают, что вершина функционального программирования и объектная ориентация являются просто отражением друг друга , формой вычисления инь и ян.

3. Спросите «Что бы сделал пользователь?» (Вы не пользователь) от Giles Colborne

Мы все склонны считать, что другие люди думают как мы. Но они этого не делают. Психологи называют это ошибочным консенсусом . Когда люди думают или действуют по-другому по отношению к нам, мы вполне можем обозначить их (подсознательно) как дефектные в некотором роде.

Этот уклон объясняет, почему программистам так трудно поставить себя на место пользователя. Пользователи не думают как программисты. Для начала они проводят гораздо меньше времени за компьютерами. Они не знают и не заботятся о том, как работает компьютер. Это означает, что они не могут использовать ни одну из техник решения проблем, знакомых программистам. Они не распознают шаблоны и подсказки, которые программисты используют для работы, через интерфейс и вокруг него.

Лучший способ узнать, как думают пользователи, — это посмотреть. Попросите пользователя выполнить задачу, используя программный продукт, аналогичный тому, который вы разрабатываете. Убедитесь, что задача реальная: «Сложите столбец чисел» — все в порядке; «Рассчитайте свои расходы за последний месяц» лучше. Избегайте слишком специфичных задач, таких как «Можете ли вы выбрать эти ячейки электронной таблицы и ввести формулу SUM ниже?» — в этом вопросе есть большая подсказка. Попросите пользователя рассказать о своем прогрессе. Не перебивай. Не пытайся помочь. Продолжайте спрашивать себя: «Почему он это делает?» и «Почему она этого не делает?»

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

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

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

4. Автоматизируйте ваш стандарт кодирования , Филип ван Лаенен

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

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

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

Существует множество инструментов, которые можно использовать для создания отчетов о качестве кода, а также для документирования и поддержания стандарта кодирования, но это еще не все решение. Это должно быть автоматизировано и применено, где это возможно. Вот несколько примеров:

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

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

Наконец, стандарт кодирования должен быть динамическим, а не статическим. По мере развития проекта потребности проекта меняются, и то, что вначале казалось умным, через несколько месяцев не обязательно будет умным.

5. Красота в простоте . Йорн Ольмхайм

Есть одна цитата, которая, на мой взгляд, особенно полезна для всех разработчиков программного обеспечения:

Красота стиля, гармония, грация и хороший ритм зависят от простоты. — Платон

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

  • читабельность
  • Ремонтопригодность
  • Скорость развития
  • Неуловимое качество красоты

Платон говорит нам, что фактором, способствующим всем этим качествам, является простота.

Что такое красивый код? Это потенциально очень субъективный вопрос. Восприятие красоты во многом зависит от индивидуального фона, так же как и наше восприятие чего-либо зависит от нашего фона. Люди, получившие образование в области искусства, воспринимают красоту (или, по крайней мере, подходят к ней) иначе, чем люди, получившие образование в области наук. Специалисты по искусству склонны подходить к красоте в программном обеспечении, сравнивая программное обеспечение с произведениями искусства, в то время как специалисты по науке склонны говорить о симметрии и золотом сечении, пытаясь привести вещи к формулам. По моему опыту, простота является основой большинства аргументов с обеих сторон.

Подумайте об исходном коде, который вы изучили. Если вы не потратили время на изучение кода других людей, прекратите читать это прямо сейчас и найдите для изучения некоторый открытый исходный код. Шутки в сторону! Я серьезно! Найдите в Интернете какой-нибудь код на выбранном вами языке, написанный известным, признанным экспертом.

Вы вернулись? Хороший. Где мы были? Ах, да … Я нашел тот код, который резонирует со мной и который я считаю красивым, имеет ряд общих свойств. Главным среди них является простота. Я считаю, что независимо от сложности всего приложения или системы, отдельные части должны быть простыми. Простые объекты с единственной ответственностью, содержащие одинаково простые, сфокусированные методы с описательными именами. Некоторые люди думают, что идея иметь короткие методы из пяти-десяти строк кода является экстремальной, а некоторые языки делают это очень трудным, но я думаю, что такая краткость является желательной целью, тем не менее.

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

Красота рождается и находится в простоте.

6. Прежде, чем Вы Рефакторинг от Rajith Attapattu

В какой-то момент каждому программисту потребуется провести рефакторинг существующего кода. Но прежде чем сделать это, подумайте о следующем, так как это может сэкономить вам и другим много времени (и боли):

  • Лучший подход к реструктуризации начинается с оценки существующей кодовой базы и тестов, написанных для этого кода . Это поможет вам понять сильные и слабые стороны кода в его нынешнем виде, чтобы вы могли сохранить сильные стороны, избегая ошибок. Мы все думаем, что можем добиться большего успеха, чем существующая система … пока мы не получим что-то не лучше или даже хуже, чем в предыдущем воплощении, потому что мы не смогли извлечь уроки из ошибок существующей системы.
  • Избегайте соблазна переписать все . Лучше всего использовать как можно больше кода. Независимо от того, насколько уродлив код, он уже был протестирован, проверен и т. Д. Выброс старого кода — особенно если он был в производстве — означает, что вы выбрасываете месяцы (или годы) проверенного, закаленного в боях кода, который возможно, имелись определенные обходные пути и исправления ошибок, о которых вы не знали. Если вы не принимаете это во внимание, новый код, который вы пишете, может в конечном итоге показывать те же загадочные ошибки, которые были исправлены в старом коде. Это потратит много времени, усилий и знаний, полученных за эти годы.
  • Многие постепенные изменения лучше, чем одно массивное изменение . Инкрементные изменения позволяют более легко оценить влияние на систему с помощью обратной связи, например, из тестов. Не приятно видеть сотню неудачных тестов после внесения изменений. Это может привести к разочарованию и давлению, что, в свою очередь, может привести к неправильным решениям. С парой неудачных тестов легко справиться, и они обеспечивают более управляемый подход.
  • После каждой итерации важно убедиться, что существующие тесты пройдены . Добавьте новые тесты, если существующих тестов недостаточно, чтобы покрыть внесенные вами изменения. Не выбрасывайте тесты из старого кода без должного рассмотрения. На первый взгляд, некоторые из этих тестов могут не подходить для вашего нового дизайна, но это будет стоить усилий, чтобы углубиться в причины, по которым этот конкретный тест был добавлен.
  • Личные предпочтения и эго не должны мешать . Если что-то не сломано, зачем это чинить? То, что стиль или структура кода не соответствуют вашим личным предпочтениям, не является уважительной причиной для реструктуризации. Думать, что вы могли бы работать лучше, чем предыдущий программист, также не является веской причиной.
  • Новая технология не является достаточным основанием для проведения рефакторинга . Одна из худших причин для рефакторинга заключается в том, что текущий код сильно отстает от всех крутых технологий, которыми мы располагаем сегодня, и мы верим, что новый язык или фреймворк могут делать вещи более элегантно. Если анализ затрат и выгод не покажет, что новый язык или структура приведут к значительным улучшениям в функциональности, удобстве обслуживания или производительности, лучше оставить все как есть.
  • Помните, что люди делают ошибки . Реструктуризация не всегда гарантирует, что новый код будет лучше или даже лучше предыдущей попытки. Я видел и был частью нескольких неудачных попыток реструктуризации. Это было не красиво, но это было по-человечески.

7. Остерегайтесь доли Уди Дахана

Это был мой первый проект в компании. Я только что закончил свою степень и очень хотел проявить себя, оставаясь допоздна каждый день, просматривая существующий код. Работая над своей первой функцией, я проявил особую осторожность, чтобы внедрить все, что я узнал — комментирование, ведение журнала, извлечение общего кода в библиотеки, где это возможно, работает. Обзор кода, к которому я чувствовал себя таким готовым, стал грубым пробуждением — повторное использование было осуждено!

Как это могло произойти? Все время повторного использования в колледже считалось воплощением качественной разработки программного обеспечения. Все статьи, которые я прочитал, учебники, опытные профессионалы в области программного обеспечения, которые учили меня. Было ли это все неправильно?

Оказывается, мне не хватало чего-то критического.

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

Библиотеки общего кода, которые я создал, привязывали шнурки каждой ноги друг к другу. Шаги по одному бизнес-домену не могут быть выполнены без предварительной синхронизации с другим. Раньше затраты на обслуживание этих независимых функций были незначительными, но общая библиотека требовала на порядок большего тестирования.
Хотя я уменьшил абсолютное количество строк кода в системе, я увеличил количество зависимостей. Контекст этих зависимостей имеет решающее значение — если бы они были локализованы, это могло бы быть оправданным и иметь некоторую положительную ценность. Когда эти зависимости не контролируются, их усики запутывают большие проблемы системы, хотя сам код выглядит просто отлично.

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

Остерегайтесь доли. Проверьте свой контекст. Только тогда продолжайте.

8. Правило бойскаута от дяди Боба

У бойскаутов есть правило: «Всегда оставляйте лагерь чище, чем вы его нашли». Если вы найдете беспорядок на земле, вы убираете его независимо от того, кто мог создать беспорядок. Вы намеренно улучшаете окружающую среду для следующей группы отдыхающих. На самом деле оригинальная форма этого правила, написанная Робертом Стивенсоном Смитом Баден-Пауэллом, отцом скаутинга, гласила: «Постарайся покинуть этот мир немного лучше, чем ты его нашел».

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

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

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

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

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

9. Сначала проверьте свой код, прежде чем искать виноватых Аллан Келли

Разработчики — все мы! — часто им трудно поверить, что наш собственный код не работает. Просто невероятно, что на этот раз сломался компилятор.

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

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

Предполагая, что инструменты широко используются, зрелы и используются в различных технологических стеках, нет оснований сомневаться в качестве. Конечно, если инструмент раннего выпуска, или его используют всего несколько человек по всему миру, или редко загружаемая версия 0.1 с открытым исходным кодом, может быть веская причина заподозрить программное обеспечение. (Точно так же альфа-версия коммерческого программного обеспечения может быть подозрительной.)

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

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

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

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

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

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

10. Рассмотрим оборудование от Джейсона П Сейджа

Распространено мнение, что медленное программное обеспечение просто нуждается в более быстром оборудовании. Такое мышление не обязательно ошибочно, но, как и злоупотребление антибиотиками, со временем оно может стать большой проблемой. Большинство разработчиков не имеют ни малейшего представления, что на самом деле происходит «под капотом». Часто существует прямой конфликт интересов между лучшими практиками программирования и написанием кода, который кричит на данном оборудовании.

Во-первых, давайте рассмотрим кэш предварительной загрузки вашего процессора в качестве примера. Большинство кэшей предварительной выборки работают, постоянно оценивая код, который еще даже не выполнен. Они помогают повысить производительность, «угадывая», куда будет переходить ваш код еще до того, как это произошло. Когда кэш «угадывает» правильно, он удивительно быстр. Если он «угадывает» неправильно, с другой стороны, вся предварительная обработка в этой «неправильной ветви» бесполезна, и происходит длительная аннулирование кэша. К счастью, легко начать делать кеш предварительной выборки более трудным для вас. Если вы закодируете свою логику ветвления так, чтобы наиболее частым результатом было условие, которое проверяется, вы поможете кэшу предварительной выборки вашего ЦП «исправляться» чаще, что приведет к меньшему количеству недействительных затрат на ЦП. Иногда это может показаться немного неловким, но систематическое применение этой методики со временем уменьшит время выполнения вашего кода.

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

Люди предпочитают писать много маленьких функций в пользу больших, чтобы облегчить обслуживание, но все эти вызовы функций имеют свою цену! Если вы используете эту парадигму, ваше программное обеспечение может тратить больше времени на подготовку и восстановление после работы, чем на самом деле! Команда goto или jmp, которой очень не нравятся, является самым быстрым методом обхода, за которым следуют таблицы переходов косвенной адресации машинного языка. Функции хороши для людей, но с точки зрения процессора они дороги.

Как насчет встроенных функций? Разве встроенные функции не обменивают размер программы на эффективность, копируя встроенный код функции, а не перепрыгивая? Да, они делают! Но даже когда вы указываете, что функция должна быть встроенной, можете ли вы быть уверены, что это так? Знаете ли вы, что некоторые компиляторы превращают обычные функции в встроенные, когда им это нравится, и наоборот? Понимание машинного кода, созданного вашим компилятором, из вашего исходного кода чрезвычайно важно, если вы хотите написать код, который будет оптимально работать для данной платформы.

Многие разработчики считают, что абстрагирование кода до n-й степени и использование наследования — это просто вершина отличного проектирования программного обеспечения. Иногда конструкции, которые выглядят великолепно концептуально, на практике ужасно неэффективны. Возьмем, к примеру, унаследованные виртуальные функции: они довольно удобны, но в зависимости от фактической реализации они могут быть очень дорогостоящими в тактовых циклах ЦП.

Для какого оборудования вы разрабатываете? Что ваш компилятор делает с вашим кодом, когда он превращает его в машинный код? Вы используете виртуальную машину? Вы редко найдете единую методологию программирования, которая будет отлично работать на всех аппаратных платформах, реальных или виртуальных.

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

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

Разработчики видеоигр и встроенных систем знают об аппаратных последствиях своего скомпилированного кода. Вы?

11. Непрерывный рефакторинг от Michael Hunger

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

Совершенно неверно отрицать, что код может расти со знаниями и способностями.

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

  • Дублирование, ближнее и дальнее
  • Непоследовательные или неинформативные имена
  • Длинные блоки кода
  • Неразборчивые логические выражения
  • Длинные последовательности условных выражений
  • Работа в кишечнике других подразделений (объектов, модулей)
  • Объекты, раскрывающие их внутреннее состояние

Если у вас есть возможность, попробуйте дезодорировать вонючий код. Не торопись. Просто сделай маленькие шаги. В « Рефакторинге» Мартина Фаулера шаги представленного рефакторинга описаны очень подробно, поэтому за ним легко следовать. Я бы предложил выполнить эти шаги хотя бы один раз вручную, чтобы понять предусловия и побочные эффекты каждого рефакторинга. Думать о том, что вы делаете, абсолютно необходимо при рефакторинге. Небольшой сбой может стать большой проблемой, поскольку он может повлиять на большую часть базы кода, чем предполагалось.

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

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

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

При рефакторинге вы часто сталкиваетесь с прозрением в какой-то момент. Это происходит, когда внезапно все кусочки головоломки попадают в место, где они принадлежат, а сумма вашего кода больше его частей. С этого момента довольно легко сделать шаг в развитии вашей системы или ее архитектуры.

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

12. Виджай Нараянан: постоянно настраивать программное обеспечение для повторного использования

Часто упоминаемая причина неспособности создавать повторно используемое программное обеспечение — нехватка времени в процессе разработки. Ловкость и рефакторинг — ваши друзья для повторного использования. Примените прагматичный подход к усилиям по повторному использованию, и вы значительно увеличите шансы на успех. Стратегия, которую я использовал при создании программного обеспечения многократного использования, заключается в непрерывном выравнивании. Что такое непрерывное выравнивание?

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

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

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

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

13. Вопросы по разметке кода Стивом Фриманом

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

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

  • Легко сканировать . Люди действительно хороши в визуальном сопоставлении с образцом (пережиток того времени, когда нам приходилось замечать львов в саванне), поэтому я могу помочь себе, сделав все, что не имеет прямого отношения к области, всю «случайную сложность», которая поставляется с большинством коммерческих языков, отходит на задний план, стандартизируя его. Если код, который ведет себя одинаково, выглядит одинаково, то моя система восприятия поможет мне выявить различия. Вот почему я также соблюдаю соглашения о том, как размещать части класса в модуле компиляции: константы, поля, открытые методы, частные методы.
  • Выразительная верстка. Мы все научились тратить время на поиск правильных имен, чтобы наш код как можно более четко выражал, что он делает, а не просто перечислял шаги — верно? Компоновка кода также является частью этой выразительности. Во-первых, команда должна согласовать автоматический форматер для основ, а затем я могу внести изменения вручную, пока я пишу код. Если нет активных разногласий, команда быстро сойдется в едином стиле «ручной работы». Форматировщик не может понять мои намерения (я должен знать, я однажды написал один), и для меня более важно, чтобы разрывы строк и группировки отражали намерения кода, а не только синтаксис языка. (Кевин МакГуайр освободил меня от рабства для автоматического форматирования кода.)
  • Компактный формат . Чем больше я могу видеть на экране, тем больше я могу видеть, не нарушая контекста, прокручивая или переключая файлы, что означает, что я могу сохранять меньше состояния в своей голове. Длинные комментарии к процедурам и множество пробелов имели смысл для 8-символьных имен и строчных принтеров, но теперь я живу в среде IDE, которая выполняет раскрашивание синтаксиса и перекрестные ссылки. Пиксели — это мой ограничивающий фактор, поэтому я хочу, чтобы каждый внес свой вклад в мое понимание кода. Я хочу, чтобы макет помог мне понять код, но не более того.

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

14. Обзоры кода Маттиас Карлссон

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

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

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

Будьте осторожны при проверке кода. Убедитесь, что комментарии конструктивные, а не едкие . Вводите разные роли проверки для совещания проверки, чтобы избежать влияния организационного старшинства среди членов команды на проверку кода. Примеры ролей могут включать, чтобы один рецензент сосредоточился на документации, другой — на исключениях, а третий — на функциональности. Этот подход помогает распределить бремя проверки между членами команды.

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

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

15. Кодирование с Разумом от Yechiel Kimchi

Попытка рассуждать о корректности программного обеспечения вручную приводит к формальному доказательству, которое длиннее кода и с большей вероятностью содержит ошибки, чем код. Автоматизированные инструменты предпочтительнее, но не всегда возможны. Далее следует средний путь: полуформальное рассуждение о правильности.

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

Раздел должен быть выбран так, чтобы в каждой конечной точке состояние программы (а именно, счетчик программы и значения всех «живых» объектов) удовлетворял легко описываемому свойству, и чтобы функциональность этого раздела (преобразование состояния) была простой описать как отдельную задачу — это облегчит рассуждение. Такие свойства конечных точек обобщают такие понятия, как предусловие и постусловие для функций и инвариант для циклов и классов (относительно их экземпляров). Стремление к тому, чтобы разделы были настолько независимы друг от друга, насколько это возможно, упрощает рассуждение и является необходимым условием для изменения этих разделов.

Многие из методов кодирования, которые хорошо известны (хотя, возможно, менее хорошо соблюдаются) и считаются «хорошими», облегчают рассуждение. Следовательно, просто намереваясь рассуждать о своем коде, вы уже начинаете думать о лучшем стиле и структуре. Неудивительно, что большинство из этих методов могут быть проверены статическими анализаторами кода:

  • Избегайте использования операторов goto , поскольку они делают удаленные разделы очень взаимозависимыми.
  • Избегайте использования изменяемых глобальных переменных, поскольку они делают все разделы, которые их используют, зависимыми.
  • Каждая переменная должна иметь наименьшую возможную область видимости. Например, локальный объект может быть объявлен непосредственно перед его первым использованием.
  • Делайте объекты неизменяемыми, когда это уместно.
  • Сделайте код читаемым, используя интервалы, как горизонтальные, так и вертикальные. Например, выравнивание связанных структур и использование пустой строки для разделения двух разделов.
  • Сделайте код самодокументированным, выбрав описательные (но относительно короткие) имена для объектов, типов, функций и т. Д.
  • Если вам нужен вложенный раздел, сделайте его функцией.
  • Сделайте свои функции короткими и сфокусированными на одной задаче. Старый 24- строчный лимит все еще применяется. Хотя размер экрана и разрешение изменились, ничего не изменилось в человеческом познании с 1960-х годов.
  • Функции должны иметь несколько параметров (четыре — хорошая верхняя граница). Это не ограничивает данные, передаваемые функциям: группирование связанных параметров в единый объект выигрывает от инвариантов объекта и сохраняет рассуждения, такие как их согласованность и согласованность.
  • В более общем смысле каждая единица кода, от блока до библиотеки, должна иметь узкий интерфейс . Меньше общения уменьшает необходимость рассуждений. Это означает, что получатели, которые возвращают внутреннее состояние, являются ответственностью — не запрашивайте у объекта информацию для работы. Вместо этого попросите объект выполнить работу с уже имеющейся информацией. Другими словами, инкапсуляция — это все — и только — о узких интерфейсах .
  • Чтобы сохранить инварианты класса, не рекомендуется использовать сеттеры, поскольку сеттеры, как правило, допускают нарушение инвариантов, управляющих состоянием объекта.

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

16. Комментарий к комментариям Кэла Эванса

На моем первом уроке программирования в колледже мой учитель раздал два листа кодирования BASIC. На доске задание гласило: «Напишите программу для ввода и усредните 10 баллов за боулинг». Затем учитель вышел из комнаты. Насколько сложно это может быть? Я не помню своего окончательного решения, но я уверен, что в нем был цикл FOR / NEXT, и он не мог содержать более 15 строк. Листы кодирования — для вас, дети, которые читают это, да, мы обычно записывали код перед тем, как вводить его в компьютер, — каждая из них содержала около 70 строк кода. Я был очень смущен тем, почему учитель дал нам два листа. Поскольку мой почерк всегда был жестоким, я использовал второй, чтобы аккуратно переписать свой код, надеясь получить пару дополнительных очков за стиль.

К моему большому удивлению, когда я получил задание в начале следующего класса, я получил едва проходную оценку. (Это должно было быть предзнаменованием для меня до конца моего времени в колледже.) Нацарапана в верхней части моего аккуратно скопированного кода: «Без комментариев?»

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

Комментарии не злые. Они так же необходимы для программирования, как базовые разветвляющиеся или зацикливающиеся конструкции. В большинстве современных языков есть инструмент, похожий на javadoc, который будет анализировать правильно отформатированные комментарии, чтобы автоматически создавать документ API. Это очень хорошее начало, но этого недостаточно. Внутри вашего кода должны быть пояснения о том, что код должен делать. Кодирование старой поговоркой «Если было трудно писать, должно быть трудно читать», оказывает плохую услугу вашему клиенту, вашему работодателю, вашим коллегам и вашему будущему «я».

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

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

17. Комментируйте только то, что код не может сказать Кевлин Хенни

Разница между теорией и практикой больше на практике, чем в теории — наблюдение, безусловно, относится к комментариям. Теоретически, общая идея комментирования кода звучит как достойная: предложите читателю подробности, объяснение того, что происходит. Что может быть полезнее, чем быть полезным? На практике, однако, комментарии часто становятся проблемой. Как и в любой другой форме письма, есть навык написания хороших комментариев. Большая часть умения заключается в том, чтобы знать, когда их не писать.

Когда код плохо сформирован, компиляторы, интерпретаторы и другие инструменты будут обязательно возражать. Если код каким-либо образом некорректен в функциональном отношении, обзоры, статический анализ, тесты и повседневное использование в производственной среде устранят большинство ошибок. Но как насчет комментариев? В «Элементах стиля программирования » Керниган и Плаугер отметили, что «комментарий имеет нулевое (или отрицательное) значение, если он неправильный». И все же такие комментарии часто засоряются и выживают в кодовой базе таким образом, что ошибки кодирования никогда не могли. Они обеспечивают постоянный источник отвлечения и дезинформации, тонкое, но постоянное затягивание мышления программиста.

Что из комментариев, которые не являются технически неправильными, но не добавляют никакой ценности к коду? Такие комментарии являются шумом. Комментарии, которые попугайуют код, не предлагают ничего лишнего для читателя — изложение чего-то один раз в коде и снова на естественном языке не делает его более правдивым или более реальным. Закомментированный код не является исполняемым кодом, поэтому он не имеет никакого полезного эффекта ни для читателя, ни для среды выполнения. Это также становится устаревшим очень быстро. Связанные с версией комментарии и закомментированный код пытаются ответить на вопросы версий и истории. На эти вопросы уже ответили (гораздо более эффективно) инструменты контроля версий.

Распространенность зашумленных комментариев и неправильных комментариев в кодовой базе побуждает программистов игнорировать все комментарии, пропуская их или предпринимая активные меры по их скрытию. Программисты находчивы и будут обходить все, что воспринимается как ущерб: складывать комментарии; переключение раскраски так, чтобы комментарии и фон были одного цвета; скрипты для фильтрации комментариев. Чтобы избавить базу кода от таких неправильных применений изобретательности программиста и снизить риск пропуска любых комментариев, имеющих подлинную ценность, комментарии следует рассматривать так, как если бы они были кодом. Каждый комментарий должен добавить некоторую ценность для читателя, иначе это отходы, которые следует удалить или переписать.

Что тогда квалифицируется как ценность? Комментарии должны сказать что-то код не может и не может сказать. Комментарий, объясняющий, что часть кода уже должна сказать, является приглашением изменить структуру кода или соглашения о кодировании, чтобы код говорил сам за себя. Вместо того, чтобы компенсировать плохие имена методов или классов, переименуйте их. Вместо того, чтобы комментировать разделы в длинных функциях, извлекайте меньшие функции, чьи имена отражают намерения предыдущих разделов. Попробуйте выразить как можно больше через код. Любой недостаток между тем, что вы можете выразить в коде, и тем, что вы хотели бы выразить в целом, становится вероятным кандидатом на полезный комментарий. Прокомментируйте то, что код не может сказать, а не просто то, что он не говорит.

18. Непрерывное обучение Клинта Шэнка

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

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

Вот список способов научить вас. Многие из них можно найти в Интернете бесплатно:

  • Читайте книги, журналы, блоги, твиттеры и веб-сайты. Если вы хотите углубиться в тему, рассмотрите возможность присоединения к списку рассылки или группе новостей.
  • Если вы действительно хотите погрузиться в технологию, попробуйте — напишите немного кода.
  • Всегда старайтесь работать с наставником, так как быть лучшим из них может помешать вашему образованию. Хотя вы можете чему-то научиться у любого, вы можете узнать намного больше от кого-то умнее или опытнее, чем вы. Если вы не можете найти наставника, подумайте о том, чтобы двигаться дальше.
  • Используйте виртуальных наставников. Найдите в сети авторов и разработчиков, которые вам действительно нравятся, и прочитайте все, что они пишут. Подпишитесь на их блоги.
  • Познакомьтесь с фреймворками и библиотеками, которые вы используете. Знание того, как что-то работает, заставляет вас знать, как использовать это лучше. Если они с открытым исходным кодом, вам действительно повезло. Используйте отладчик, чтобы пройтись по коду, чтобы увидеть, что происходит под капотом. Вы увидите код, написанный и проверенный некоторыми действительно умными людьми.
  • Всякий раз, когда вы делаете ошибку, исправляете ошибку или сталкиваетесь с проблемой, старайтесь действительно понять, что произошло. Вероятно, кто-то еще столкнулся с той же проблемой и опубликовал ее где-то в Интернете. Google действительно полезен здесь.
  • Действительно хороший способ научиться чему-то — это учить или говорить об этом. Когда люди будут слушать вас и задавать вам вопросы, вы будете мотивированы учиться. Попробуйте обед-н-учиться на работе, в группе пользователей или на местной конференции.
  • Присоединитесь или создайте учебную группу (по образцу сообщества) или локальную группу пользователей для языка, технологии или дисциплины, которые вас интересуют.
  • Ходить на конференции. И если вы не можете пойти, многие конференции размещают свои выступления в Интернете бесплатно.
  • Долго ездить? Слушайте подкасты.
  • Вы когда-нибудь запускали инструмент статического анализа над базой кода или просматривали предупреждения в вашей IDE? Понять, что они сообщают и почему.
  • Следуйте советам прагматичных программистов и изучайте новый язык каждый год. По крайней мере, изучите новую технологию или инструмент. Разветвление дает вам новые идеи, которые вы можете использовать в своем текущем технологическом стеке.
  • Не все, что вы изучаете, должно быть о технологиях. Изучите домен, в котором вы работаете, чтобы лучше понять требования и помочь решить бизнес-проблему. Научиться быть более продуктивным — как работать лучше — это еще один хороший вариант.
  • Идти обратно в школу.

Было бы неплохо иметь возможность, которую Neo имел в The Matrix, и просто загружать необходимую нам информацию в наш мозг. Но мы этого не делаем, поэтому потребуется время. Вам не нужно тратить каждый час на обучение. Немного времени, скажем, каждую неделю, лучше, чем ничего. Есть (или должна быть) жизнь вне работы.

Технология быстро меняется. Не оставляй позади.

19. Грегор Хопе не удобство

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

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

  • Я не хочу, чтобы другие классы делали два отдельных вызова, чтобы сделать это одно.
  • Зачем мне делать другой метод, если он почти такой же, как этот метод? Я просто добавлю простой переключатель .
  • Видите, это очень просто: если второй строковый параметр оканчивается на «.txt», метод автоматически предполагает, что первый параметр является именем файла, поэтому мне действительно не нужны два метода.

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

1
parser.processNodes(text, false);

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

Метафора API как языка может привести нас к лучшим проектным решениям в этих ситуациях. API должен обеспечивать выразительный язык, который дает следующему уровню выше словарный запас, чтобы задавать полезные вопросы и отвечать на них. Это не означает, что он должен предоставлять ровно один метод или глагол для каждого вопроса, который стоит задать. Разнообразный словарный запас позволяет нам выразить тонкости в значении. Например, мы предпочитаем говорить « ход» вместо « ходьба» (true) , даже если это можно рассматривать как по сути одну и ту же операцию, просто выполняемую на разных скоростях. Последовательный и хорошо продуманный словарь API делает код более выразительным и простым для понимания на следующем уровне. Что еще более важно, составляемый словарь позволяет другим программистам использовать API способами, которые вы, возможно, не ожидали — большое удобство для пользователей API! В следующий раз, когда у вас возникнет соблазн объединить несколько вещей в один метод API, помните, что в английском языке нет одного слова для MakeUpYourRoomBeQuietAndDoYourHomeWork , даже если это кажется действительно удобным для такой часто запрашиваемой операции.

20. Развертывание рано и часто Стив Берчук

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

Процесс установки / развертывания — это первое, что видит клиент, а простой процесс установки / развертывания — это первый шаг к созданию надежной (или, по крайней мере, простой в отладке) производственной среды. Развернутое программное обеспечение — это то, что клиент будет использовать. Не гарантируя, что развертывание правильно настроит приложение, вы будете задавать вопросы своим клиентам, прежде чем они начнут использовать ваше программное обеспечение полностью.

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

Последнее развертывание означает, что процесс развертывания может быть более сложным, чтобы обойти предположения в коде. То, что казалось отличной идеей в IDE, где у вас есть полный контроль над средой, может сделать процесс развертывания намного более сложным. Лучше знать все компромиссы раньше, чем позже.

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

Процесс установки / развертывания важен для продуктивности ваших клиентов или вашей профессиональной команды обслуживания, поэтому вы должны тестировать и реорганизовывать этот процесс по мере необходимости. Мы тестируем и реорганизуем исходный код на протяжении всего проекта. Развертывание заслуживает не меньше.

21. Различают бизнес-исключения Дана Берга Джонссона

Есть две основные причины, по которым что-то идет не так во время выполнения: технические проблемы, которые мешают нам использовать приложение, и бизнес-логика, которая мешает нам неправильно использовать приложение. Большинство современных языков, таких как LISP, Java, Smalltalk и C #, используют исключения для сигнализации обеих этих ситуаций. Тем не менее, эти две ситуации настолько различны, что их следует тщательно разделять. Это потенциальный источник путаницы, когда они представляют одну и ту же иерархию исключений, не говоря уже об одном и том же классе исключений.

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

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

Вариант этой ситуации — когда вы находитесь в «библиотечной ситуации», и вызывающая сторона нарушила контракт вашего метода, например, передала совершенно странный аргумент или неправильно настроила зависимый объект. Это наравне с доступом к 83-му элементу из 17: вызывающий должен проверить; это не является ошибкой программиста на стороне клиента. Правильный ответ — бросить техническое исключение.

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

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

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

22. Много ли преднамеренных практик Джон Джаггер

Умышленная практика — это не просто выполнение задачи. Если вы спросите себя: «Почему я выполняю это задание?» и ваш ответ: «Чтобы выполнить задачу», тогда вы не делаете преднамеренную практику.

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

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

Сколько преднамеренной практики требуется, чтобы приобрести опыт?

  • Питер Норвиг пишет : «Может быть, 10 000 часов […] магическое число».
  • Мэри Поппендик в своей книге « Leading Lean Software Development» отмечает, что «элитным исполнителям требуется не менее 10 000 часов преднамеренной целенаправленной практики, чтобы стать экспертами».

Экспертиза приходит со временем постепенно — не все сразу за 10000 час! Тем не менее, 10 000 часов это много: около 20 часов в неделю в течение 10 лет. Учитывая этот уровень приверженности, вы можете беспокоиться, что вы просто не экспертный материал. Вы. Величие во многом зависит от осознанного выбора. Твой выбор Исследования последних двух десятилетий показали, что основным фактором приобретения опыта является время, затрачиваемое на обдуманную практику. Врожденная способность не является основным фактором.

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

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

  • Питер: «Ключ [к развитию экспертизы] — это совещательная практика: не просто делать это снова и снова, но ставить перед собой задачу, которая выходит за рамки ваших текущих возможностей, пробует ее, анализирует вашу производительность во время и после выполнения и корректирует любые ошибки. »
  • Мэри: «Намеренная практика не означает, что ты делаешь то, что у тебя хорошо получается; это значит бросать вызов себе, делать то, что у тебя плохо получается. Так что это не обязательно весело ».

Умышленная практика — это обучение. Об обучении, которое меняет вас; узнав, что меняет ваше поведение. Удачи.

23. Специфичные для домена языки Майкла Хангера

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

В мире программного обеспечения DSL — это исполняемые выражения на языке, специфичном для домена с ограниченным словарным запасом и грамматикой, которые могут быть прочитаны, понятны и, как мы надеемся, доступны для записи специалистам в области. DSL, предназначенные для разработчиков программного обеспечения или ученых, существуют уже давно. Например, «маленькие языки» Unix, найденные в файлах конфигурации, и языки, созданные с помощью макросов LISP, являются одними из старых примеров.

DSL обычно классифицируются как внутренние или внешние:

  • Внутренние DSL написаны на языке программирования общего назначения, синтаксис которого был согнут, чтобы выглядеть намного больше как естественный язык. Это проще для языков, которые предлагают больше синтаксического сахара и возможностей форматирования (например, Ruby и Scala), чем для других, которые этого не делают (например, Java). Большинство внутренних DSL обертывают существующие API, библиотеки или бизнес-код и предоставляют оболочку для менее изнурительного доступа к функциональности. Они выполняются напрямую, просто запустив их. В зависимости от реализации и домена они используются для построения структур данных, определения зависимостей, запуска процессов или задач, взаимодействия с другими системами или проверки ввода пользователя. Синтаксис внутреннего DSL ограничен языком хоста. Существует много шаблонов — например, построитель выражений, объединение методов и аннотации — которые могут помочь вам согнуть основной язык в DSL. Если основной язык не требует перекомпиляции, внутренний DSL может быть разработан довольно быстро, работая бок о бок с экспертом по предметной области.
  • Внешние DSL являются текстовыми или графическими выражениями языка — хотя текстовые DSL, как правило, встречаются чаще, чем графические. Текстовые выражения могут обрабатываться цепочкой инструментов, которая включает в себя лексер, анализатор, преобразователь модели, генераторы и любой другой тип постобработки. Внешние DSL чаще всего считываются внутренними моделями, которые составляют основу для дальнейшей обработки. Полезно определить грамматику (например, в EBNF). Грамматика обеспечивает отправную точку для генерации частей цепочки инструментов (например, редактор, визуализатор, генератор анализатора). Для простых DSL может быть достаточно парсера ручной работы — например, с помощью регулярных выражений. Пользовательские парсеры могут стать громоздкими, если от них слишком много просят, поэтому имеет смысл взглянуть на инструменты, разработанные специально для работы с языковыми грамматиками и DSL — например, openArchitectureWare, ANTlr, SableCC, AndroMDA. Определение внешних DSL как диалектов XML также довольно распространено, хотя читаемость часто является проблемой — особенно для нетехнических читателей.

Вы всегда должны принимать во внимание целевую аудиторию вашего DSL. Являются ли они разработчиками, менеджерами, бизнес-клиентами или конечными пользователями? Вы должны адаптировать технический уровень языка, доступные инструменты, синтаксическую справку (например, intellisense), раннюю проверку, визуализацию и представление для целевой аудитории. Скрывая технические детали, DSL могут расширить возможности пользователей, предоставляя им возможность адаптировать системы к их потребностям без помощи разработчиков. Это также может ускорить разработку из-за потенциального распределения работы после создания исходной языковой структуры. Язык может развиваться постепенно. Существуют также различные пути миграции для существующих выражений и грамматик.

24. Не бойся сломать вещи Майк Льюис

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

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

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

Переопределите внутренние интерфейсы, реструктурируйте модули, измените код, вставьте скопированный код и упростите свой дизайн, уменьшив зависимости. Вы можете значительно уменьшить сложность кода, устраняя угловые случаи, которые часто возникают из-за неправильно связанных функций. Медленно переведите старую структуру в новую, тестируя по пути. Попытка выполнить большой рефакторинг в «одном большом шебанге» вызовет достаточно проблем, чтобы заставить вас подумать о том, чтобы отказаться от всего усилия на полпути.

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

25. Не будь мил с вашими данными испытаний Род Бегби

Становилось поздно. Я добавлял некоторые метки-заполнители для проверки макета страницы, над которой я работал.

Я присвоил членам The Clash имена пользователей. Названия компаний? Названия песен от Sex Pistols подойдут. Теперь мне нужны были некоторые биржевые символы — всего несколько букв из четырех букв заглавными буквами.

Я использовал эти четыре буквы слова.

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

На следующее утро менеджер проекта сделал несколько скриншотов для презентации.

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

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

  • Во время статусной встречи клиент нажимает на кнопку, которая пока не реализована. Им говорят: «Не нажимай снова, придурок».
  • Программисту, обслуживающему унаследованную систему, было приказано добавить диалоговое окно с сообщением об ошибке, и он решает использовать выходные данные существующей закулисной регистрации для ее активизации. Пользователи внезапно сталкиваются с такими сообщениями, как «Ошибка фиксации базы данных, Бэтмен!» когда что-то ломается.
  • Кто-то смешивает тестовый и живой административные интерфейсы и делает «забавный» ввод данных. Покупатели размещают в вашем интернет-магазине «личный массажер в форме Билла Гейтса» за 1 млн долларов.

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

Даже ваш исходный код не обязательно свободен от проверки. В 2004 году, когда архив с исходным кодом Windows 2000 попал в сети с общим доступом к файлам, некоторые люди весело проглядывали его за ненормативную лексику, оскорбления и другой забавный контент . (Комментарий // УЖАСНО УЖАСНО НЕТ ХОРОШЕГО ОЧЕНЬ ПЛОХОГО ХАКА , я признаю, с тех пор время от времени меня присваивает!)

Таким образом, при написании любого текста в вашем коде — будь то комментарии, журналы, диалоги или тестовые данные — всегда спрашивайте себя, как он будет выглядеть, если он станет общедоступным. Это спасет некоторые красные лица вокруг.

26. Не игнорируйте эту ошибку! Пит Гудлифф

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

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

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

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

Ошибка, какая ошибка? Это не будет серьезно. Честно. Я могу игнорировать это.

Это не выигрышная стратегия для твердого кода. На самом деле это просто лень. (Неправильная сортировка.) Независимо от того, насколько маловероятно, что вы думаете об ошибке в вашем коде, вы всегда должны проверять ее и всегда обрабатывать. Каждый раз. Вы не экономите время, если не делаете этого: вы накапливаете потенциальные проблемы на будущее.

Мы сообщаем об ошибках в нашем коде несколькими способами, в том числе:

  • Коды возврата могут использоваться в качестве результирующего значения функции для обозначения «она не работает». Коды возврата ошибок слишком легко игнорировать. Вы не увидите ничего в коде, чтобы выделить проблему. Действительно, стало стандартной практикой игнорировать возвращаемые значения некоторых стандартных функций Си. Как часто вы проверяете возвращаемое значение из printf ?
  • errno — странная аберрация C, отдельная глобальная переменная, установленная для сигнализации об ошибке. Его легко игнорировать, сложно использовать, и это приводит к всевозможным неприятным проблемам — например, что происходит, когда несколько потоков вызывают одну и ту же функцию? Некоторые платформы защищают вас от боли здесь; другие нет.
  • Исключения — это более структурированный поддерживаемый языком способ сигнализации и обработки ошибок. И вы не можете игнорировать их. Или ты можешь? Я видел много кода, как это:
1
2
3
4
try {
// ...do something...
}
catch (...) {} // ignore errors

Изящество этой ужасной конструкции в том, что она подчеркивает тот факт, что вы делаете что-то морально сомнительное.

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

Не обработка ошибок приводит к:

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

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

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

  • Обработка ошибок загромождает поток кода, затрудняя его чтение и обнаруживая «нормальный» поток выполнения.
  • Это дополнительная работа, и у меня надвигается крайний срок.
  • Я знаю, что этот вызов функции никогда не вернет ошибку (printf всегда работает, malloc всегда возвращает новую память — в случае неудачи у нас возникают большие проблемы …).
  • Это всего лишь игрушечная программа, и ее не нужно писать на уровне, достойном производства.

27. Не просто выучить язык, понять культуру Андерс Норас

В старших классах мне пришлось выучить иностранный язык. В то время я думал, что хорошо справлюсь с английским, поэтому решил поспать три года на уроках французского. Через несколько лет я отправился в Тунис на каникулы. Арабский язык является официальным языком там, и, будучи бывшей французской колонией, французский также широко используется. На английском говорят только в туристических районах. Из-за моего лингвистического невежества я оказался ограниченным у бассейна чтением « Поминки по Финнегану» , силы Джеймса Джойса в форме и языке. Игривая смесь Джойса из более чем сорока языков была удивительным, хотя и утомительным опытом. Понимание того, как переплетенные иностранные слова и фразы дали автору новые способы самовыражения, — это то, что я сохранил в своей карьере программиста.

В своей оригинальной книге «Прагматичный программист» Энди Хант и Дейв Томас побуждают нас каждый год изучать новый язык программирования. Я пытался жить по их совету, и на протяжении многих лет у меня был опыт программирования на многих языках. Мой самый важный урок из моих приключений на полиглоте заключается в том, что для изучения языка нужно больше, чем просто изучение синтаксиса: вам необходимо понять его культуру. Вы можете писать на Фортране на любом языке, но чтобы по-настоящему выучить язык, вы должны принять его. Не оправдывайтесь, если ваш код на C # является длинным методом Main с преимущественно статическими вспомогательными методами, но узнайте, почему классы имеют смысл. Не стесняйтесь, если вам трудно понять лямбда-выражения, используемые в функциональных языках, заставьте себя использовать их.

После того, как вы выучите веревки нового языка, вы удивитесь тому, как вы начнете использовать языки, которые вы уже знаете, по-новому. Я научился эффективно использовать делегаты в C # из программирования на Ruby, высвободив весь потенциал дженериков .NET, дал мне идеи о том, как я могу сделать дженерики Java более полезными, и LINQ позволил мне освоить Scala.

Вы также получите лучшее понимание шаблонов проектирования, переключаясь между различными языками. Программисты на C обнаруживают, что C # и Java коммодифицировали шаблон итератора. В Ruby и других динамических языках вы все еще можете использовать посетителя, но ваша реализация не будет похожа на пример из книги «Банды четырех».

Некоторые могут утверждать, что Finnegans Wake невозможно прочитать, а другие аплодируют его стилистической красоте. Чтобы сделать книгу менее устрашающей, доступны переводы на один язык. По иронии судьбы, первый из них был на французском языке. Код во многом похож. Если вы пишете код Wakese с небольшим количеством Python, немного Java и намеком на Erlang, ваши проекты будут в беспорядке. Если вы вместо этого исследуете новые языки, чтобы расширить свой кругозор и получить свежие идеи о том, как вы можете решать проблемы различными способами, вы обнаружите, что код, который вы пишете на своем верном старом языке, становится более красивым для каждого нового изученного вами языка.

Вы можете найти все 97 вещей в книге, 97 вещей, которые должен знать каждый программист, или на оригинальном сайте

Это произведение лицензировано в соответствии с указаниями Creative Commons 3.

Наилучшие пожелания

Джастин