Табы против Пробелов. Дубль 100500 -2


Холивар про «Табы против Пробелов» стар как мир, тем не менее, окончательной точки в этом вопросе, как мне казалось, так никто и не поставил.

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

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

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

Пробелы:

  • У всех одинаково видны, т.е. форматирование у всех одинаковое вне зависимости от настроек IDE и прочего

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

var i    uint64 = 10
var name uint64 = 20


Табы:

  • Каждый может настроить отступы под себя не мешая другим в проекте. При этом код будет одинаковый у всех
  • Объем файлов меньше

Обе стороны только одинаково понимают что мешать оба стиля в одном проекте НЕЛЬЗЯ. Хоть тут сходимся.

Если вдруг кто не знает — в Go создатели языка впилили целый пакет удобных утилит для разработки «прямо из коробки». Тут вам и компилятор, и тестировщик, и генератор документации, и многое-многое другое. Но самое интересное — это утилита gofmt, которая обеспечивает форматирование кода. И благодаря этой части пакета Go, форматирование кода у всех одинаковое, и холивары тут неуместны. Собственно в том и была идея создателей — убить холивары на корню. Но что еще интереснее — это выбор символа для выравнивания. В Go это табуляция.

Поначалу меня это очень смутило, ведь я давно был приверженцем пробелов и не ожидал что люди создавшие С, Unix и Go могли принять такое решение. Но как я уже сказал — кредит доверия к ним большой, и именно это и помогло мне перешагнуть confirmation bias, которому я как и многие подвержен в холиварных вопросах. Проблема состоит в том, что когда уже принял какую-то сторону, особенно в холиваре, то аргументы второй стороны ты слушаешь да не слышишь. Ну и голову не включаешь.

Так вот, когда включаешь голову то решение оказывается столь простым и очевидным что даже трудно понять как оно раньше в голову не пришло. А вся проблема в том самом правиле «мешать — нельзя». Так то оно так, только когда такое говорят то имеют ввиду indentation, а не alignment. В английском языке для этого два разных слова, но у нас чаще всего и то и то величают «выравниванием» (хотя indention это «отступ», но и «выравниванием» его часто называют).

Вот что делает Go. Для indention — используются табы и только табы. Пример:

func main() {
	var i = 1
}

А вот для alignment — пробелы:

var i    uint64 = 10
var name uint64 = 20

Сколько я ни думал, я так и не смог придумать ни одного существенного минуса в таком подходе. А вот плюсы сохраняются от обеих сторон:

  • Блочное выравнивание все еще сохраняется у всех вне зависимости от настроек IDE
  • Отступы каждый себе сам делает как ему удобно, не мешая другим
  • Исходники меньшего размера

Лично для меня это раз и навсегда закрывает этот один из самых старых холиваров IT-мира.

Однако может я чего-то не замечаю?

UPD: Я таки и правда не замечал (точнее забыл) пару моментов, за которые я всегда предпочитал пробелы. В комментах мне на них благополучно указали:
1. В таком подходе нельзя сделать красивое выравнивание переноса длинных строк
Например в SQL запросе:
SELECT CASE WHEN val < 0 THEN 'Negative'
            WHEN val > 0 THEN 'Positive'
            ELSE              'NULL or zero'
       END AS field_sign, ...

Или же в переносе аргументов вызова функции в длинной строке:
            if (object.drawRect(rectangle.x,
                                rectangle.y,
                                rectangle.width,
                                rectangle.height)) {
            }


2. Отображение кода в местах где мы не контролируем размер tabstop-а (Github, git diff, email, diff, slack, habr, etc.)
В таких случаях размер табстопа будет зависеть от настроек конкретной среды, и часто будет 8 символов, ломая всю красоту отображения

P.S. Каюсь, я был наивен решив что Go положили конец холивару крайне простым и крайне очевидным (да и часто используемым) решением. На то они и холивары…




К сожалению, не доступен сервер mySQL