Стандарты кодирования

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

Для погружения в проблему

Применение теории разбитых окон (ru.wikipedia.org/wiki/Теория_разбитых_окон) в нью-йорском метро: ayrat-galiullin.livejournal.com/65038.html
Видео-лекция Яндекса про стандарты кодирования: events.yandex.ru/events/shri/msk-2012/talks/566.
Стандарты кодирования (HTML/CSS) от Google (перевод): habrahabr.ru/post/143452

Общие положения

Отступы

Табуляция, 4 символа.

Единообразие в именах и названиях: файлы, папки, классы, методы, функции, переменные, атрибуты

Не транслит. Названия на английском понятном языке. Из нескольких синонимов выбирать наиболее часто используемое. slovari.yandex.ru в помощь.

При выборе названия для элемента, содержащего логического значение, имя должно начинаться с is или has.

Названия файлов и папок

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

Длина строки

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

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

Для кода, для которого характерен большой уровень вложенности, например, HTML-XML-XSLT стоить использовать принудительные переносы и специальное форматирование элементов:

<xsl:stylesheet>
    <xsl:template match="input">
        <form>
            <fieldset>
                <div class="fieldset">
                    <div class="row"><div class="control"><xsl:choose>
                        <xsl:when test="@type = 'checkbox'">
                            <label for="is-published">
                                <input type="checkbox"
                                    value="1"
                                    checked="true"
                                    name="is-published"
                                    id="is-published"
                                    class="required"
                                    style="border-color: red;"
                                />

                                Да
                            </label>
                        </xsl:when>
                        <xsl:otherwise>
                            <input type="text" />
                        </xsl:otherwise>
                    </xsl:choose></div></div>
                </div>
            </fieldset>
        </form>
    </xsl:template>
</xsl:stylesheet>

Тезисы

Код должен выглядеть так, как будто его пишет один человек.

На проектах нужно использовать файл ~/Contribute.md, в котором давать ссылку на общий (этот) документ со стандартами, описывать принятые договоренности, если они отличаются от стандартных.

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

Важно документировать неявный код.

Написание примеров использования.

Уменьшение чрезмерного количества уровней вложенности.

Автоматизированная проверка кода (IDE + Pre commit hook to check style of the code)

git-scm.com/book/en/Customizing-Git-Git-Hooks
gist.github.com/davetron5000/37350
checkstyle.sourceforge.net

PHP

Подробно по ссылке framework.zend.com/manual/1.12/ru/coding-standard.html. Выжимка MyObject.php:

<?php

class MyObject
{
    /**
     * @var integer
     */
    protected $_variable;

    /**
     * @var string
     */
    protected $_result;

    /**
     * @param array[integer] $_inputParams
     * @return integer|false
     */
    protected function _doSomethingInsideObject(array $_inputParams = null)
    {
        if ($_inputParams) {

            // Делаем какую-то значимую работу

            if (isset($this->_variable)) {
                $this->_variable = 0;
            }


            // Делаем что-то еще, что нужно выделить, но выносить
            // в отдельный метод не хотим

            foreach ($_inputParams as $item) {
                $this->_variable += $item;
            }

            return $this->_variable;
        }

        return false;
    }

    public function __construct()
    {
        $result = $this->_doSomethingInsideObject(array(1, 2, 3, 4, 5));
        echo $result !== false ? 'OK' : 'Empty';
    }
}

Отступления

Блоковые комментарии /**/ используем только для документирования или отладочного комментирования большого объема кода. Для отключения кода // нужно ставить в начале строки, а для добавления комментария к коду — с отступом согласно уровню отступа кода, к которому комментарий относится.

Перед комментарием желательно добавлять два переноса строки, после него — один:

if (isset($this->_variable)) {
    $this->_variable = 0;
}


// Делаем что-то еще

foreach ($_inputParams as $item) {
    $this->_variable += $item;
}

Вместо слитной конструкции elseif используется раздельное написание else if.

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

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

function printPhone($_number)
{
    $number = '+7 (495) ' . $_number;
    echo $number;
}

MySQL

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

Название первичного ключа — название таблицы + _id.

Название таблицы, реализующей связь многие-ко-многим — основная_таблица_has_вспомогательная_таблица.

Атрибуты таблиц, реализующие логическое поведение — is_ + название.
Тип — TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 (при проектировании в MySQL Workbench тип — BOOLEAN).

Javascript

Как в PHP, но в строковых конструкциях используются двойные кавычки.

XML, XSLT, HTML

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

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

Все HTML-тэги нужно закрывать, так как часто верстка переносится в XSL-таблицы стилей.

CSS

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

Каждое свойство и каждый селектор — с новой строки.

Открывающая фигурная скобка на новую строку не переносится.

div.error,
div.success {
    border-width: 1px;
    padding: 0.5em 1em;
    color: #000;
}

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

div.error,
div.success {
    border-width: 1px;
    padding: 0.5em 1em;
    color: #000;
}

    div.error a {
        text-decoration: none;
        color: #f00;
    }

        div.error a span {
            border-bottom: #333 1px dashed;
        }