Главная » Хабрахабр » [Перевод] 25 ошибок начинающего программиста

[Перевод] 25 ошибок начинающего программиста

Научитесь выявлять их. Выработайте привычки избегать их.

Цель этой статьи не загнобить новичков за типичные ошибки, а научить выявлять их и избегать. Порядок перечисления – случайный.

От переводчика

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

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

1) Программирование без планирования
2) Чрезмерное планирование
3) Недооценивание важности качества кода
4) Хвататься за первое решение
5) Не отступать
6) Не гуглить
7) Не использовать инкапсуляцию
8) Планирование неизвестного
9) Использование неподходящих структур данных
10) Ухудшать код
11) Комментирование очевидных вещей
12) Не писать тесты
13) Думать, если что-то работает, то это правильно сделано
14) Не подвергать сомнению существующий код
15) Одержимость лучшими практиками
16) Одержимость производительностью
17) Не ориентироваться на конечного пользователя
18) Не подбирать правильные инструменты
19) Непонимание, что проблемы с кодом вызывают проблемы с данными
20) Изобретение колеса
21) Неправильное отношение к инспекции кода (code review)
22) Не использование систем контроля версий
23) Злоупотребление общим состоянием (shared state)
24) Неправильное отношение к ошибкам
25) Не отдыхать

1) Программирование без планирования

Качественный контент не создаётся “на коленке”, а требует основательной работы. Программный код – не исключение.

Хороший код должен проходить через следующие стадии:

Исследование. Замысел. Написание. Планирование. Изменение. Проверка.

Каждому из этих пунктов надо уделить достаточно усилий.

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

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

Если очень зол — то до 100”. “Если ты зол, сосчитай до 10, прежде чем говорить. (Томас Джефферсон)

Для нашего случая это можно перефразировать так:

Если для этого кода нет тестов — то до 100”. “Когда проверяешь код, сосчитай до 10 прежде чем переписать 1 строчку.

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

Программирование – это не просто написание строк кода, а творчество, основанное на логике, которое надо развивать в себе.

2) Чрезмерное планирование

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

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

Разработка подразумевает обратную связь и вы постоянно будете удалять и добавлять функционал, что никак нельзя учесть в «водопадном планировании». Линейное планирование всей программы “от А до Я” (водопадным методом) – не годится для большинства программных продуктов. И каждый новый надо включать в план лишь после гибкой адаптации к реальности (Agile). Планировать следует несколько следующих элементов.

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

3) Недооценивание важности качества кода

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

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

(Джон Вудс) “Пишите свой код так, будто его будет сопровождать агрессивный психопат, знающий, где вы живете”.

Важны даже “мелочи”. Если вы бессистемно используете заглавные буквы и отступы, то у вас нужно отобрать лицензию программиста.

tHIS is WAY MORE important
than you think

Не используйте длинные строки. Строку длиннее 80 символов очень трудно читать. Используйте специальные инструменты для приведения кода в порядок (ESLint, Prettier для js).

Разделяйте код на мелкие части, понятные и тестируемые. Следите за количеством строк в функциях и файлах. Функция больше 10 строк – слишком длинная.

Не не не делайте так. Не используйте двойное отрицание. Это очень не не плохо.

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

(Фил Карлтон) “В компьютерных науках есть только две по настоящему сложные вещи: инвалидация кэша и именование переменных”.

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

const daysInYear = 365;

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

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

(Бил Гейтс) “Измерять программирование строками кода, это то же самое, что измерять авиастроительство тоннажем произведенных самолетов”.

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

4) Хвататься за первое решение

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

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

(Тони Хоар) “Есть два пути написания программы: 1) сделать её настолько простой, что в ней, очевидно, не будет недостатков; 2) сделать её настолько сложной, что в ней никакие недостатки не будут очевидными”.

5) Не отступать

Другая частая ошибка новичков – не отступать. Даже когда они поняли, что выбранное решение не самое лучшее. Подход “не сдаваться” хорош во многих сферах, но не в программировании. Программистам полезно признавать ошибки раньше и чаще. Как только вы засомневались в решении – отбросьте его и переосмыслите проблему. Не важно, сколько вы уже вложили в этот путь. Системы контроля версий типа Git позволяют создавать ветки и экспериментировать с разными решениями, активно пользуйтесь этим.

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

