diff options
| author | 2026-02-02 00:35:54 +0300 | |
|---|---|---|
| committer | 2026-02-02 00:35:54 +0300 | |
| commit | bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9 (patch) | |
| tree | 27fff9c802dcdd22960bb2e776e58278000d0364 /content/posts/2025-04-05-tabs-or-spaces | |
| parent | Поправил шаблон (diff) | |
| download | blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.gz blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.bz2 blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.tar.xz blog-bfdd73d7324a4f66a16f55d4fb064b0ff08d40e9.zip | |
Большая чистка блога
Diffstat (limited to 'content/posts/2025-04-05-tabs-or-spaces')
| -rw-r--r-- | content/posts/2025-04-05-tabs-or-spaces/index.md | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/content/posts/2025-04-05-tabs-or-spaces/index.md b/content/posts/2025-04-05-tabs-or-spaces/index.md new file mode 100644 index 0000000..8122e06 --- /dev/null +++ b/content/posts/2025-04-05-tabs-or-spaces/index.md @@ -0,0 +1,398 @@ +--- +categories: + - Размышления +date: "2025-04-05T16:53:27+03:00" +description: null +image: null +location: Казань +tags: + - размышления +title: Табы или пробелы? +--- + +Так получилось, что с Нового Года я ничего в блог не писал. Тому причина в +личной загруженности, и в не менее личной лени. Так же я делал некоторые +эксперименты над самим блогом, потому что моё внутреннее чувство прекрасного не +даёт мне просто остановиться и не трогать то, что работает. + +Но всё же, я чувствую внутреннюю потребность написать небольшую заметку с +размышлениями, которые недавно приходили ко мне в голову. + +А связаны они с тем, что есть определённые догмы в индустрии, которые непонятно +(ну или понятно) почему появились, и которым слепо следуют, хотя, как будто они +уже не имеют смысла. + +<!--more--> + +## Вечный спор + +Для затравки, «вечный спор» табы или пробелы использовать в коде для отсутпов. +Лично для меня здесь не то что выбор очевиден, для меня очевидно, что и самого +выбора то нет. Конечно же, только табы! Отступ пробелами просто не имеет права +на жизнь, и вот почему: + +- Во-первых, это просто какой-то костыль, использовать пробел не по назначению. + Наверное, не очень очевидно, но назначение пробела — это именно разделение + слов. Невероятно! А наначение таба — как раз таки форматирование отступа. + Давайте использовать инструменты по назначению! +- Во-вторых, и самое главное, как по мне, это гибкость табуляции. Я, как + читающий код, волен сам выбирать размер отступа. Например, если у меня узкий + экран (смартфон, например) — я выберу отступ в 2 _визуальных_ пробела. + Наоборот, если бы у меня было слабое зрение — я бы выбрал отступ в бо́льшее + число _визуальных_ пробелов. +- В-третьих, исходя из предыдущего пункта, я считаю, что использование именно + пробелов — это диктование автором исходника мне своей воли в виде своих + предпочтений (например, только 4 пробела, и никак иначе!). А какого чёрта? Это + буквально насилие! Зачем? Я считаю, это не допустимо. Пусть у каждого будет + возможность выбирать себе настройки отображения на _своей_ машине под _свои_ + вкусы, а не вкусы автора! +- В-четвёртых, самое малозначительное — это то, что таб это 1 байт, а пробелов + обычно больше чем 1 байт (от 2 до 8). Я считаю этот аргумент малозначительным, + т.к. уж что что, а места на носителях информации нынче в достатке. Но тем не + менее, это один из аргументов! + +А что по аргументам за пробелы? Да нет их. Ну окей, предположим, что есть. Во +многих кодстайлах (PEP-8, PSR итп) закреплены именно пробелы. Я не понимаю, +почему, вроде как, умные люди которые эти стандарты придумывали так сделали. +Возможно, привычка. Но является ли привычка каких-то людей аргументом? Наверное, +нет. И самое грустное, что эти стандарты уже не поменять, ибо с их +использованием _уже_ написаны мегатонны кодов. + +Единственное, меня радует, что хотя бы в стандарте форматирования моего любимого +языка Go этой откровенной чуши нет. В Go отступы приняты табами и только ими. + +Сразу скажу, я говорил только про отступы в начале строки, но не про отступы +внутри строки, например, чтобы выстраивать значения подряд идущих констант в +одну ровную колонку. Там, вроде как, пробелы вполне оправданы. Но это не точно. +Я пока не решил для себя. + +Думаю, здесь насчёт табов и пробелов можно завершить. Если есть что накинуть — +пишите письма, e-mail внизу страницы. + +## Вечный консенсус + +Про табы и пробелы была скорее затравочка. Там, как мне кажется, всё очевидно. +Но есть менее очевидная, но как мне кажется очень родственная тема. Эта тема +вызывает сильно меньше споров, т.к. вроде как в ней уже есть консенсус. Но этот +консенсус ошибочен! + +А говорю я про форматирование длины строк! А именно, т.н. hard-wraps и +soft-wraps. Если коротко, при hard-wraps в текст в точках переноса (например, на +80 или 120 колонке) вставляются символ переноса строк (`\n`), при мягком +переносе текст остается на одной строке, но выглядит так, как будто он разделен +на несколько строк. + +А начну я с небольшой предыстории, как я к этому пришёл. Как я уже писал в +начале, у меня есть постоянное шило в седалище, которое не даёт мне просто +остановиться и использовать то, что работает, как минимум, в контексте этого +блога. И из последнего куда я смотрел — протокол Gemini[1]. Разбирая его, меня +сначала немного удивила его особенность, а именно: + +=> https://geminiprotocol.net/ [1] + +> Text in Gemtext documents is written using "long lines", i.e. you (or your +> editor) shouldn't be inserting newline characters every 80 characters or so. +> Instead, leave it up to the receiving Gemini client to wrap your lines to fit +> the device's screen size and the user's preference. This way Gemtext content +> looks good and is easy to read on desktop monitors, laptop screens, tablets +> and smartphones. + +> Note that while Gemini clients will break up lines of text which are longer +> than the user's screen, they will not join up lines which are shorter than the +> user's screen, like would happen in Markdown, HTML or LaTeX. This means that, +> e.g. "dot point" lists or poems with deliberately short lines will be +> displayed correctly without the author having to do any extra work or the +> client having to be any smarter in order to recognise and handle that kind of +> content correctly. + +Сначала, я подумал, да это же нифига не удобно, что используются длинные строки, +а не склеиваются разделённые одним переносом как в Markdown! Более того, это моё +возмущение подогревалось тем, что я всё это время был сторонником как раз +hard-wraps и форматировал что код, что markdown для блога по 80 или 120 колонке. +Потому что так всегда и везде было принято. Но потом вчитавшись, я понял, что +как раз таки «склеивание» Markdown это максимально неправильное поведение! Оно +порождает такие минусы, как более сложный парсинг, который должен обрабатывать +по разному один и два переноса строк, неочевидность, когда пишешь текст в +редакторе, а отображается он совсем по другому, потенциальные ошибки, когда +абзацы внезапно склеиваются, и т.п. + +При этом, парсинг Gemtext поразительно простой. В общем случае, достаточно +парсить по строке, и не думать о предыдущем состоянии (относится текущая строка +к предыдущему параграфу или таки нет). Единственное исключение — +преформатированный текст, при парсинге которого надо помнить состояние. Но и это +очень просто, достаточно держать единственный флаг который говорит, мы сейчас в +нормальном состоянии или в состоянии преформатированного текста. И переключать +этот флаг когда очередная строка начинается с _```_. Вообще, Gemtext кажется +наиболее правильным и приятным для меня языком разметки. Наверное, я на него +перейду. Но потом, сейчас нет времени. + +К чему я тут углубился в описание формата Gemtext? А вот к чему: только после +прочтения спеки этого формата до меня сошло озарение, что использование длинных, +а не обрезанных по 80 или 120 или ещё какую колонку более правильное не только +для формата разметки, но и для обычного кода! + +И вот аргументы: + +- Во-первых, все редакторы кода поддерживают soft-wrap и каждый волен выставить + для своего личного редактора удобную ему длину строки, а не подчиняться + привычкам автора кода. +- Во-вторых, за длину в 80 символов топят в основном старпёры что-то там + говорящие про терминалы шириной в 80 символов. Только и этот аргумент не + понятен. Когда вы в последнее время видели терминал в 80 символов? Не эмулятор + терминала, а именно сам терминал? Ну даже, хорошо, пусть будет этот терминал в + 80 символов. Но он что, не умеет переносить? Подозреваю, что может. И в чём + тогда проблема? Непонятно. Короче, требование в 80 символов (ну или более + современное в 120) выглядит как высосанное из пальца, потому что под ним нет + реальной основы кроме каких-то там исторических причин на доисторическом + железе. +- В-третьих, см. пункт про насилие автора кода над читателем кода. Например, + опять таки, узкий монитор например. И на нём не soft-wrapped текст может + вызывать горизонтальную прокрутку. И это убого. +- В-четвёртых, да, это усложняет парсинг. Это слабый аргумент, я знаю. Как + пример, правильный парсер Markdown (не буду тут бомбить про количество разных + стандартов Markdown) пишется не то чтобы очень просто. В это же время, + написать парсер Gemtext который полностью покроет спецификацию — дело максимум + часа-двух для любого, кто программирует больше, хотя бы, нескольких месяцев! + +В общем, как и в случае с табо-пробелами я не вижу ни одной достойной причины +делать жесткие переносы строк по какой-то длине! + +Возможно, я что-то упустил — тоже можно по этому поводу поспорить со мной в +электропочте. Возможно, я даже поменяю мнение, но наврядли. + +## Update 06.04.25 + +Как я и просил, один хороший человек, Владислав +(https://t.me/c/1331521959/2285), написал ответ. Прокомментирую его здесь: + +> Мне есть что сказать про ширину таба и 80 символов. + +> Аргумент про разную ширину таба работает слабо: многие стили предполагают его +> фиксированную длину. Если ставить другой, то форматирование ломается. + +> Пример: ядро Linux, где ширина таба 8, и аргументы функций "плывут" при другой +> ширине. + +Я не единожды видел этот аргумент, но он как раз и кажется мне слабым. Большая +ли разница для читающего код, как именно он его видит: + +``` +/ tabsize=2 + func someFunc( + one, + two, + three, + ) +... + callOfSomeFunc = someFunc( + "one", + "two", + "three", + ) +``` + +или так + +``` +/ tabsize=4 + func someFunc( + one, + two, + three, + ) +... + callOfSomeFunc = someFunc( + "one", + "two", + "three", + ) +``` + +или даже так + +``` +/ tabsize=8 + func someFunc( + one, + two, + three, + ) +... + callOfSomeFunc = someFunc( + "one", + "two", + "three", + ) +``` + +Кажется, что для 8 пробелов на таб всё сильно уезжает, но раз человек себе так +настроил — то как будто его право и наверное были основания? + +> Про 80 символов. Дело вообще не в размере терминала или ширине перфокарты. +> Некоторые программисты разделяют редактор на две вкладки, чтобы смотреть два +> файла. + +И тогда soft-wrap как раз и вместит весь код в каждую из половинок без +горизонтальной прокрутки, о чём я и говорю. + +> Некоторые используют большой шрифт. С шириной в 120 символов мы лишаем из +> возможности удобно читать код. К тому же, я считаю этот аргумент важным, 120 +> символов - это способ замаскировать плохой код. Чувак сделал 5 уровней +> вложенности в коде? Отлично! Главное чтобы в 120 символов влезло. + +Всё так! Возможно, я не очень подробно расписал, но основная моя мысль в том, +что такое жесткое ограничение мне кажется просто надуманным и взятым с потолка. +А если я после функции хочу написать небольшой коммент и он ну никак не влезает +на пяток символов? Новую строку ради этого делать? Ну как-то бредово. А для +указанного случая гораздо лучше бы звучало ограничение в стандарте типа «не +используйте больше 3 уровней вложенности в коде». Это хотя бы имело вполне себе +обоснование, то что скорее всего такой код просто архитектурно неверен и его +стоит пересмотреть. + +> Конечно, можно сказать что есть длинные константы или имена функций, но этот +> спор становится менее однозначным. Как по мне вполне хороший консенсус - это +> 100 символов в строке + +Здесь не согласен. Здесь опять «магическая константа» с потолка. + +> В целом, эти срачи мне кажутся достаточно поверхностными. Они в своем корне +> несут вопрос "как повысить читаемость кода?", но акцентируются на мелочах. + +Согласен. Мелочи. Но почему и бы про мелочи не поговорить :) Из них по +отдельности всё и строится (избитая фраза, да). В больших стандартах обычно +говорится просто декларативно «только пробелы, отступ 4 пробела, длина строк +120» и всё. А зачем и почему — опускается, как будто всем всё и так понятно. Мне +вот не очень. Чувствую себя ребёнком спрашивающим «Почему небо синее?». Потому +что мне кажется, что под этим требованием нет объективного требования кроме «так +принято». А «так принято» я часто и принимаю как валидный аргумент, например, +когда прихожу в какой-то проект, но в сути своей аргументом не является. + +> Хотелось бы иметь какие-то объективные метрики, какая-то работа в этом +> направлении была проделана, но, как я понял, это, во-первых, недостаточно +> точные метрики, а во-вторых, недостаточно развитая история. +> https://seeinglogic.com/posts/visual-readability-patterns/ + +Интересная статья, спасибо, с удовольствием прочитал. В целом, по выводам +(https://seeinglogic.com/posts/visual-readability-patterns/#8-patterns-for-improving-code-readability) +согласен. Метрика по Хольстеду (или как это перевести?) выглядит интересно, тем +что она чётко считается (хотя когда я руками считал, что-то у меня не сошлось с +примером :) ). + +Из объективных метрик, тут вскользь ещё упоминалась цикломатическая сложность, +которая вполне себе имеет право на жизнь. + +А так же, только что пришло в голову что можно читабельность кода оценивать как +вторую (?) производную от отступов по непустым строкам. При этом, чем эта +производная ближе к нулю — тем лучше. + +То есть, грубо говоря вот такой «код»: + +``` +_____ + ________ + _____ + _______ + ___ + ___ + _____ + __ + ____ +___ +``` + +Лучше чем, такой: + +``` +_____ + ________ + _____ + _______ + ___ + ___ + _____ + __ + ____ + ___ +``` + +Это стоит ещё подумать, это буквально пришло в голову только что, пока читал +статью. + +P.S.: Из забавного + +> As others have written, computers are fast and premature optimization is a bad +> thing. + +Сначала они пишут «computers are fast» а потом происходит такое: [2] + +=> https://tonsky.me/blog/disenchantment/ru/ [2] + +## Update 06.04.25 - 2 + +Со вчерашнего дня я решил дополнить немного ещё. + +Во-первых, хочу немного снизить градус холиворности и радикальности. Ещё раз +упомяну что не вижу проблем для выравнивания пробелами текста внутри строки. То +есть например, вот так: + +``` +→ → ConstWithLongName = 0 +→ → Const1 = 1 +→ → Const2 = 2 +→ → Const3 = 3 +``` + +для меня вполне нормально кажется. Даже более того, табы _внутри_ строки кажутся +плохим решением. Я говорю только про отступы в начале строки. + +Во-вторых, насчёт длинных строк. Я расписал немного сумбурно и в одну кашу +смешал как код, так и просто текст. Не стоило так. Хоть это и разные сущности, +но я всё равно считаю жесткое ограничение необоснованным ни там ни там. Но по +разным причинам: + +- Для обычного текста ограничение в N символов выглядит таким же не обоснованым, + как, например, требование автора «Читайте мои тексты только шрифтом Arial + 12pt». Глупость? Глупость. +- Так же встречал, что люди используют это ограничение при написании электронных + писем. Это выглядит как минимум странно. Письмо пишется для кого? Для + получателя, т.е. читателя. Почему отправитель за читателя решает то, как у + него будет отображаться письмо? Я часто читаю почту со смартфона с узким + экраном, но средним шрифтом (чтобы меньше напрягать глаза). И горизонтальная + прокрутка выглядит не очень. Горизонтальная прокрутка вообще почти всегда + выглядит не очень и её стоит избегать всеми силами. +- Для кода же история другая. Я не настолько поехал чтобы требовать всё писать в + одну строку. Если у функции в сигнатуре много (больше одного - двух) + аргументов — то это отличная идея написать их в столбик, а не в длинную линию, + которая ещё неизвестно как перенесётся. Я против именно переноса только из-за + магической константы колиечества символов. + +Да и вообще я ни от кого ничего не требовал. Я предлагаю только задуматься, а +обоснованны ли «общепринятые» вещи? Может, уже прошло какое-то время и ситуация +поменялась и удобнее и эффективнее выбрать что-то другое? + +И как будто стоит абстрактному «читателю», к которому я отсылал, в этом посте, +решать этот вопрос техническими средствами, типа editorconfig + pre-commit хуки +на форматирование в принятый в команде формат? Возможно да. Иначе получится, что +борясь за личную свободу — нарушаешь чужую свободу <del>писать говнокод</del>. + +А .editorconfig я себе такой в home положил: + +```.editorconfig +[*] +indent_style = tab +tab_width = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +soft_wrap = true + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +[*.json] +indent_size = 2 +``` + +Вроде как, покрывает основное. |
