diff options
Diffstat (limited to 'content/posts/2025-04-05-tabs-or-spaces.md')
| -rw-r--r-- | content/posts/2025-04-05-tabs-or-spaces.md | 400 |
1 files changed, 0 insertions, 400 deletions
diff --git a/content/posts/2025-04-05-tabs-or-spaces.md b/content/posts/2025-04-05-tabs-or-spaces.md deleted file mode 100644 index a44e052..0000000 --- a/content/posts/2025-04-05-tabs-or-spaces.md +++ /dev/null @@ -1,400 +0,0 @@ ---- -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 -``` - -Вроде как, покрывает основное. |