6) Не гуглить

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

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

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

Не будьте креативным в понятиях Брета Виктора, который сказал:

“Думать, что ты знаешь, что делаешь – самая опасная мысль креативного человека”.

7) Не использовать инкапсуляцию

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

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

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

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

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

Этот загадочный термин означает, что внутри класса должно быть максимально связей, а между классами – минимально зависимостей. Стремитесь к тому, чтобы ваш код имел высокое зацепление и низкую связанность (High Cohesion and Low Coupling).

8) Планирование неизвестного

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

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

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

(Эдвард Эбби) “Рост ради роста — это идеология раковой клетки”.

9) Использование неподходящих структур данных

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

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

Вот несколько примеров. Неуместно использованная структура данных это кричащее предупреждение: “код новичка!”.

Массив или объект?

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

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

Стек или рекурсия?

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

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

10) Ухудшать код

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

Вот несколько распространенных ошибок, приводящих к беспорядку в коде:

Дублирование

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

Не использование файла конфигурации

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

Лишние условные операторы и временные переменные

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

function isOdd(number) else { return false; }
}

Его можно переписать без единого if:

function isOdd(number) { return (number % 2 === 1);
};

11) Комментирование очевидных вещей

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

Например, такой код:

// This function sums only odd numbers in an array
const sum = (val) => { return val.reduce((a, b) => { if (b % 2 === 1) { // If the current number is even a+=b; // Add current number to accumulator } return a; // The accumulator }, 0);
};

Можно заменить таким:

const sumOddValues = (array) => { return array.reduce((accumulator, currentNumber) => { if (isOdd(currentNumber)) { return accumulator + currentNumber; } return accumulator; }, 0);
};

Но иногда прояснить код можно только комментарием. В таком случае сосредоточьтесь на вопросе: “ЗАЧЕМ нужен этот код”, а не “ЧТО делает этот код”. Вот пример кода, где комментарии только засоряют код:

// create a variable and initialize it to 0
let sum = 0;
// Loop over array
array.forEach( // For each number in the array (number) => { // Add the current number to the sum variable sum += number; }
);

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

12) Не писать тесты

Если вы считаете себя экспертом в программировании, который не нуждается в написании тестов для своего кода, то вы – новичок.

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

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

Разработка через тестирование (test-driven development, TDD) создана не для прикола и хайпа. Если можете, создавайте проверки даже прежде самого кода. Она благотворно влияет на то, как вы продумываете, проектируете и реализуете программные элементы.

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

13) Думать, если что-то работает, то это правильно сделано

Взгляните на эту функцию, которая суммирует нечетные числа. Всё ли там правильно?

const sumOddValues = (array) => { return array.reduce((accumulator, currentNumber) => { if (currentNumber % 2 === 1) { return accumulator + currentNumber; } return accumulator; });
}; console.assert( sumOddValues([1, 2, 3, 4, 5]) === 9
);

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

Проблема 1

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

TypeError: Cannot read property 'reduce' of undefined.

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

TypeError: Cannot execute function for empty list.

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

Проблема 2

Нет валидации. Что если в функцию передадут вместо массива строку, число или объект? Вот что произойдет:

sumOddValues(42);
TypeError: array.reduce is not a function

Подвох в этой ситуации в том, что array.reduce — это как раз функция. Но так как вы назвали аргумент функции array (массив), то что бы вы не передали ей (в данном примере это 42), будет названо массивом внутри функции. На самом деле ошибка говорит о том, что 42.reduce — это не функция. Не лучше ли сделать вывод ошибки в виде:

ОшибкаТипа: 42 - это не массив, чувак.

Проблемы 1 и 2 описывают стандартные исключения, которые легко предусмотреть. Но бывают и менее очевидные исключения, с которыми надо быть внимательнее. Например, что произойдёт, если в массиве будут отрицательные числа?

sumOddValues([1, 2, 3, 4, 5, -13]) // => still 9

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

Это задуманный функционал” — удобная отмазка тех, кто не пишет тестов. “Это не баг.

Проблема 3

Не все валидные случаи правильно работают. Забудьте разные каверзные исключения. Эта функция неправильно работает и с вполне обыденным набором переменных.

sumOddValues([2, 1, 3, 4, 5]) // => 11

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

14) Не подвергать сомнению существующий код

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

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

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

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

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

