Правила хорошего программирования. Правила программирования. Самое сложное - начать

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

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

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

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

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

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

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

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

Начальник

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Компьютер всегда прав

Самая раздражающая ситуация в программировании - когда код верный, но не работает. “Да тут три строчки, блин, просто негде ошибиться! Наверное баг! Пойду потрачу три дня на изучение баг-репортов компилятора/интерпретатора/фреймворка... ”. Возникает чувство, будто компьютер над вами издевается!

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

Успокойся и все получится

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

Самое сложное - начать

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

Читай книги

Читайте книги. Я еще раз напишу: Читайте книги!
Почему-то многие программисты совершенно игнорируют книги. “Я и на работе отлично просвещаюсь ”, “У меня нет времени ”, “Я читаю статьи в интернете ”. Это все здорово, но лично я считаю, что лучший источник знаний - это все еще книги. Я стабильно покупаю по одной-две книги в месяц, плюс время от времени перечитываю что-то старое. Не буду врать, у меня на полке скопилась внушительная стопка того, что я купил, но пока не читал (как с играми в стиме) , но я дойду, обязательно дойду.

Знай свои инструменты

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

Не будь перфекционистом

Выше я писал, что самое трудное - это начать. Так вот, закончить - тоже не всегда легко. Отлаживать и рефакторить код можно бесконечно. “Что-за длинный метод? ”, “Может это в отдельный класс? ”, “Было бы удобнее если бы... ”, “А вдруг потом понадобится... ”, “А вдруг... ”. В программировании нельзя быть перфекционистом. Проблема в том, что достаточно почитать Роберта Мартина или Банду четырёх, как тут же возникает желание переписать нафиг весь свой код. Нужно понимать, что идеального кода нет. Я придерживаюсь правила: “Код должен работать без багов, быть тестируемым и читаемым ”. Все. Пока код метода отвечает этому требованию, я его не трогаю. Даже если в нем два цикла, три условных оператора и четыре параметра.

Умей отдыхать

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

Так что теперь у вас есть проблема, если вы пишете библиотеку, которая будет использоваться как кодом старой школы, написанным с wchar_t , определённым как псевдоним для unsigned short , так и кодом новой школы, написанным с wchar_t как отдельным внутренним типом. Какой тип данных вам нужно использовать для строковых параметров?

Это перевод The sad history of Unicode printf-style format specifiers in Visual C++ .

Windows реализовала Unicode раньше, чем большинство других операционных систем. В результате решения Windows для многих проблем отличаются от решений, принятых теми, кто подождал, когда пыль осядет¹. Самым ярким примером этого является использование Windows UCS-2 в качестве кодировки Unicode. Тогда это была кодировка, рекомендованная консорциумом Unicode, потому что Unicode 1.0 поддерживал только 65"536 символов². Консорциум Unicode передумал пять лет спустя, но к тому времени было уже слишком поздно для Windows, которая уже выпустила Win32s, Windows NT 3.1, Windows NT 3.5, Windows NT 3.51 и Windows 95 - все из которых использовали UCS-2³.

Но сегодня мы поговорим о строках формата в стиле printf .

Это перевод If FlushInstructionCache doesn’t do anything, why do you have to call it, revisited .

Предполагается, что вы будете вызывать функцию FlushInstructionCache , когда вы генерируете или модифицируете исполняемый код в run-time - чтобы процессор при выполнении вашего сгенерированного/модифицированного кода читал бы написанные вами инструкции, а не старые инструкции, которые могут остаться в кеше команд процессора.

Ранее мы узнали, что . Это потому, что простого вызова функции было достаточно, чтобы очистить кэш команд.

Но в Windows NT функция FlushInstructionCache выполняет реальную работу, поскольку ей необходимо уведомить все остальные процессоры о необходимости очищать их кэши.

Однако если вы посмотрите на Windows 10, то вы обнаружите, что функция FlushInstructionCache выглядит как версия для Windows 95: она ничего не делает .

В чём тут дело?

У меня тоже есть методички о программировании, даже по проектированию программ и разработке, так же в 1С, кое-что выложено здесь .

Я раньше работал доцентом в институте (впрочем до преподавания был админом, разбирался с 1С, поработал немного во франче но зарабатывал не много). После 5 лет преподавания сейчас уже 6 лет профессиональный 1Сник. Спустя шесть лет данной публикацией навеяло кое-что добавить.

Видел я разных студентов и учителей, программистов и начальников. Сам я постигал азы программирования с детства на коленке, курсов не кончал, а преподавал так - компилировал учебники и статьи из интернета, смотрел, показывал и делал видеокурсы, практическими заданиями правда все больше готовыми пользовался. По роду деятельности программистом после института и в возрасте уже нет особой возможности много учиться, так что я - программист из окопа, занимался по началу все больше оперативной деятельностью, много был на поддержке пользователей в чем не особо пригодилось чему учили и чему учил, так как на первом месте даже не качество а объем и скорость разработки, ну и соответственно умение в 100 процентов случаев достигать положительного результата. Даже если в текучке ошибся - пользователь напишет или сам позвонит и покажет, все такое в рабочем режиме без проблем устраняется. Очень полезная штука в организации труда на поддержке Битрикс, документооборот с заявками на ИТ. Вот если неправильно разработать метождику проекта или не до конца продумать, вот тут уж проблема может быть гораздо серьезнее.

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

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

В проектной деятельности больше всего помогает знание основ моделирования IDEF и чтение SAP ARIS (но рисовать схемы ARIS трудоемко). Всяко и прежде всего надо обязательно начинать проекты с продуманного ТЗ потому что без него понимание и общение с заказчиком проекта очень непросто складывается.

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

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

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

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

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

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

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

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

· Имена переменных должны отражать их смысл. Правильно выбранные имена могут сделать программу в некоторой степени самодокументированной. Неудачные имена, наоборот, служат источником проблем. Сокращения ухудшают читаемость, и часто можно забыть, как именно было сокращено то или иное слово. Общая тенденция состоит в том, что чем больше область видимости переменной, тем более длинное у нее имя. Перед таким именем можно поставить префикс типа (одну или несколько букв, по которым можно определить тип переменной). Для счетчиков коротких циклов, напротив, лучше обойтись однобуквенными именами типа 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 }

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