Правила программирования. Критерии хорошего кода в программировании


15 правил написания качественного кода

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

Правило 1. Следуйте стандартам оформления кода.

У каждого языка программирования есть свой стандарт оформления кода, который говорит, как надо делать отступы, где ставить пробелы и скобки, как называть объекты, как комментировать код и т.д.

Например, в этом куске кода в соответствии со стандартом есть 12 ошибок:

For(i=0 ;i

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

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

Правило 2. Давайте наглядные имена.

Ограниченные медленными, неуклюжими телетайпами, программисты в древности использовали контракты для имён переменных и процедур, чтобы сэкономить время, стуки по клавишам, чернила и бумагу. Эта культура присутствует в некоторых сообществах ради сохранения обратной совместимости. Возьмите, например, ломающую язык функцию C wcscspn (wide character string complement span). Но такой подход неприменим в современном коде.

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

Гораздо важнее, чтобы вы долго и хорошо думали перед тем, как что-то назвать. Является ли имя точным? Имели ли вы в виду highestPrice или bestPrice? Достаточно ли специфично имя, дабы избежать его использования в других контекстах для схожих по смыслу объектов? Не лучше ли назвать метод getBestPrice заместо getBest? Подходит ли оно лучше других схожих имён? Если у вас есть метод ReadEventLog, вам не стоит называть другой NetErrorLogRead. Если вы называете функцию, описывает ли её название возвращаемое значение?

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

Правило 3. Комментируйте и документируйте.

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

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

Правило 4. Не повторяйтесь.

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

  • Создание справочников API из комментариев, используя Javadoc и Doxygen.
  • Автоматическая генерация Unit-тестов на основе аннотаций или соглашений об именовании.
  • Генерация PDF и HTML из одного размеченного источника.
  • Получение структуры классов из базы данных (или наоборот).

Правило 5. Проверяйте на ошибки и реагируйте на них.

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

Правило 6. Разделяйте код на короткие, обособленные части.

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

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

Правило 7. Используйте API фреймворков и сторонние библиотеки.

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

Правило 8. Не переусердствуйте с проектированием.

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

Правило 9. Будьте последовательны.

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

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

Правило 10. Избегайте проблем с безопасностью.

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

Правило 11. Используйте эффективные структуры данных и алгоритмы.

Простой код часто легче сопровождать, чем такой же, но изменённый ради эффективности. К счастью, вы можете совмещать сопровождаемость и эффективность, используя структуры данных и алгоритмы, которые даёт ваш фреймворк. Используйте map, set, vector и алгоритмы, которые работают с ними. Благодаря этому ваш код станет чище, быстрее, более масштабируемым и более экономным с памятью. Например, если вы сохраните тысячу значений в отсортированном множестве, то операция пересечения найдёт общие элементы с другим множеством за такое же число операций, а не за миллион сравнений.

Правило 12. Используйте Unit-тесты.

Сложность современного ПО делает его установку дороже, а тестирование труднее. Продуктивным подходом будет сопровождение каждого куска кода тестами, которые проверяют корректность его работы. Этот подход упрощает отладку, т.к. он позволяет обнаружить ошибки раньше. Unit-тестирование необходимо, когда вы программируете на языках с динамической типизацией, как Python и JavaScript, потому что они отлавливают любые ошибки только на этапе исполнения, в то время как языки со статической типизацией наподобие Java, C# и C++ могут поймать часть из них во время компиляции. Unit-тестирование также позволяет рефакторить код уверенно. Вы можете использовать XUnit для упрощения написания тестов и автоматизации их запуска.

Правило 13. Сохраняйте код портируемым.

Если у вас нет особой причины, не используйте функциональность, доступную только на определённой платформе. Не полагайтесь на то, что определённые типы данных (как integer, указатели и временные метки) будут иметь конкретную длину (например, 32 бита), потому что этот параметр отличается на разных платформах. Храните сообщения программы отдельно от кода и на зашивайте параметры, соответствующие определённой культуре (например, разделители дробной и целой части или формат даты). Соглашения нужны для того, чтобы код мог запускаться в разных странах, так что сделайте локализацию настолько безболезненной, насколько это возможно.

Правило 14. Делайте свой код собираемым.

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

Правило 15. Размещайте всё в системе контроля версий.

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

Заключение.

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

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

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

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

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

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

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

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

· Имена переменных должны отражать их смысл. Правильно выбранные имена могут сделать программу в некоторой степени самодокументированной. Неудачные имена, наоборот, служат источником проблем. Сокращения ухудшают читаемость, и часто можно забыть, как именно было сокращено то или иное слово. Общая тенденция состоит в том, что чем больше область видимости переменной, тем более длинное у нее имя. Перед таким именем можно поставить префикс типа (одну или несколько букв, по которым можно определить тип переменной). Для счетчиков коротких циклов, напротив, лучше обойтись однобуквенными именами типа i или k.



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

· Для записи каждого фрагмента алгоритма необходимо использовать наиболее подходящие средства языка. Например, ветвление на несколько направлений по значению целой переменной более красиво записывается с помощью оператора case, а не нескольких if. Для просмотра массива лучше пользоваться циклом for. Оператор goto применяют весьма редко, например. для принудительного выхода из нескольких вложенных циклов, а в большинстве других ситуаций лучше использовать другие средства языка, такие как процедуры break или exit.

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

· Не следует размещать в одной строке много операторов. Как и в русском языке, после знаков препинания должны использоваться пробелы:

· Вложенные блоки должны иметь отступ в 3-4 символа, причем блоки одного уровня вложенности должны быть выровнены по вертикали. Форматируйте текст по столбцам везде, где это возможно.

· Помечайте конец длинного составного оператора.

· Для организации циклов пользуйтесь наиболее подходящим оператором. Цикл repeat применяется только в тех случаях, когда тело непременно потребуется выполнить хотя бы один раз, например при проверке ввода. Цикл for используется, если число повторений известно заранее и параметр имеет порядковый тип, цикл while - во всех остальных случаях. При записи итерационных циклов (в которых для проверки условия выхода используются соотношения переменных, формируемых в теле цикла) необходимо предусматривать аварийный выход по достижении заранее заданного максимального количества итераций. Чтобы цикл легче читался, надо стремиться объединять инициализацию, проверку условия выхода и приращение в одном месте.

Несколько советов по записи операторов ветвления:

· Более короткую ветвь if лучше поместить сверху, иначе вся управляющая структура может не поместиться на экране, что затруднит отладку.

· Бессмысленно использовать проверку на равенство true или false.

· Следует избегать лишних проверок условий.

· Если первая ветвь оператора if содержит передачу управления, использовать else нет необходимости:

if i > 0 then exit; { здесь i <= 0 }

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

  1. Перед началом каких-либо операций проверьте существование всех нужных файлов, папок и переменных. Например, если файл не будет найден, то вы его сможете создать и избавиться от ошибок.
  2. Проверяйте все входные данные, которые передаются по форме. Например, если в переменной должна прийти дата - проверьте являются ли пришедшие данные датой. Даже если в форме предлагается выбор этих самых дат. Помните, форму всегда можно сохранить локально и поправить ее на свое усмотрение.
  3. Проверяйте входные данные, чтоб они были только в пределах диапазона, указанного вами. Например, если вы поставили ограничение на 1000 символов в сообщении, а вам написали 2000.
  4. Длина слов и другие, так как в простую форму можно вести очень много символов, из которых вам нужно будет всего лишь 3-4 десятка с начала, то на форму лучше всего тоже поставить ограничение.
  5. Длина слов и другое. Если ввести слов 20 без пробела, то на странице это будет выглядеть некрасиво, а вам это не надо, поэтому либо запрещайте ввод таких длинных слов, либо разделяйте длинные слова самостоятельно, либо укорачивайте слова и другое
  6. Вы знаете, что в поле имени (скрипты: гостевые книги, форумы…) пользователь может ввести что угодно, в том числе и ваше имя. Но так как в интернете не все честные, то некоторые, подписавшиеся вашим именем могут наговорить много всего нехорошего. Чтобы подобного не произошло, создайте список с запрещенными именами и проверяйте не совпадает ли имя пользователя с именем из этого списка.
  7. Никогда не показывайте в форме пароля его текущее значение. Помните о том, что в этом случае пароль может попасть остаться в компьютере в так называемом каталоге временных файлов Интернета. А если это общественный компьютер? Тогда следующий кто сядет за него может легко узнать пароль. Кроме того форму с паролями обязательно отправляйте по методу POST.
  8. В вашем скрипте обязательно должно быть предусмотрено модерирование. Согласитесь, гораздо проще и удобнее зайти на сайт, зайти в на страницу модерирования и нажать на пару кнопок и заполнить пару форм, чем заходить по FTP на сайт, открывать нужную страницу и ковыряться в HTML коде.
  9. Кавычки. Заменяйте в получаемых данных все кавычки на ESCAPE - последовательность. Например, кавычку ["] на [\"]. Данные в форму можно ввести так, что при отображении может много чего натворить с вашей страницей. Например, можно вставить скрипт на Java, изменить оформление. Кроме того если это у вас форум или гостевая, можно заменять два пробела на пробел, для того чтоб количество пробелов отображалось верное.
  10. Храните пароли в закодированном виде. Ведь если какой-нибудь пользователь и сумеет скопировать себе этот файл с паролями, то он пароль не сможет расшифровать. Если пользователь забыл пароль - меняйте его на абракадабру и отправляйте на Email. При этом обязательно выдавайте вначале ссылку для подтверждения, чтобы никто не узнал пароль.
  11. Всегда заменяйте метки и разделители, которые вы используете для сохранения информации или отображения, на что-то подобное. Иначе имеется какой-то шанс, что его пользователь введет в форму ваш разделитель и на странице появится целый список ошибок.
  12. Никогда не забываете ставить error_reporting (0) в начало страницы, благодаря этому параметру все ошибки, если они будут, не будут отображаться на странице и злоумышленник не сможет узнать слабое место в вашем скрипте.
  13. При подгрузке какого-нибудь файла сначала удостоверьтесь в его существовании, а если он и вправду существует, то подгружайте его с помощью функции require, а не include, потому что в 1 случае если будет ошибка то файл совсем не будет подгружаться, а во 2 он подгрузится с ошибками.
  14. Проверяйте откуда пользователь пришел. Потому что пользователь может сохранить форму ввода у себя на компьютере и подправить ее, но если он попытается отправить через нее данные, то ничего не получится, так как он его запрос придет не с той страницы, с которой нужно.

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

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

«Отвергнуть хорошего кандидата гораздо лучше, чем принять плохого… Если у вас возникнут хотя бы малейшие сомнения - Не нанимайте»

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

«Самых лучших?» Но это же я! Я «самый лучший». Разумеется, я должен нанимать людей, таких же одаренных, таких умных и симпатичных, как я сам. Да и зачем засорять мою прекрасную команду всяким сбродом?

Кто они, самые лучшие программисты?

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

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

Начальник

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

Наверное, в крупной компании с таким подходом можно прожить. Я сильно подозреваю, что Лохматый Начальник в комиксах про Дилберта был срисован с натуры.

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

Кадры программистов

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

Ищите людей, склонных к самоанализу

«Самые лучшие» работники никогда не перестают учиться.

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

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

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

Как найти такого человека?

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

На собеседованиях кандидату часто предлагается описать свою основную слабость. Хотя этот вопрос до ужаса традиционен, он мне нравится.

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

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

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

Нанимайте разработчиков, а не программистов

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

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

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

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

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

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

  1. Способен ли этот кандидат сделать для группы то, что не сможет никто другой?
  2. Находится ли он в процессе постоянного обучения?
  3. Знает ли этот кандидат о своих слабостях и может ли спокойно обсуждать их?
  4. Насколько этот кандидат универсален и способен сделать «все, что потребуется», чтобы обеспечить коммерческий успех продукта?
  5. Принадлежит ли кандидат к числу «десятикратных» программистов?
  6. Обладает ли он степенью бакалавра, полученной в одном из уважаемых университетов?
  7. Если кандидат обладает докторской степенью, имеются ли другие признаки, свидетельствующие о его способностях к разработке коммерческих продуктов?
  8. Имеется ли у кандидата опыт работы в группах, занимавшихся разработкой коммерческих продуктов?
  9. Может ли кандидат представить примеры хорошего кода?
  10. Любит ли кандидат программирование настолько, чтобы писать код в свободное время?

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

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

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

Первое правило программиста

Разделяй и властвуй.
(© предположительно Гай Юлий Цезарь)

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

Второе правило программиста

Лучше день потерять, зато потом за пять минут долететь.
(© Орёл из м/ф «Крылья, ноги, хвосты»)

Признак хорошего программиста — автоматизация собственной деятельности.
(© ibigdan)

Никогда нет денег и времени, чтоб сделать всё как надо. Но на то, чтоб потом переделывать, и время и деньги находятся.
(© Закон Хеопса)

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

Третье правило программиста

Read The Fucking Manual
(© отчаявшийся сисадмин)

Знание некоторых принципов легко компенсирует незнание некоторых фактов.
(© Гельвеций)

Воображение важнее знания. Знание ограничено. Воображение охватывает весь мир.
(© А.Эйнштейн)

Смысл: вы должны уметь взлетать высоко и нырять глубоко. Уметь увидеть задачу в целом и уметь разобрать её до мельчайших деталей. Без системного мышления и аналитического склада ума в программировании делать нечего.

Четвёртое правило программиста

Зри в корень.
(© Козьма Прутков)

Не так много сущностей, как взглядов на них. Сущность — основа решения, взгляд на неё — доработка под конкретную задачу.
(© ibigdan)

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

Пятое правило программиста

Правильно назвать — значит правильно понять.
(© неизвестный автор)

Ответь на вопрос «что это?» — получишь термин. Ответь на вопрос «зачем это?» — получишь смысл. Возможно на вопрос «как лучше это сделать?» отвечать уже не придётся.
(© ibigdan)

Суть программирования в том, что бы разобрать предметную область на мелкие куски (анализ) и воссоздать её в компьютере в виде работающей модели (синтез).
(© ibigdan)

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

Шестое правило программиста

Не плоди сущностей сверх необходимого.
(© В.Оккам)

Пусть это будет просто: просто, как только можно, но не проще.
(© А.Эйнштейн)

Совершенство достигнуто не тогда, когда нечего добавить, а когда нечего удалить.
(© неизвестный автор)

Дублирование и избыточность — признак неправильного понимания предметной области.
(© ibigdan)

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

Седьмое правило программиста

Сложные проблемы всегда имеют простые, лёгкие для понимания, неправильные решения.
(© айтишный фольклор)

Если маленький простой предмет увеличить в 100 раз, то он станет большим и сложным.
(© ibigdan)

Когда мы пытаемся вытащить что-нибудь одно, оказывается, что оно связано со всем остальным.
(© Закон Мура)

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

Восьмое правило программиста

Программный продукт, моделирующий некую предметную область, физически не может быть проще этой предметной области.
(© ibigdan)

Следствие: универсальный программный продукт на несколько порядков сложнее специализированного, поскольку охватывает группу взаимосвязанных областей.
(© ibigdan)

Следствие: программный продукт который может всё — бесконечно сложен, а значит невозможен в принципе.
(© ibigdan)

Смысл: увы, никто не выделит вам ресурсы на поиск ответа на «главный вопрос жизни, вселенной и ваще». Ищите компромиссы между желаемым и возможным.

Девятое правило программиста

При автоматизации организационного управления на основе использования ЭВМ следует помнить, что главным залогом ее успеха является коренное изменение традиционной технологии организационного управления.
(© В.М.Глушков)

Автоматизация не самоцель, а инструмент оптимизации деятельности предприятия. Если автоматизация не оптимизирует, то в ней нет никакой необходимости.
(© ibigdan)

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