Решил я тут полностью перейти на стиль оформления кода согласно стандарту PSR-2. Но являясь противником отступов пробелами (я считаю что SmartTabs это самый правильный вариант), решил изучить вопрос: что написано в стандарте и почему это именно так. Погнали.

Что говорит стандарт


Заглянем в текст стандарта и посмотрим что там написано:
1. Overview
Code MUST use 4 spaces for indenting, not tabs.

В краткой справке пишут что код ДОЛЖЕН использовать 4 пробела, но не табы. Ладно допустим, читаем дальше про этот пункт более подробно.
2.4. Indenting
Code MUST use an indent of 4 spaces, and MUST NOT use tabs for indenting.

Опять повторяют краткую справку, о том, что нельзя использовать табы, а надо использовать 4 пробела. И вот далее самое интересное читаем сноску к этому пункту.
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.

Воспользуемся гугл-переводчиком:

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

С под-отступом понятно, довольно интересная фишка, но я как то никогда ею не пользовался, используется например так:



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

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

Ставим эксперимент №1


1. Создадим два файла, в одном будет код с пробелами в другом, точно такое же код, но уже с табами.

2. Сделаем копии этих файлов и внесем в них изменения.

3. Теперь посмотрим с помощью программы WinMerge

Табы



Пробелы



4. Отправим эти файлы в GIT

5. Посмотрим с помощью программы SourceTree

Табы



Пробелы



6. Посмотрим на сайте Bitbucket



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

Ставим эксперимент №2


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

2. Создадим два файла, у которого после изменений будут повторяющиеся куски кода. И также сделаем копии этих файлов и внесем в них изменения.

3. Теперь посмотрим с помощью программы WinMerge

Табы



Пробелы



4. Отправим эти файлы в GIT

5. Посмотрим с помощью программы SourceTree

Табы



Пробелы



6. Посмотрим на сайте Bitbucket



7. Внезапно, что с табами что с пробелами проблема видна невооруженным глазом и ни одна из программ не смогла правильно понять где произошли изменения. Тогда к чему в стандарте написано, что пробелы позволяют решить проблему: helps to avoid problems with diffs, patches, history, and annotations.

В качестве заключения


Так может быть стоит плюнуть на этот пункт стандарта и использовать SmartTabs, ведь преимущества использования табов в начале строки неоспоримы. Табы можно настроить как нравится, хочешь как два пробела, хочешь как 4, а хочешь как 8 или даже 3. При этом если все используется правильно, то код никогда и никуда не уедет.

UPDATE1
Прочитав комментарии я полностью изменил свое мнение по поводу пробелов, проведя данное исследование хотелось разобраться в плюсах 4 пробелов перед табами, тем более тогда мне казалось, что у табов плюсов гораздо больше. Но теперь табы уже не кажутся такими хорошими как раньше. Да, нужно делать как в стандарте, тем более, что так делает большинство, зачем плыть против течения. Но у пробелов тоже есть свои минусы. В общем когда делали стандарт выбрали наименьшее зло из двух возможных (ИМХО).

Но эти холивары похоже будут длится еще довольно долго.