15) Одержимость лучшими практиками

Термин “лучшие практики” вредный, он ограничивает вас в исследовании, «ведь уже есть лучшая практика».

Бывают хорошие практики на сегодняшний день и для этого языка программирования. “Лучших практик” не бывает.

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

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

16) Одержимость производительностью

Дональд Кнут, 1974 “Преждевременная оптимизация – это корень всех зол в программировании (или почти всех)”.

Хотя программирование существенно изменилось со времен Дональда Кнута, его совет актуален и в наши дни.

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

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

В погоне за вымышленной производительностью вы можете наделать реальные баги в самых неожиданных местах.

17) Не ориентироваться на конечного пользователя

Когда вы добавляете новый функционал в приложение, вы думаете в первую очередь о себе или конечном пользователе? Допустим, надо добавить новый ввод. Проще его прикрепить к уже существующей форме? Или нужно добавить ссылку. Проще всего прикрепить её к уже существующему меню ссылок?

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

18) Не подбирать правильные инструменты

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

Ориентироваться на популярность инструмента, а не пригодность для конкретной задачи – признак новичка.

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

Это неправильно. Есть кодеры, которые чувствуют себя комфортно с известным для них набором инструментов и не хотят изучать новые.

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

19) Непонимание, что проблемы с кодом вызывают проблемы с данными

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

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

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

Можно использовать несколько уровней валидации: на фронтенде, бекенде, при передаче и в базе данных (БД). Как защитить себя от такого? Как минимум, используйте встроенные ограничения в БД.

Хорошо знайте все типы ограничений в БД и используйте их все при создании новых столбцов и таблиц.

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

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

CHECK проверяет произвольное выражение, например, для процентов нужно проверять вхождение в интервал от 0 до 100.

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

FOREIGN KEY говорит о том, что величины этого столбца содержатся в другой таблице.

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

20) Изобретение колеса

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

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

Проводите исследование. Иногда бывает сложно выбрать нужное колесо из-за многообразия. Большинство “программных колёс” бесплатны и с открытым кодом. Пробуйте перед покупкой. По возможности используйте заготовки с открытым исходным кодом (open source), их легко отлаживать, улучшать, заменять и поддерживать.

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

21) Неправильное отношение к инспекции кода (code review)

Один из признаков новичков, это восприятие инспекций кода как критицизма. Они не любят их, не ценят и даже боятся.

Смотрите на каждую инспекцию кода как на ценную возможность обучения. Это в корне неправильное отношение надо как можно быстрее изменить. Учитесь посредством них. Любите и цените их. И благодарите делающих замечания.

Надо принять тот факт, что программист – это вечный ученик, а инспекция кода – это одна из форм обучения.

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

22) Не использование систем контроля версий (Git)

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

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

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

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

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

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

Систему контроля можно использовать в разных целях, даже до того, как изменения кода превратились в официальные коммиты:

  • отслеживание изменений (staging changes)
  • выборочный патч (patching selectively)
  • сброс (resetting)
  • прятание (stashing)
  • перезапись истории (amending)
  • применение (applying)
  • просмотр изменений (diffing)
  • отмена коммитов (reversing)

Изучите все эти возможности, поймите, используйте и цените их. Чем меньше возможностей Git вы знаете, тем больше вы новичок.

23) Злоупотребление общим состоянием (shared state)

И снова это не про сравнение парадигмы функционального программирования с остальными.

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

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

24) Неправильное отношение к ошибкам

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

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

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

25) Не отдыхать

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Давайте уберём кватернионы из всех 3D-движков

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

Конференция Velocity London от O’Reilly: обзор и слайды

Её организует издательство O'Reilly, и она проходит трижды в год: один раз в Калифорнии, один раз в Нью-Йорке и один раз в Европе (причём город меняется каждый год). Velocity — это конференция, которая посвящена распределённым системам. Главный офис Badoo находится ...