Пользователь
0,0
рейтинг
15 августа 2013 в 21:34

Разработка → Оформление кода, оптимизация процесса проверки качества кода перевод

JavaScript, the winning style



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

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

В отличие от Питона у которого есть единый свод правил «Style Guide for Python Code», у языка JavaScript такого нет. Однако на выбор есть целых 6 популярных гайдов:



Помимо гайдов, не стоит так же забывать об автоматических анализаторах кода, таких, например, как JSLint и JSHint. И в них уже заложены свои настройки. Вопрос в том, какой же все-таки максимально правильный способ писать код на JavaScript, который был бы актуален и максимально соответствовал бы большинству рекомендаций? Давайте попробуем объединить большинство рекомендаций в этой статье и подумаем как можно оптимизировать процесс проверки качества кода.

Оформление


Отступ

  • 2 пробела, не больше и без табуляции: Google, npm, Node.js, Idiomatic
  • Табуляция: jQuery
  • 4 пробела: Crockford


Пробел между аргументами и выражением

  • Без пробела, как на примере: Google, npm, Node.js

    project.MyClass = function(arg1, arg2) {
    

  • С пробелом, как на примере: Idiomatic, jQuery

    for ( i = 0; i < length; i++ ) {
    

  • Без особого мнения: Crockford


Многие гайды так же напоминают, чтобы не было пробелов в конце строк (trailing spaces)

Длина строки

  • Максимум 80 знаков: Google, npm, Node.js, Crockford

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

  • Без особого мнения: jQuery, Idiomatic


Точка с запятой

  • Всегда использовать точку с запятой: Google, Node.js, Crockford
  • Не использовать в некоторых ситуациях: npm
  • Без особого мнения: jQuery, Idiomatic


Комментарии:

  • JSDoc: Google, Idiomatic
  • В Idiomatic Style Guide так же разрешены более простые комментарии, но JSDoc предпочтительнее
  • Без особого мнения: npm, Node.js, jQuery, Crockford


Кавычки

  • Предпочтительнее одинарные кавычки. Лучше 'value', чем "value": Google, Node.js
  • Двойные кавычки ": jQuery
  • Без особого мнения: npm, Idiomatic, Crockford


Декларирование переменных

  • Одна переменная на одной строке: Node.js

    var foo = '';
    var bar = '';
    

  • Несколько переменных, разделяемые запятыми в конце строки, как на примере: Idiomatic, jQuery

    var foo = "",
       bar = "",
       quux;
    

  • Запятая в начале строки: npm

    var foo = ""
      , bar = ""
      , quux;
    

  • Без особого мнения: Google, Crockford


Скобки

  • Ставьте открывающую скобки на той же строке: Google, npm, Node, Idiomatic, jQuery, Crockford

    function thisIsBlock() {
    

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

  • В npm гайде указано, что скобки нужно использовать только в случае, когда тело функции переносится на следующую строку.

    if (foo) bar()
    while (foo) {
      bar()
    }
    


Глобальные переменные

  • Не используйте глобальные переменные: Google, Crockford

    Google:
    Global name conflicts are difficult to debug, and can cause intractable problems when two projects try to integrate. In order to make it possible to share common JavaScript code, we’ve adopted conventions to prevent collisions.

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


  • Crockford считает, что глобальные переменные не нужно использовать вовсе.
  • Без особого мнения: Idiomatic, jQuery, npm, Node


Имена



Переменные

  • Первое слово с маленькой буквы, все последующие с большой: Google, npm, Node, Idiomatic

    var foo = "";
    var fooName = "";
    


Константы


  • Все слово большими буквами: Google, npm, Node

    var CONS = 'VALUE';
    var CONSTANT_NAME = 'VALUE';
    

  • Без особого мнения: jQuery, Idiomatic, Crockford


Функции

  • Первое слово с маленькой буквы, все последующие с большой (camelCaps/camelCase): Google, npm, Node, Idiomatic

    Предпочтительнее длинное имя, которое бы описывало действие функции

    function veryLongOperationName
    function short()..
    


    Используйте слова is, set, get:

    function isReady()
    function setName()
    function getName()
    

  • Без особого мнения: jQuery, Crockford


Массивы

  • Используйте множественную форму слова: Idiomatic

     var documents = [];
    

  • Без особого мнения:Google, jQuery, npm, Node, Crockford


Объекты и классы

  • Используйте Pascal case (каждое слово с большой буквы): Google, npm, Node

    var ThisIsObject = new Date();
    

  • Без особого мнения: jQuery, Idiomatic, Crockford


Другое

Используйте all-lower-hyphen-css-case для многосоставных названий файлов и настроек: npm

Используйте JSHint и .jshintrc файл


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

{
  "camelcase" : true,
  "indent": 2,
  "undef": true,
  "quotmark": "single",
  "maxlen": 80,
  "trailing": true,
  "curly": true
}


Во все файлы, которые обрабатываются браузером добавляем:

/* jshint browser:true, jquery:true */


В файлы Node.js добавляем:

/*jshint node:true */


Во все типы JS файлов, так же лучше добавить:

'use strict';


Это повлияет и на JSHint и на обработчика JavaScript в целом, который станет менее терпимым к ошибкам, но будет работать быстрее. Почитать больше о 'use strict' (внешняя ссылка)

Автоматическая проверка кода JSHint перед git commit


Если вы хотите быть уверены в том что все ваши JS файлы прошли проверку и следуют общему стилю, который вы определили в .jshintrc. То добавьте эти строки в ваш .git/hooks/pre-commit файл. Теперь перед тем как закомитить изменения, скрипт будет проверять только измененные файлы на нарушения стилистики кода. И если таковые имеются, то операция будет прервана.

#!/bin/bash
# Pre-commit Git hook to run JSHint on JavaScript files.
#
# If you absolutely must commit without testing,
# use: git commit --no-verify

filenames=($(git diff --cached --name-only HEAD))

which jshint &> /dev/null
if [ $? -ne 0 ];
then
  echo "error: jshint not found"
  echo "install with: sudo npm install -g jshint"
  exit 1
fi

for i in "${filenames[@]}"
do
	if [[ $i =~ \.js$ ]];
	then
		echo jshint $i
		jshint $i
		if [ $? -ne 0 ];
		then
			exit 1
		fi
	fi
done


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

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

Оригинальная статья: (http://seravo.fi/2013/javascript-the-winning-style)
Перевод: Otto Kekäläinen
Егор @505abc
карма
13,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (61)

  • 0
    Большое спасибо. Google style в очередной раз оказался милее других. Ох уж эта Империя 'Добра'.
  • +2
    > Точка с запятой

    Минимизатор может дать нерабочий код, это лучший аргумент за, чем все гайдлайны.
    • 0
      Баг рипорт мэйнтейнерам оптимизатора. У ECMAscript абсолютно четкая грамматика.
      • +1
        Ловцу бага от этого будет не легче :)
        • +2
          Людям, которые пишут оптимизаторы, очень полезны подобные фидбэки. Они могут просто не знать о подобных проблемах.
          Вносите свою лепту в инструменты, которыми пользуетесь.

          Пример из моей жизни: Я в 98 году написал класс, который куда только не пастили. Года через 3 пришел баг репорт, о том, что класс не верно себя ведёт с аутлуком. Всех изменений — добавить \r. В сети на форумах нашел пару десятков веток, как обойти этот баг.

          MiKXMan, Вы уверены, что вместо того, чтобы автор добавил строчку в BNF, нужно сидеть тихо и клепать воркараунды? Вы, уверены, что авторы продуктов, которыми Вы пользуетесь не заслуживают чести получить репорт, что бы улучшить своё детище? Вы уверены, в продукте, который не получает или не исправляет репортов?
          Да, конечно написать толковый репорт — час времени. Или каждый должен ловить свои баги?
      • 0
        dean.edwards.name/packer/
        Предлагаете зашивать всю грамматику ECMAscript в простой скрипт ради восстановления пары точек с запятой, об отсутствии которых и так рапортует IDE?
        • 0
          Конечно, ведь иных вариантов нет.
          Или работающий до минимизации корректный код не будет работать.
          • –1
            Вот и для asm.js необходим более строгий синтаксис.
            Считаете, авторы совсем не правы?
            • 0
              А при чем asm.js?
              Вы, наверное, не к тому комментарию свой оставили.
              • –1
                Некоторым инструментам нужен строгий синтаксис иначе они не сработают.
                Один инструмент экономит трафик, а другой — процессорное время.
    • +2
      Не может. Или это катастрофически сломанный минимизатор, не поддерживающий JS, зачем тогда его использовать.
      Давайте еще по IE6 определять, какой JS хороший, а какой плохой.
  • +1
    Хороший перевод хорошей статьи. Но коль тема у нас оптимизация процесса проверки качества кода. То хочу добавить, что JSDOC аннотации + google closure compiler позволяют многие типы ошибок, начиная с синтаксиса и проверкой типов, и заканчивая необъявленные переменными или недоступным кодом.
  • 0
    Помимо jslint и jshint очень советую использовать github.com/mdevils/node-jscs.
  • +5
    Даешь холивар «таб vs пробелы»! И больная же тема.
    • 0
      Да разве только «таб vs пробелы»?!
      Тут холиваров не на один месяц статей:
      — Пробел между аргументами и выражением
      — Кавычки
      — Открывающая скобка
    • +8
      Я, конечно, в холиваре «tab vs пробелы» не участвую, давно для себя всё решил оптимальным образом.
      Но почему 2 пробела, а не 4 – искренне не понимаю.
      • +1
        Потому, что в 2 раза меньше места занимает по горизонтали при большой вложенности.
        • +2
          Ну и что? Сейчас экраны пошли за горизонтальное место переживать особо не стоит. Тем более, учитывая рекомендацию ограничения в 80 символов.
          Зато визуально намного легче воспринимается.
        • +1
          1 пробел ещё в два раза меньше места занимает.
          • +4
            Да-да, а 0 пробелов…
      • 0
        Если вложенность большая (например 3 цикла for), то меньше пробелов рисовать. Если что я за табы.
        • +1
          Если что – я тоже. Но все IDE умеют при должной настройке по клавише Tab нарисовать нужное количество пробелов.
          • +1
            Ну, видимо, экономят место по-ширине (как уже написано выше). Мне, если что, тоже 4 пробела удобней чем 2: воспринимается легче.
      • 0
        Но почему 2 пробела, а не 4

        Чтобы куча вложенных callback-ов не вылезала за границы широкоформатного монитора 80 символов?
    • +2
      Для меня двух пробелов мало, а четырёх — много.

      Использую поэтому три пробела.
      • +11
        Извините за оффтоп, но! Еретик!
      • +8
        Да у вас, как можно заметить, во всём свой путь…
      • +4
        Все правильно, надо делать как удобно, а не как «принято».

        (Сам раньше использовал отступ в 7 символов.)
  • +4
    Хорошо бы такие требования свести в таблицу (для аргументации в мелких рабочих группах, почему так лучше или так), а также дополнить все правила аргументациями, почему лучше так, а не иначе. И наконец, перечислить кодоформматоры — что они умеют и для каких языков (будет болльшая таблица — фичи по горизонтали, языки по вертикали, форматоры в ячейках).

    * Например, когда лучше пробелы, а когда — табы, об этом много писали в статьях ранее.
    * Почему лучше одиночные кавычки в JS, а двойные — в HTML — потому что так меньше конфликтов при записи одного в другом, а двойные в HTML традиционны.
    * Почему лучше запятые перед объявлением — потому что сразу и на одном месте видно, что означает очередная строка, не глядя в её конец.
    * Всегда точка с запятой — потому что бывают ошибки при сцеплении строк с переносом, когда конец одной — без точки с запятой, а начало следующей — скобка.
    • 0
      Идея для небольшого портала, а-ля overapi.com/
  • +5
    Вы пишете об использовании слов «is», «set», «get» в именах функций, что библиотека jQuery «без особого мнения».

    На самом же деле библиотека jQuery построена таким образом, что употребление этих слов в именах функций исключается. Один и тот же метод объекта может совершать и get (например, «$('div.hh').css('color')»), и set (например, «$('div.hh').css('color', '#7FA0B0')»).

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

      1) На самом деле не «Вы пишете», а «Otto Kekäläinen пишет». Я видел, что передо мною перевод, так что это моё выражение — просто оговорка.

      2) На самом деле «вдвое больше вспоминать» не только за счёт роста длины имени метода в два раза, но также и за счёт увеличения числа самих методов вдвое же. Может быть, вернее было бы мне сообщить, что «вчетверо больше вспоминать» приходится, но уверенности в этом у меня нет.
    • 0
      jquery — это фактически DSL. Грамотный, удобный, но DSL…
      Поэтому cчитаю их методология не может являться примером для coding-style обычного js.
    • 0
      Кстати тот самый подход, getCSS и setCSS используется в mootools.
  • 0
    Как насчет пробела перед списком аргументов в анонимных функциях?

    Например,
    function sum(a, b) {}
    

    но
    var sum = function (a, b) {};
    
    • 0
      Без пробела

      var sum = function(a, b) {
      
      };
      
      • 0
        В jQuery — по-разному.
        Крокфорд рекомендует ставить.

        А вот еще вопрос на засыпку: стоит ли объявлять переменные в начале функции? Что если переменная используется только в цикле?

        Лично я не вижу ничего страшного в таком двойном объявлении:
        function foo() {
           ...
          for (var i=0; i<a.length; i++) {
            console.log(a[i]);
          }
          for (var i=0; i<b.length; i++) {
            console.log(b[i]);
          }
        }
        
  • 0
    Используйте как в примере: Google, npm, Node

    var thisIsObject = new Date;

    Про объекты вообще ничего не понял. А как еще можно это использовать?
    И поправьте ошибку в заголовке этой части в слове Объекты…
    • 0
      В оригинале там, кстати, нормально написано. Поправьте перевод…
      • 0
        Спасибо. Исправил, оригинал статьи был изменен после перевода.
  • 0
    Только недавно перестал волноваться по поводу пробеляции. Сначала увидел систему работы с этой проблемой в Sublime Text, а потом и в WebStorm. Я тогда скопировал код откуда-то – там была пробеляция – а в мой код вставилось уже с табуляцией.
    Вообще, считаю, что пробеляция – это неверно: для табуляции есть символ табуляции. Работая в любом современном редакторе, никто не жмёт клавишу пробела дважды для создания табуляции, программист жмёт Tab. Так зачем усложнять всем жизнь?
    • 0
      Согласен. Тем более, благодаря возможностям IDE, разработчик может настроить размер табуляции по своему вкусу.
    • +3
      Любой современный редактор позволяет забиндить на клавишу TAB сколь угодное кол-во пробелов.
      • 0
        Да, но зачем?
        • +1
          Причины почему нужно использовать пробелы, а не табы можно найти даже в самих гайдлайнах/кодстайлах:

          RSR-2:
          N.b.: Using only spaces, and not mixing spaces with tabs, helps to avoid problems with diffs, patches, history, and annotations. The use of spaces also makes it easy to insert fine-grained sub-indentation for inter-line alignment.

          PEAR:
          This helps to avoid problems with diffs, patches, SVN history and annotations.

          Список гайдлайнов в поддержку пробелов: sprng.me/ife6p
          • 0
            Не вижу собственно причину.
            Пока что я вижу закостенелость.
            “fine sub-identation” – это как форматирование отступов в начале строки в текстовом процессоре – том же Word'е. Так делают секретарши, не осилившие стили текста.
            (Смешивать пробеляцию с табуляцией, конечно же, не нужно – перед использованием кода я слежу за тем, чтобы все пробелы в началах строк были заменены на табы.)
            • +1
              Я, например, очень много кода просматриваю в браузере. И смотреть на подобное мне совершенно не хочется.
              • 0
                Какое отношение этот говнокод имеет к нашей беседе?
                • +1
                  Он отформатирован исключительно табами и наверняка выглядит не так плохо в настроенном текстовом редакторе автора. К слову, почти весь код на гитхабе, отформатированный табами, в той или иной степени разъезжается.
                  Ну и не совсем понятно, почемы вы назвали это говнокодом. Потому что он плохо отображается в браузере? Не шедевр, конечно, но не так уж всё и плохо.
                  • –4
                    Ты слепой, что ли? Потому что углубить табуляцию на шесть уровней с нуля – это говно, а не код.
                    • +1
                      Ну т.е. вы приняли решение основываясь на форматировании.
                      Упустил момент, когда мы перешли на «ты».
          • 0
            Причин, почему нужно использовать таб вместо пробелов – тоже достаточно.
            Основная причина – отсутствие стандарта на размер отступа.
            Если вы используете пробелы – вы фактически навязываете разработчиу, который потом будет смотреть ваш код, свои привычные отступы.
            В случае же использования табов его <название любимой IDE> выровняет код по его настройкам.
            Ясное дело, что это касается только отступов в начале строки. Для выравнивания внутри кода надо пользоваться только пробелами.
    • 0
      Eclipse и Ctrl-Shift-F вообще чудеса творят
  • 0
    JSLint все решил за меня. Не со всем я, конечно, согласен ( в частности от пробелов в «function ($arg) {» меня каждый раз телепает), но любой единый стандарт в бесконечность раз лучше, чем любая «вкусовщина»
    • +1
      P.S: С чем не смог смириться в JSLint'е — запрет на ++ / — и подчеркивание в начале имен. Это уже перебор.
      • +2
        Вот поэтому-то позвольте ещё раз обратить Ваше внимание на важнейшее из обстоятельств в том переводе, который 505abc опубликовал: можно и нужно перейти с JSLint на JSHint, потому что у JSHint есть множество настроек, позволяющих настроить его именно на проверку какого надо стиля кодирования.

        В частности, запрет на «++» и «--» по умолчанию отключён в JSHint. (Можно включить, но я бы не рекомендовал.)
        • 0
          Понимаете, лично для меня это множество настроек — это огромнейший минус. Либо у языка какой-то стандарт кодирования есть (All hail pep8), либо его нет и стилем написания каждого отдельного файла каждый автор будет пытаться выразить свой огромный внутренний мир и чувство прекрасного.

          Dura jslint sed jslint

          P.S: в jslint эти две опции тоже отключаются, но я уже почти достиг нирваны понимания того, что даже их отключать не нужно.
          • +1
            Это статья как-раз таки о том, что надо выроботать общий стиль что-бы не слишком-то рушить огромные, но хрупкие миры каждого отдельного программиста в команде. Более того вам никто не мешает настроить JSHint под себя, и перестать героические преодолевать трудности создаваемые JSLint (если таковые имеются).

            Лично я предпочитаю гибкие инструменты, которые можно настроить под себя. Это требует времени, но стоит того. Не хочу затрагивать тему open-source и проприетарного софта, но направление мысли, я думаю, вы поняли.
    • –1
      Согласен. Нет никаких “мне нравится”, есть правильно и неправильно.

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