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

Хорошие навыки программирования делают работу с командой проще простого

Жизнь программиста прекрасна, когда код, с которым они работают, прекрасен. Через свой код вы можете повлиять на жизнь своих коллег-программистов:

  • Они будут радоваться / паниковать, когда узнают, что им нужно работать с кодом, который вы написали.
  • Они потратят 10 минут / 1 час на понимание написанного вами кода.
  • Они сообщат 0 ошибок / 2 ошибки при редактировании написанного вами кода.

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

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

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

Сделайте ваш код читабельным

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

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

// Avoid this
label1.text = dog.name
label2.text = dog.breed
label3.text = dog.int_temp
label4.text = dog.breed.int_fact

Как ваши товарищи по команде узнают, правильно ли назначены значения, если метки не дают никаких подсказок относительно информации, которую они должны отображать? и как ваши товарищи по команде узнают, что именно означают int_temp и int_fact?

// Do this
name_label.text = dog.name
breed_label.text = dog.breed
internal_temperature_label.text = dog.internal_temperature
interesting_fact_label.text = dog.breed.interesting_fact

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

Если я увижу только это имя в исходном коде, узнаю ли я, для чего оно предназначено, не углубляясь в код?

Реальная история: я видел код JavaScript, в котором ссылки на элементы управления пользовательского интерфейса назывались x, y и z, поэтому Мне пришлось тщательно просмотреть код, чтобы определить, какие элементы управления x, y и z имели в виду.

2. Следуйте конвенциям.

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

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

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

3. Делайте функции краткими и точными.

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

Мы оба знаем, что в настоящее время некоторые экраны ОГРОМНЫ. Таким образом, вы можете настроить эту рекомендацию и сделать так, чтобы функции соответствовали половине экрана, 1/3 экрана или любой части экрана, которая вам подходит.

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

Обновление: как указал в этом комментарии пользователь Reddit lykwydchykyn, при написании функции опасно слепо придерживаться определенного количества строк. У новичков может возникнуть соблазн написать ужасно плотные, длинные строки кода, чтобы сохранить функции ниже лимита количества строк, или функции бригады ведра, где одна процедура просто произвольно разбивается на функции, которые вызывают друг друга (т. Е. step1() попадает в строка 19, а затем вызывает step2(), который попадает в строку 19 и вызывает step3(). Никакой отдельный шаг не имеет смысла изолированно.) '. Итак, новичкам следует иметь в виду, что важнее сохранять значимость своих функций, чем придерживаться заданного количества строк. Кроме того, даже если языки программирования позволяют размещать два или более операторов в одной строке, лучше записывать каждый оператор в отдельной строке. И, наконец, в IDE отображается правое поле, указывающее рекомендуемую длину строки. Вы можете использовать это правое поле, чтобы знать, не слишком ли разрастается ваша линия.

4. Явное обновление переменных-членов

Другие руководства объясняют это более широко, говоря :

Функции не должны иметь побочных эффектов.

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

Эта часть сложна, потому что мы обычно обновляем закрытые члены класса внутри его методов, когда класс представляет объект бизнес-области. Например, car.move обновит переменную положения автомобиля, и это нормально, потому что Car представляет объект бизнес-домена. Я говорю не о таких занятиях.

Подумайте о классах, используемых для Android Activity или iOS UIViewController. В этих классах у нас есть множество переменных-членов, которые содержат всевозможную информацию. Мы можем инициализировать некоторые из этих переменных внутри функций, которые делают другие вещи. Это плохо.

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

5. Разумно используйте комментарии

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

Ваши комментарии должны быть грамотно размещены, чтобы сказать, ПОЧЕМУ что-то было закодировано определенным образом. Джефф Этвуд чудесно объясняет это в своей статье Код говорит вам, как, а комментарии говорят вам, почему.

Если вы поймете, что думаете:

Я реализовал это таким образом из-за того важного технического решения.

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

Наконец, вот что на самом деле думают ваши товарищи по команде, когда видят закомментированный код:

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

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

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

Сделайте свой код надежным

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

1. Избегайте дублирования

Знаменитая DRY (Не повторяйся).

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