UPDATE2 14.10.2015
По просьбе в комментарии, соберу в одном месте основные моменты почему пробелы лучше табов:
  1. SmartTabs это конечно здорово, но tzlom в своем комментарии написал, в каком случае даже умные табы хуже пробелов.
  2. Банально, большинство людей пишут пробелами, там уж повелось исторически (комментарий) от пользователя symbix, также вот пруф

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

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


  1. GrizliK1988
    15.09.2015 14:41
    +5

    Чем помогает стандарт?

    В команде можно (и нужно) его принять за основу и всегда проверять код на соответствие ему.

    Чем плохи свои изменения стандартов?

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


    1. DimNS
      15.09.2015 14:55
      +2

      Если дело об одной команде и нормах принятых в ней это да, но работая в такой команде привыкаешь к их правилам (особенно плохо если ты новичок был когда пришел). А потом когда уходишь из этой команды и приходишь в другую где разработка полностью соответствует PSR-2 стандарту, становится уже труднее, приходится опять переучиваться.

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

      Мне тут подсказали одно интересное решение, можно пользоваться табами для отступов, а во время коммита GIT будет проводить конвертацию табов в 4 пробела. А при каждом получении новых данных с сервера проводится обратная конвертация пробелов в табы. Тем самым в сервисе контроля версий код всегда валиден PSR-2, а локальные копии у каждого программиста могут быть какими угодно (как кому больше нравится)


      1. AotD
        15.09.2015 15:06
        +1

        Почему посчитали пробелы предпочтительнее табов — науке это неизвестно, но если отбросить вариант с «GIT и IDE сами разберутся», есть большАя доля вероятности что в проект с пробелами попадёт пулл-реквест с табами и наоборот.

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


        1. DimNS
          15.09.2015 15:13
          +1

          Пост писался как раз чтобы попытаться разобраться почему именно пробелы выбрали авторы, а не табы.

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

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

          P.S. судя по моей карме и рейтингу поста, разброд и шатание не собирается униматься )


          1. Fedot
            15.09.2015 16:08

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

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


      1. hugrid
        14.10.2015 11:03

        " А потом когда уходишь из этой команды и приходишь в другую где разработка полностью соответствует PSR-2 стандарту, становится уже труднее, приходится опять переучиваться."
        Выгоднее привыкать быстро переучиваться, на мой взгляд, чем привязываться к чему-то «правильному». Новый стандарт кодирования, хоткеи, новая IDE… Потом на стандарт кодирования и т.п. условности становится уже все равно. Какой принят в фреймворке, на таком и пишешь. Привыкаешь быстро усваивать новые условия кодирования.


  1. symbix
    15.09.2015 15:40
    +2

    Все просто — PSR-2 делался с оглядкой на существующие стили кодирования в популярных фреймворках и компонентах, одной из задач была фиксация существующего статус-кво. А в подавляющем большинстве PHP-фреймворков и библиотек использовались 4 пробела — просто так сложилось.

    Лично я не вижу разницы — работал и со смарт-табами, и с пробелами, никаких проблем в обоих случаях.


    1. DimNS
      15.09.2015 16:04

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


    1. SamDark
      15.09.2015 17:55

      Так и было. Надо было прекратить холивар. php-fig это сделали.


      1. SamDark
        15.09.2015 17:57

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

        Про diff имелась ввиду ситуация как раз с phpdoc.


  1. tzlom
    15.09.2015 15:47
    +1

    Вот вам пример когда SmartTabs садится в лужу:

    class MyClass 
    {
        /**
         * Usage example:
         * <code>
         * MyClass::doFoo(function () {
         * // oh shi~, indentation, what should I use????
         * FFUU$a = 0;
         * }
         * </code>
         */
        static public function doFoo()
    

    Плюс согласитесь, наличие строк типа «ваша IDE должна отображать таб как 4 пробела» это странно для стандарта написания кода, а цель стандарта — единообразие


    1. DimNS
      15.09.2015 16:09

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

      В этом примере согласно SmartTabs нужно делать пробелами отступы, да и вряд ли кто-то будет копировать этот код примера чтобы его использовать, ведь после копирования все равно останутся в начале строк знаки "*" от комментария.


      1. tzlom
        15.09.2015 16:21
        +2

        А в документации будет бардак? Оттуда код копируют


        1. DimNS
          15.09.2015 18:33

          Ах ну да, вы правы


  1. DimNS
    15.09.2015 16:19

    Вот что нашел, жаль данные устарели, вот бы сейчас посмотреть как изменилась ситуация
    http://sideeffect.kr/popularconvention

    P.S. хм, ссылка не ставится нормально, придется копировать, извините.


  1. eaa
    15.09.2015 16:27

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

    Rationale:

    • Developers should not need to configure the tab width of their text editors in order to be able to read source code.
    • From the Apache jakarta coding standards: In a distributed development environment, when the commit messages get sent to a mailing list, they are almost impossible to read if you use tabs.


    1. VEG
      15.09.2015 16:37

      Developers should not need to configure the tab width of their text editors in order to be able to read source code.
      Зато если используются табы для отступов, то разработчик получает возможность задать удобный для себя размер. Да и вообще, во всех редакторах по умолчанию стоит какое-то значение, так что если кому-то лень задавать свою ширину таба — можно использовать знаение по умолчанию. Так себе причина. (При условии, конечно же, что табы используются только для отступов, а для выравнивания — пробелы).
      From the Apache jakarta coding standards: In a distributed development environment, when the commit messages get sent to a mailing list, they are almost impossible to read if you use tabs.
      Требует пояснения или примера.


  1. VEG
    15.09.2015 16:37

    Мимо. Ответ здесь.


  1. hell0w0rd
    15.09.2015 17:59

    Я думаю под диффами имеется ввиду merge изменений. Представьте код с пробелами — все ок, с табами прийдется заново выстраивать форматирование.


  1. DimNS
    15.09.2015 18:41
    +3

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


  1. Frag
    15.09.2015 20:25

    Вы ещё не учли такой вариант. Есть два разработчика: один использует табы, другой использует пробелы.

    Далее рассмотрим два варианта:

    1. Каждый разработчик просто молча использует свой стиль. Таким образом, в коде будет каша из пробелов и табов.
    2. IDE будет ругаться на непоследовальное использование пробелов и табов и предлагать исправить. Будут постоянные замены табов на пробелы и наоборот — при каждом коммите.

    Это может быть проблемой. Хотя, современные VCS-системы (git, SVN и пр.) должны не обращать внимание на замену пробельных символов.

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

    — Мы на проекте используем стандарт PSR-2.
    — Круто! Пойду менять настройки своей IDE! **Радостно убежал**


  1. Dreyk
    15.09.2015 21:29
    +1

    Я вот никогда этого пункта не понимал. Табы как раз и предназначены для универсальности: кому-то нравится 2 пробела, кому-то 4. Просто ставишь таб, а у каждого он означает свое.

    Но комьюнити во многих языках проголосовало за пробелы (php, ruby) и приходится смириться


    1. Ag47
      15.09.2015 22:06
      +2

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


      1. DimNS
        16.09.2015 07:02

        Поддерживаю, но как писали выше похоже просто так исторически получилось, но и пример с комментариями phpDoc тоже правильный

        P.S. это из-за кармы я не могу ссылки в комментах ставить?

        1) ссылка на слово «выше»: http://habrahabr.ru/post/266903/#comment_8573493
        2) ссылка на слово «пример»: http://habrahabr.ru/post/266903/#comment_8573843


  1. hugrid
    14.10.2015 11:07

    «Прочитав комментарии я полностью изменил свое мнение по поводу пробелов, проведя данное исследование хотелось разобраться в плюсах 4 пробелов перед табами, тем более тогда мне казалось, что у табов плюсов гораздо больше. Но теперь табы уже не кажутся такими хорошими как раньше. Да, нужно делать как в стандарте, тем более, что так делает большинство, зачем плыть против течения. Но у пробелов тоже есть свои минусы. В общем когда делали стандарт выбрали наименьшее зло из двух возможных (ИМХО).»

    Не могли бы вы вкратце нписать в апдейте, чем собственно пробелы лучше? А то статья получается ущербной для читателя: всю статью доказываю что таб лучше, а в конце «не, вообще-то всё неправильно». Зачем тогда было тратить время читателя?

    Хотеось бы на хабре читать взвешенные и ценные материалы, а не промежуточные и неверные результаты чьих-то исследований.


    1. DimNS
      14.10.2015 14:26

      Спасибо за подсказку. Обновил статью, вынес основные тезисы.