// Written by Tommy two weeks ago
setHourlyAlarm() {
    /**
     * Very cool code for setting an alarm    <- DUPLICATED
     */
    /**
     * Very cool code to do it hourly
     */
}
// Written by you just now because you didn't see Tommy's code
setDailyAlarm() {
    /**
     * Very cool code for setting an alarm    <- DUPLICATED
     */
    /**
     * Very cool code to do it daily
     */
}

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

Сделайте себе одолжение и быстро просмотрите существующий код ПЕРЕД началом работы. Вы можете увидеть, есть ли что-то, что можно использовать повторно, чтобы сделать вашу работу более эффективной.

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

2. Избегайте жестко запрограммированных строк и магических чисел.

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

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

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

// Avoid this
switch(status) {
    case 1:
        do_this();
        break;
    case 2:
        do_that();
        break;
    default:
        do_something_else();
}

Как узнать, что система должна делать в статусе 1 или статусе 2, если вы не знаете, что означают эти числа? Сохраняйте свой код автоматически документированным, помещая числа в константу или перечисление.

// Do this
switch(status) {
    case STATUS_ENABLED:
        do_this();
        break;
    case STATUS_DISABLED:
        do_that();
        break;
    default:
        do_something_else();
}

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

Реальная история: я видел код, в котором простой номер присваивается переменной под названием «статус», а рядом с номером - комментарий, указывающий, что это число означает.

3. Проверьте значения из ненадежных источников.

Или, как сказал мой друг Габриэль Агирре:

Не доверяйте серверу.

У вас есть сервер, и он обещал вам вернуть объекты JSON со всеми необходимыми значениями: именем и породой собаки. Вы доверяете серверу и используете эти значения непосредственно в своем коде:

// Avoid this
// This code throws a null exception 
// if the JSON doesn't have the 'name' or 'breed' properties
dogName = dogDataJSON.get("name").getAsString();
dogBreed = dogDataJSON.get("breed").getAsString();

Если сервер не выполняет свои обещания, ваше приложение вылетает безвозвратно. Но это еще не все, это не просто сервер, которому нельзя доверять. Вы не можете доверять данным, поступающим из ЛЮБОГО ненадежного ресурса. Что-то могло пойти не так с генерацией ожидаемой информации, и вы могли обнаружить нежелательное нулевое значение.

// Do this
// Do a null check before working with data obtained from the server
dogName = dogDataJSON.get("name") != null? 
            dogDataJSON.get("name").getAsString() : "";
dogBreed = dogDataJSON.get("breed") != null? 
            dogDataJSON.get("breed").getAsString() : "";

Реальная история: у меня дважды возникала эта ошибка с объектами SOAP и объектами JSON. Я усвоил урок.

4. Всегда ставьте фигурные скобки вокруг однострочных блоков.

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

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

Облегчите жизнь тем, кто придет после вас, и добавьте фигурные скобки в однострочные if, else, while, for и любой другой блок, который позволяет использовать дополнительные фигурные скобки.

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

Пишите все, что связано с кодом, на английском языке

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

Почему лучше писать вещи, связанные с кодом, на английском?

  • Имена на английском короче, поэтому имена переменных и функций короче и легче читаются, если вы называете их на английском языке.
  • Легче задать вопрос в Stack Overflow и скопировать / вставить свой код без перевода комментариев или имен переменных / функций, чтобы люди со всего мира могли ответить на ваш вопрос.
  • Это позволяет вам легко добавить нового члена команды из другой страны в ваш проект, потому что каждый программист знает английский язык.
  • Геттеры и сеттеры: странно иметь геттеры и сеттеры, которые не начинаются с get и set. Поэтому некоторые люди смешивают слово get / set с испанским словом, обозначающим объект, который они получают / устанавливают. Это как-то странно.

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

Одна из проблем, с которыми я столкнулся в этой практике:

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

НЕ БОЙСЯ! Google Translate - ваш лучший друг. Просто переведите термины и используйте их английский эквивалент в своем приложении. Я делал это несколько раз и ни разу не пожалел об этом, но сожалею, что не использовал английский в качестве единственного языка в моей кодовой базе.

Заключительные слова

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

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

На эту тему написано много книг и статей. Мне особенно нравится Чистый код: руководство по созданию гибкого программного обеспечения.

Спасибо за чтение и наслаждайтесь жизнью программиста.