Читабельність коду. Способи, кращі практики та помилки

«Чистий код читається як добре написана проза», — писав Граді Буч, автор Object Oriented Analysis and Design with Applications. Звичайно, я його не читав, але цитата дуже подобається.

Привіт, я Олександр, COO у VT Labs. Маю близько десяти років досвіду в Software Development, працював як у великих закордонних компаніях, так і сам на себе. За цей час я мав нагоду подивитись на код з різних сторін: як розробник, як менеджер, та як замовник, тож маю певне уявлення, як ті чи інші практики та стандарти коду впливають на життя девелопера, його оточення та продукт. Тож ця стаття може бути цікава не тільки розробникам, але і людям з бізнесу.

Перш за все, пропоную домовитись про те, навіщо і кому взагалі потрібна читабельність коду. Те, що ми робимо, зазвичай називається software, і це є антиподом hardware. Це те, що можна легко змінити. Якщо розробник не може зрозуміти код, він не зможе виправити баг чи запилити нову фічу.

Є відомий факт про те, що швидкість друку не впливає на швидкість розробки, бо більшість часу девелопер читає код, а не пише. Не думаю, що когось питали на інтерв’ю про число символів у секунду.

Одне з моїх найулюбленіших питань на співбесідах, це «Який код краще, той що працює, але не зрозумілий, чи несправний, але його легко прочитати?». Багато хто відповідає, що справний краще. Але баги можна виправити, а незрозумілий код вже не змінити, його можна тільки викинути. Він вже не є software.

Так кому ж потрібен зрозумілий код? В першу чергу тому, хто його буде змінювати. Парадокс в тому, що найчастіше — це той самий девелопер, що його писав. Коли ти пишеш читабельний код, ти допомагаєш майбутньому собі.

Часто під тиском замовника або менеджера виникає ілюзія того, що можна зараз зробити швиденько, а потім відрефакторити. Але такий підхід уповільнить розробку вже поточної таски, навіть не наступної, тому що майбутнє наступає швидше, ніж хочеться — вже наступного дня, а також на code review, тестуванні, та на стадії «це дуже круто, але треба дещо інакше».

Спочатку скажи «ніт»

Час — це завжди гроші. Для бізнесу час — це кількість оплачених годин девелоперів та втрати від того, що фіча ще не у продакшені. Сукупно це можуть бути величезні кошти, тому бізнес завжди бажатиме всього, бажатиме на вчора, та обов’язково не так, як було раніше узгоджено, тому що ситуація на ринку вже змінилась. Це природньо. Якщо замовник цього не хоче, то мертвий або він, або його компанія.

«Скільки часу вам потрібно, щоб запилити ці фічі? Тільки майте на увазі, що це потрібно зробити цього тижня! Ви ж фахівець, придумайте як!», — хто не був учасником такої розмови? «Так, я фахівець і тому знаю, що це неможливо. Зараз я піду і подумаю, що я можу зробити цього тижня, а що потім і коли», — це єдина відповідь, після якої ваш код може залишитись читабельним.

«Єдиний спосіб робити швидко — робити добре», — писав Роберт Мартін. А щоб робити добре, потрібен час. Девелопмент можна порівняти з приготуванням їжі — якщо збільшити вогонь, то вона згорить замість того, щоб приготуватися швидше. Те саме відбувається з кодом, коли розробник погоджується на нереальні терміни.

Срібна куля

Чи можна мати якусь автоматичну метрику читабельності коду? Звичайно, наприклад в SonarQube є метрика cognitive complexity, тобто складність сприйняття. Її можна побачити в розділі Measures. Зрозуміло, що гарні показники не обов’язково означають зрозумілий код, але погані точно скажуть, що щось пішло не так.

How to find complexity metrics in SonarQube

Дуже важливо змінити дефолтне значення у правилі «Cognitive complexity of functions should not be too high» в розділі Quality Profiles. Стандартне «15» пропускає взагалі все, можна поставити хоча б «5».

Те саме варто зробити й з правилом «Cyclomatic complexity of functions should not be too high». Ця метрика показує, скільки юніт-тестів потрібно написати, щоб покрити ними весь код.

Знову тести :(

Яке взагалі відношення мають тести до читабельности коду? Якщо подивитись на графіки Cognitive Complexity і Cyclomatic Complexity, то вони виявляються дуже схожими, і це не просто так. Якщо функція є нагромадженням if/else/case, сайд-ефектів, додаткових аргументів та return стейтментів, то буде складно і прочитати її й написати тести.

Функції з більшою Cyclomatic Complexity(7 vs 2) складніше читати

Cognitive Complexity vs Cyclomatic Complexity in SonarQube

Дуже просте правило: якщо ти не в змозі швидко написати простий тест, то код треба рефакторити до тих пір, поки тест не буде значно простіший за код. Більшість проблем, пов’язаних з юніт-тестами, — це проблеми поганого коду.

Складності також виникають, коли розробник спочатку пише код, а потім намагається покрити його тестами. Такий код вже не проєктувався таким чином, щоб можна будо писати тести легко. Потрібно витратити час на ручне тестування, потім на те, щоб покрити тестами код, який може бути дуже складний для цього, а потім на рефакторинг. Тому що з першого разу написати тест не вийшло. Що трапиться в більшості випадків? Правильно: «Зараз важливіше закрити таску, ніж ті тести». І поганий код йде в продакшн.

Як не витрачати на це час? Дуже просто — тестувати свій код тестами, а не руками. Скільки разів на хвилину розробник може вивести console.log? А скільки тисяч юнітів можна виконати? Приємним бонусом буде і те, що автоматичний тест не помиляється, що скоротить час на фікс багів.

Достатньо відомим є експеримент, коли девелопер виконував одну й ту саму невелику задачу кілька разів поспіль з TDD і без. Рішення з TDD завжди були швидше, хоча і відчувались суб’єктивно довше.

Але як такий підхід впливає на реальні проєкти? Є багато наукових досліджень з різними висновками, але тільки одне вивчає вплив TDD на maintainability. Це, на мій погляд, висвітлює відірваність академічних праць від індустрії в реальному світі. Дослідження ж maintainability, попри зниження продуктивності, показує суттєве зниження середнього часу на change request з 80+ до 60- часів. Причиною цьому цілком може бути зниження cyclomatic complexity з 6-7к до 4.5к. Код, дизайн якого базується на тестах — простіший, і тому його легше читати та змінювати.

Зниження складності з TDD. Credit: T. Dogsa, D. Batic

Слід зазначити, що розробники в дослідженні не використовували TDD раніше, що може бути причиною нижчої продуктивности на першому етапі. Але у світі сучасної Agile-розробки, яка базується на зворотному зв’язку від юзера, більш ніж на upfront design, проєкти перетворюються на потік change request. Тож ми можемо стверджувати про вищу продуктивність в перспективі.

Фідбек девелоперів про TDD. Credit: T. Dogsa, D. Batic

Звичайно, винятково TDD мало хто витримає, проте це чудовий приклад того, що правильне використання тестів пришвидшує розробку, а не сповільнює. Навіть якщо просто почати з заміни ручного тестування юнітами, то результат приємно вразить.

FUBAR foobar

Назви — це найголовніше з того, що не виправити автоматично чи тестами. Ми не читаємо оператори та дужки, ми читаємо назви. Вони надають коду сенс, це зміст прози. Хтось читав би Толкієна, якщо замість Арагорна був би prsn_2931? Там і без того достатньо речей, які відрізняються лише одним символом.

Перш за все, назва повинна максимально точно і зрозуміло описувати сутність. Вона не має дезінформувати.

  • Назва має бути змістовна.
  • Змінні, константи та класи це завжди іменники.
  • Методи та функції — дієслова.
  • Не треба скорочувати — це унеможливлює пошук.
  • Не треба використовувати синоніми для однієї сутності. Наприклад user і customer.
  • Не треба робити «magic numbers». Числа повинні бути зрозумілими.

Чудовою ідеєю буде встановити Code Spell Checker в IDE, це не тільки позбавить від несподіванок при пошуці, але й від сорому, якщо код буде читати нейтив.

Погані приклади:

  1. const p
  2. const prise
  3. const price = () => ‘$2000’
  4. getUserData()
    getCustomerInfo()
  5. Product.productName
  6. if (width < 768) {...}

Як краще:

  1. const price
  2. const price (use Code Spell Checker)
  3. const getPriсe = () => ‘$2000’
  4. getUser()
  5. Product.name
  6. const MOBILE_BREAKPOINT = 768
    if (width < MOBILE_BREAKPOINT) {...}

Tab vs Space

Форматування дуже важливе, бо не можна читати книгу без полів, абзаців, заголовків, розділів, та у якої текст не влазить на сторінку. Ще важливіше, щоб воно було завжди однаковим. Можна користуватись табами, можна пробілами, але їх не треба змішувати.

На щастя, про більшість проблем форматування можна забути, якщо користуватись Prettier або чимось подібним.

Але є дещо, на що варто звернути увагу:

  • Довжина рядка — не повинно бути горизонтального скролу, бо так не зручно читати. Зазвичай, це навколо 120 символів.
  • Якщо немає вертикального скролу, то взагалі добре, але не завжди можливо.
  • Імпорти з бібліотек варто відокремити порожнім рядком.
  • Варто видаляти старий код — чим менше коду, тим легше читати.

No comments

Не треба писати коментарі, вони не зроблять незрозумілий код краще. Напевно, кожен читав якусь стару товсту книгу, в якій відбувається щось дивне, і виносками пояснюється, що насправді мав на увазі автор в контексті його часу та положення. Це і є коментарі, які пояснюють код. Цю книгу треба було б відрефакторити, але її девелопер вже давно вимер, як і розробники на Cobol.

Ще один підводний камінь коментарів полягає в тому, що їх забувають змінити або видалити, коли змінюють код. Як наслідок, код з часом наповнюється дезінформацією.

Якщо код не зрозуміти без коментаря, то треба рефакторити код, а не писати коментар.

Але є винятки:

  • Legal коментарі. Наприклад, ліцензія.
  • Пояснення неочевидної бізнес-вимоги. Наприклад, «треба обрізати три останні символи строки, тому що третя сторона передає неправильні дані». Такій коментар не пояснює, що відбувається, він пояснює навіщо.
  • TODO — наші рішення не завжди оптимальні, тому варто залишати собі нагадування щось виправити, коли таке трапляється.

TL;DR

Читабельний код — це тільки основа, але без неї складно обговорювати інші аспекти програмування.

  • «Єдиний спосіб робити швидко — робити добре», — Роберт Мартін.
  • Static code analysis дуже сильно покращує життя.
  • Юніт-тести допомагають писати читабельний код швидше.
  • Назва завжди повинна мати сенс.
  • Жити без Prettier не дуже добре.
  • Коментарі — це зло, але іноді виправдане.
👍НравитсяПонравилось15
В избранноеВ избранном5
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Якшо треба рефакторити код замість того, шоб писати коментар то тоді треба робити оптимальні рішення, шоб не писати TODO

Не треба писати коментарі, вони не зроблять незрозумілий код краще.

Вибачте, але ви неправі.
Коментарі лише тоді зло, коли вони повторюють те, що написано у коді. І тоді справді вам доводиться змінювати код, а потім обов’язково коментар.
Але якщо вам потрібно написати high-level опис методу або класу з кількох рядків, це нормальна практика і без цього взагалі важко зрозуміти, для чого потрібен той чи інший API. У Java це називається Java Docs.

Складності також виникають, коли розробник спочатку пише код, а потім намагається покрити його тестами. Такий код вже не проєктувався таким чином, щоб можна будо писати тести легко.

Чому??? Я написав REST API, не має значення з думкою про тестування чи без неї.
Написати потiм тести для REST API — звичайна стандартна справа, коли ви формуєте запит, відправляєте його та перевіряєте відповідь. І все.

Написати потiм тести для REST API — звичайна стандартна справа, коли ви формуєте запит, відправляєте його та перевіряєте відповідь. І все.

Если это REST для работы со статическими объектами — то да. Но я подозреваю что в основном REST используется для вызова бизнес логики. Которая, в общем, может использоваться еще в десятке мест. Так что

формуєте запит, відправляєте його та перевіряєте відповідь

это далеко не

І все.
Дуже просте правило: якщо ти не в змозі швидко написати простий тест, то код треба рефакторити до тих пір, поки тест не буде значно простіший за код. Більшість проблем, пов’язаних з юніт-тестами, — це проблеми поганого коду.

Як взагалі пов’язана складність коду та складність тесту?
Код може бути 1000 разів складним, але перевірити його можна тестом із двох рядків. І навпаки.

Якщо функція є нагромадженням if/else/case, сайд-ефектів, додаткових аргументів та return стейтментів, то буде складно і прочитати її й написати тести.

Я не розумію, а навіщо для написання тестів читати тіло функції та розуміти, як ця функція працює?
А якщо це буде тест, який буде викликати ваш REST API та перевіряти відповідь? У автора тесту взагалі може бути доступу до коду проекту.
Коли ви пишете автоматизований тест, для вас те, що ви тестуєте, має бути чорною скринькою, і ніяк і інакше.
А ви виходить, пропонуєте, писати тести не за документацією до проекту, а за тим, як фактично працює код. А це докорінно неправильно.

Я не розумію, а навіщо для написання тестів читати тіло функції та розуміти, як ця функція працює?

Для юнит-тестов не надо знать как работает тестируемая функция?

Для unit-тестів потрібно розуміти, що робить метод, а не як він це робить (як працює).
Тобто якщо, наприклад, розробника попросили написати юніт-тести для функції, яка складає два числа, чи повинен він читати код функції? Ні, лише її контракт. Тобто опис вхідних параметрів і значення, що повертається.
Тут може також бути обробка виняткових ситуацій (неправильне значення аргументів тощо.).

Це по-перше. А по-друге, як ви, наприклад, читатимете код функції, якщо ви використовуєте TDD?
У вас при TDD немає жодного коду функції, ви спочатку пишете тести і потім уже реалізацію (production code)

А по-друге, як ви, наприклад, читатимете код функції, якщо ви використовуєте TDD

Не использую и отношусь в целом скептически

Для unit-тестів потрібно розуміти, що робить метод, а не як він це робить (як працює).

Ок, как вы напишете юнит-тест для гипотетической функции

void doSomething (boolean param1, boolean param2) {
if (param1) {
callVoidMethod1();
} else if (param2) {
callVoidMethod2();
} else {
callVoidMethod3();
}
}

Я так розумію, чи це публічна функція в деякому класі?
Тому що я особисто тести на приватні та захищені методи не пишу.
Ок, так от, якщо це публічна функція, це означає, що її повинен викликати якийсь код в іншому класі (компоненті).
А щоб викликати функцію з іншого класу, необхідно розуміти, що вона робить.
Як Java розробник розуміє, що робить той чи інший клас/метод із JDK? Навряд чи він щоразу відкриває його sources. Швидше за все, він читає контракт (документацію) як Java Docs.
Більше того, якщо ви використовуєте поліформізм або інтерфейси (патерн Strategy), ви повинні додати контракт на такі інтерфейси:

interface Executor {
public void execute();
}

Інакше ніхто не зможете реалізувати цей інтерфейс, тому що не розумітиме, що реалізація має робити.
Якщо ви написали метод і не має контракту, як зрозуміти, правильно ви його написали чи ні? Дивитись sources? Але цей метод може використовувати безліч інших класів і так по ланцюжку. Щоразу розкручувати це простирадло? Мені здається незручно та непрактично.

Я так розумію, чи це публічна функція в деякому класі?

Да

Ок, так от, якщо це публічна функція, це означає, що її повинен викликати якийсь код в іншому класі (компоненті).

В общем — да. Но вызывающий компонент вполне может быть еще не реализован. Или таких компонентов может быть несколько. Но при чем тут это в принципе? Это в общем случае ответственность третьих лиц, о которых вы можете быть вообще не в курсе.

А щоб викликати функцію з іншого класу, необхідно розуміти, що вона робить.
Як Java розробник розуміє, що робить той чи інший клас/метод із JDK? Навряд чи він щоразу відкриває його sources. Швидше за все, він читає контракт (документацію) як Java Docs.

Ок, уточняю пример:

/**
* This function loads global data dictionaries into memory from several possible sources
* @param useWebService indicates that source should be web-service call
* @param useDatabase indicates that source should be database
*/
public void loadGlobalData (boolean useWebService, boolean useDatabase) {
// globalDataHolder — instance of the GlobalDataHolder class
if (useWebService) {
globalDataHolder.loadDataFromWs();
} else if (useDatabase) {
globalDataHolder.loadDataFromDb();
} else {
globalDataHolder.loadDataFromLocalFileSystem();
}
}

Как это повлияет на вопрос,

как вы напишете юнит-тест для гипотетической функции

loadGlobalData , если не знаете

як ця функція працює?
Але баги можна виправити, а незрозумілий код вже не змінити, його можна тільки викинути. Він вже не є software.

А рефакторинг на що? Його ж і вигадали для того, що робити код (і дизайн) краще і зрозуміліше.

Что это за язык в примерах? Здесь const это тип или признак неизменности как в C#?
Просто в случае C# я бы константы не называл с префиксом get.

const в js стал стандартом вместо let а тем более, фу-фу, var

Ще раз раджу The Programmers Brain, для розуміння як краще писати читабельний код. (Книжка більше про те як розуміти код чужий і свій код)

Статья ни о чём.

незрозумілий код вже не змінити, його можна тільки викинути

Обманываете общественность. Для многих языков есть формальная семантика, а для них чекеры, и можно его переписать верифицированно хорошо, только это требует включения межушного нервного ганглия а с этим у наших девелоперов есть определённые траблы, по этому «нельзя»

є ілюзія того, що можна зараз зробити швиденько, а потім відрефакторити.

Действительно это имеет смысл, если требования не до конца известны. И это применяется не только в SD но и в прочей инженерии.

Роберт Мартін.

 ну, в прочем, после этого имени можно не читать.

«Cognitive complexity of functions should not be too high»

это только капля в море

Дуже просте правило: якщо ти не в змозі швидко написати простий тест, то код треба рефакторити до тих пір, поки тест не буде значно простіший за код. Більшість проблем, пов’язаних з юніт-тестами, — це проблеми поганого коду.

Далеко не всегда, это зависит от задачи которая решается.

Потрібно витратити час на ручне тестування

Только, исключительно автотесты

Код, дизайн якого базується на тестах — простіший, і тому його легше читати та змінювати.

пруфы

якщо код буде читати нейтив.

 да какая разница

Форматування дуже важливе,
Не треба писати коментарі

Ваш к.о.

Короче, тема сичистого кода не раскрыта вовсе.Ни как эту сложность снижать, ни из чего она берётся, ни что такое есть чистый код формальным и чётким определением,и так далее. Поток воды.

Имхо, код делают чистым из любви к искусству, а не к ближнему своему.

Чужой код это всегда легаси, а свой — новье.

за што ві всє так нє любітє кабол?77

Не шмогли, вот и не любят.

Читаемость кода сильно субъективная метрика, зависящая от знаний\опыта читуемого.

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

Обьективная и вычисляемая.

критерии объективности и алгоритм вычисляемости в студию.

Отличная статья, спасибо!

Читабельний код потрібен ще і техрайтерам. Їм іноді приходиться зазирати в код. І яку вдячність вони відчувають до розробників, якщо ті залишили їм хоч якісь коментарі, що той робить.

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

Потому что многие программисты пишут код как маленькие дети собирают что-то из кубиков:
в голове пусто, общей идеи, «генерального плана» в ней нет,
а просто кубики громоздятся друг на друга, лишь бы не падали (компилятор пропустил, тесты не упали, в рантайме не вывалилось).
Причина говнокода — та же обычно: мысли не было, а было накидывание кубиков так, чтобы гравитация их не уронила.
таску ж надо закрыть, думать некогда!

в итоге парадокс — тот кто не может написать внятные, полезные комментарии, не может И написать код который не требует никаких комментариев.
А тот кто может писать такие комментарии — может написать и такой код, который их не будет требовать.

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

Как говорится «ваши бы слова — да менеджеру в уши»!

Спочатку скажи «ніт»

Менеджеров учат НИКОГДА не говорить НЕТ клиенту!

Який код краще, той що працює, але не зрозумілий, чи несправний, але його легко прочитати?

Для бизнеса ответ очевиден, для менеджера — то же. Едиственно, кому мешает плохой код — это девелоперам. Ну так это же их проблемы! «Ты ж программист» — поэтому должен быть готов разобраться в любом коде. Если не получается — посиди в овертайм, подумай. Если не хочешь — то воткни костыль по-быстрому и в следующий раз это уже будет чужая проблема.

Менеджер никогда не поймет, что воткнутый костыль сегодня = сниженная скорость разработки завтра. Что скорость работы с кодом обратнопропорциональна количеству костылей в нем. А если и поймет, то это, как верно заметили, будет не его проблема.

Поэтому, лично на мой взгляд, это полностью ответственность программиста — писать код качественно с самого старта проекта.

И поторапливание сверху — такое себе оправдание. Инженер оперирует непреложными фактами, физическими законами, если хотите. Если менеджер спрашивает «закипел ли там чайник?» и «можем ли мы закипеть при 80 градусах?», единственный верный ответ — нет. Потому что только инженер знает этот факт достоверно. Менеджер же сомневается, и если слышит нечто неуверенно-философское на тему «ну мы могли бы, но...», то слышит только часть «могли бы» =)

Если менеджер спрашивает «закипел ли там чайник?» и «можем ли мы закипеть при 80 градусах?», единственный верный ответ — нет.

"Я своими глазами видел, как какая-то неопрятная девушка подливала из ведра в ваш громадный самовар сырую воду, а чай между тем продолжали разливать."©
Если клиенту надо срочно (а это почти всегда) — то и 80 градусов можно считать кипятком.

Если честно — не смог себя заставить читать статью о читаемости кода.
Глаза ни на чем не остановились.

Не треба писати коментарі, вони не зроблять незрозумілий код краще.

я вже бачив такє.
коли лід гордо казав що коментарі не потрібні, а потім через деякий час волав — хлопці, а чому ми не коментуємо свій код???

на останьому проекті добре себе показала практика додавати коментарем номер та назву таски в джирі.
Дуже скорочує час потім шукати — а коли оцей код з’явився і до чого?

тобто, в якомусь ідеальному світі код, тех завдання, спеки, описи тасок, і т.д повинні утворювати таку собі вікісистему.
звісно, зараз немає такого інструментарія

але програмний код — то такий же документ як і всі інші в проекті. а ніяка не комп’ютерна программа.
комп’ютерна програма з’являється без участі людини: компілятор, або інтерпретатор, або ще якє середовище створює та виконує программу на основі документів. і зараз вже не тільки документів з кодом, а і документів конфігів.

і всі документи — це інформаційний всесвіт проекту.

про самодокументований код топить здається Мартін. і, насправді, я б в рота йому не дивився.
і розумів так: чим менше код потребує коментування — тим він кращий.
а не — «а давайте не писати взагалі коментарів»
бо відсутність коментарів не робить код зрозумілішим

тобто, в якомусь ідеальному світі код, тех завдання, спеки, описи тасок, і т.д повинні утворювати таку собі вікісистему.
звісно, зараз немає такого інструментарія

Есть кусочки из которых такую систему вполне можно построить (правда это требует определенных усилий) — встречал такое на одном из проектов. Когда дизайн описывался в confluence, из сonfluence создавались таски в jira, из jira создавались бранчи в git-e — и все это было между собой интегрировано, и trace-абельно. То есть из таски в jira сразу были видны линки на описание, коммиты, результаты билдов и тестов, бранчи в гите автоматом именовались на основании тасок в jira и т.п.

Есть кусочки из которых такую систему вполне можно построить (правда это требует определенных усилий)

в том и вопрос — окупятся ли эти усилия :)

На небольших проектах — скорее нет, на больших — однозначно да

на останьому проекті добре себе показала практика додавати коментарем номер та назву таски в джирі.

git blame же

Я читаю код. Какой ещё гит? Это ж — время и отвлечение. Примерно как — см сноску в конце книги. А её нельзя было на этой же странице сделать?

Комментарии призваны расширить, указать контекст кода.
Эта часть кода могла правиться многими и по многим причинам.
Но контекст этого кода не изменился. Почему же его надо выяснять исследуя комиты?

Я читаю код. Какой ещё гит?

в том же vscode есть git lens, или вы код в распечатках читаете?

Он не только в VS есть. Проблема в том что невозможно прочитать никак то, что нигде не написано.
А в коментах комментах к комитам я не сомневаюсь что кто описывает причины и детали реализации.

Потому что для понимания кода, ИМХО, чаще всего важнее его эволюция. А её описывать в коментариях совсем тоскливо. И это не говоря о том, что один и тот же коментарий может относится к нескольких местам в проекте. А раз уж всё равно надо лезть в git, то...

чаще всего важнее его эволюция.

полностью согласен.
именно знание эволюции проекта и есть — экспертиза в проекте

А её описывать в коментариях совсем тоскливо.

да, поэтому и не пишут.

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

да, и — опа, а у нас в коде номер таски и ее описание — в этих нескольких местах и есть
и глобальным поиском — IDE мгновенно его находит :)

А раз уж всё равно надо лезть в git, то...

а в гите искать — дольше.

но да, когда времени полно и не жалко его — ищите в гите
гит шикарная штука, когда ты
уже знаешь историю какого кода ты хочешь посмотреть

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

по другому скажу
код — это измерение по оси X
комиты — это измерение по оси Y
а коменты в коде — это измерение по оси Z

«трехмерный код» проекта лучше двухмерного :)
и комиты не могут заменить коменты. а коменты — комиты.

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

да, и — опа, а у нас в коде номер таски и ее описание — в этих нескольких местах и есть и глобальным поиском — IDE мгновенно его находит :)

Ну... очень часто живёт проект на одном сервере, клоны есть на github, gitlab, и тут возникает вопрос, а где искать таску? Второй нюанс в том, что часто такие изменения к таске не имеют никакого отношения. Просто делал таску, заметил, что можно улучшить, улучшил. Да, можно заводить отдельную таску, там что-то писать... Но мне куда удобнее написать это в сообщении коммита и не плодить по таске на каждый коммит. Тем более, что это банально надо куда-то переключаться из терминала, отвлекаться, и т. п.

а в гите искать — дольше

Мне быстрее искать в git, а всякая Jira и таски больше для менеджеров.

но комент указывает не на историю — а на причины появления этого кода

git checkout -b tmp && git reset --hard interesting-commit && git blame interesting.file

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

Ну... очень часто живёт проект на одном сервере, клоны есть на github, gitlab, и тут возникает вопрос,

почему правки кода вносятся то в один клон, то в другой?

а где искать таску?

а зачем ее — искать? название ж — есть. нужны подробности, все ее обсуждение? ну точно его не в коде хранить.
а почему и тут у вас — куча «джир», и поди найди в какой из них...

Просто делал таску, заметил, что можно улучшить, улучшил

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

Мне быстрее искать в git,

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

git checkout -b tmp && git reset —hard interesting-commit && git blame interesting.file

у меня нужный мне файл — уже открыт. быстро могу и историю гитовую в ide открыть.
и в ней быстро увидеть — вот фрагмент был в комите — появился и комент к нему.
вот через пару комитов — изменения совсем лишили его смысла, и комент тоже — удалили.
Ок, история становится понятной.
Вы IDE что-ли не пользуетесь? Я с «дества», с Turbo C люблю IDE

Пробелма коментариев больше в том, что их надо актулизировать.

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

Но ещё больше в том, что автор кода не экстрасенс

это да, факт.

Экстрасенс тот кто будет его читать. Как писали в теме уже — джуны бац, и враз все поняли.

Но мне не очень часто попадались проекты с подробными комментариями

а мне только такие и попадаются. ессно — не те что писаны по моднему, и под NDA.

хотя и было, попался мне проект такой себе веб студии из Днепра.
там в комментах емко было — исправить эту хню!
ну все, понятно, раз коммент такой — не исправлено, смотри внимательней, в чем хня :)

У меня не сильно взлетело, потому что пишешь новеллу неделю,

а зачем писать новеллы?
не пишите их, да и все.
можно и коротко писать.

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

согласен. когда джуны сплошные экрасенсы, и вопросов почти не задают, то незачем.

а потом понимаешь, что надо сделать по другому

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

а код — получится, когда не можешь ответить себе на вопрос — на кой и что ты решил написать?

почему правки кода вносятся то в один клон, то в другой?

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

Вы IDE что-ли не пользуетесь? Я с «дества», с Turbo C люблю IDE

Не знаю, считать ли vim IDE или нет, то разные VS Studio и пр. не знаю... бесят они меня... Навязывают стиль разработки, скажем так. Не у всех есть макросы, ...

и? в чем проблема? это ж от таски зависит, повлияло на нее изменение кода

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

гы. а код не надо актуализировать?

Вот, я поменял код. Дальше надо лазить по проекту и смотреть все коментарии, какие стали неактуальны?

Экстрасенс тот кто будет его читать. Как писали в теме уже — джуны бац, и враз все поняли.

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

зачем в комменте дублировать код? напишите основную идею, причину, почему решили сделать по другому.

Я это пишу в тексте коммита. Просто ситуация такая: коммит в котором изменялось три файла. И есть коментарий, который я хочу оставить, который относится ко всем файлам сразу. И тут начинается, а в какой файл его вставлять, и т. п. Например, простой пример, я добавил какую-то опцию в утилиту. И возникает вопрос, писать зачем это опция нужна где? В том месте, где парсится аргументы командной строки? В том месте, где она вызывается? В том месте, где она реализована?

можно и коротко писать.

А вот не получается коротко... Думаешь и то надо сказать, и то надо сказать...

коммит в котором изменялось три файла. И есть коментарий, который я хочу оставить, который относится ко всем файлам сразу.

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

И возникает вопрос, писать зачем это опция нужна где?

В Джаве, например, принято описывать аргументы в комментарии над public методом.

В Джаве, например, принято описывать аргументы в комментарии над public методом.

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

В Джаве, например, принято описывать аргументы в комментарии над public методом.

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

мне удобнее всего читать комментарии в тексте коммитов

Дихотомия «комментарий в коде либо комментарий в коммите» — ложная. Никто не запрещает писать комментарии в тексте коммита, но есть кейс, когда такой подход не годится — когда коммит охватывает несколько файлов(или несколько мест в одном файле), а нужно прокомментировать конкретное решение в конкретном месте.

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

Суть нового аргумента это и есть причина, по которой внесены изменения.

когда такой подход не годится — когда коммит охватывает несколько файлов(или несколько мест в одном файле), а нужно прокомментировать конкретное решение в конкретном месте.

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

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

Отдельный коммит, который меняет код в четырёх местах. А в тексте коммита обычно зачем понадобилось расширять. И этот коммент будет отночится ко всем затронутым строкам.

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

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

То есть завести в первом коммите код с неиспользуемой переменной?)

Комент в общем случае является частью кода, а не истории изменения кода. Его смысл — предоставлять информацию к актуальному коду, которая по каким то причинам не может быть описана на ЯП, или из описания на ЯП сложно получить информацию более высокого уровня абстракции чем код на ЯП.

Размещение комментариев в описании к коммиту поэтому для меня звучит как:
а я код не в исходниках храню, а в описаниях коммитов!

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

В большинстве случаев я и так вижу что делает код.

«и вы говорите»

все известные мне программисты пишут что на чтение кода уходит — время, а потому все что уменьшает временные затраты полезно, но вы особенный. вжик! и увидели :)

А почему в зеркалах возможны изменения в коде?
И почему улучшение системы логирования меняет функционал игры в португальские шашки?
И зачем вам лазить по коментам в других файлах если вы там ничего не меняли?
Теоретически вы конечно можете написать в тексте коммита что угодно. Но я не встречал чтобы там описывали нюансы реализации. А встречаю — рядом с кодом, где который эти нюансы и реализует.

Опции утилит командной строки, и помощь к ним — где обычно можно прочитать? Вот в том месте и писать.
А к реализации тогда будет достаточно добавить предложение, два о чем она.
Откройте исходник любой cli утилиты и посмотрите как другие делают.

А у меня наоборот, длинно не получается.

Так что тут не подскажу, как научится писать емкие а потому короткие коменты.

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

Так в коде же

коментарем номер та назву таски в джирі

и все равно в жиру лезть и от кода отвлекаться

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

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

тут мы подходим к второй проблеме — к полезному испльзованию трекера

а оно — у всех перед глазами, любой публичный баг трекер опенсорс проекта — полон ценнейшей информации. нередко ценнее стековерфлов.
и если на проекте комментов к таскам нет, ну, ждем тогда вопля — «А где у нас документация», потому что ее тоже обычно и нет, в таком случае.

«Программистам некогда писать комменты в коде, комменты к таске, доку,
Они Ваятели, код пишут!»

ну-ну...

а оно — у всех перед глазами, любой публичный баг трекер опенсорс проекта — полон ценнейшей информации. нередко ценнее стековерфлов.

Не знаю, исходники и коммиты мне куда ценнее. Баг трекеры они больше не по конкректному проекту, а вообще, типа возникла проблема, и похожая была на этом проекте, которого ты знать не знал о существовании.

конечно исходники с историей коммитов лучше чем исходники без истории комитов.

а разговор о коментах тут при чем?
у них же другая задача.

Я читаю код. Какой ещё гит? Это ж — время и отвлечение. Примерно как — см сноску в конце книги

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

швидко

а ще швидше — НЕ переходити нікуди.

на останьому проекті добре себе показала практика додавати коментарем номер та назву таски в джирі.

почитайте в статье этот случай описан

Такій коментар не пояснює, що відбувається, він пояснює навіщо.

автор не предлагает полностью отказаться от коментариев, просто если комментарий типа «здесь мы проходим по списку айтемов и находим тот у которого поле эктив=тру» то это абсолютно избыточная хрень, которую можно прочитать и без комментария

Коментарі — це зло, але іноді виправдане.

а я не считаю их злом.

просто если комментарий типа «здесь мы проходим по списку айтемов и находим тот у которого поле эктив=тру»

согласен, таких долбо-эпических примеров в учебниках полно.

на практике, думаю, такие комментарии появляются когда есть требование их писать, вот народ и «соблюдает метрики»

Запрещаю комментировать код у себя в проектах, могу пять раз завернуть PR из-за невнятного имени переменной или метода, без тестов даже не смотрю PR. Вы скажете «это замедляет разработку?» — ну разве что, пока пациенты не научатся писать лаконичный self-explanatory код.
Ну и безусловно — git blame прекрасно работает, а в купе с тестом ещё и поясняет, сведущему, почему было сделано именно так.

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

Запрещаю комментировать код у себя в проектах

запрещайте, я вам не указ

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

Вы скажете «это замедляет разработку?»

а вы скажете что не замедляет?

но если вам выделили время делать долго — то вперед, избавляйтесь от полезных коментариев.

git blame прекрасно работает,

он — делает другое.
выше уже написал.

Комментировать разрешаю разве что самые неочевидные части,

а зачем комментировать очевидные?

где без пояснения трудно разобраться

а вы пишите такой код чтобы не трудно было разобраться!
и git blame вам в помощь!
зачем же комменты писать?

И все норм, джуны приходят в проект и почти не задают вопросов

да это понятно что есть проекты где «джуны почти не задают вопросов».
пришел — глянул код — и все ему стало ясно, зачем так было сделано, как надо делать.

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

javadoc или его аналоги тоже запрещаете?

про самодокументований код топить здається Мартін. і, насправді, я б в рота йому не дивився. і розумів так: чим менше код потребує коментування — тим він кращий

Именно это, насколько я понимаю, и имеет в виду Мартин.

Как часто вы встречали названия методов вида «updateScenes()»? Когда вы смотрите на вызов этого вот в каком-то месте чужого кода и совершенно не понимаете, что имел в виду автор.

Какие такие «scenes»? Что значит «update»? Потом разбираешься в коде метода, и оказывается, что «scenes» — это автор так криво перевел слово «киносеанс». Но всё ещё не понятно что значит «update». Загрузить ИЗ базы? Положить В базу? Синхронизировать с удаленным АПИ? А ведь такая возможность тоже имеется. И если так, то в какую сторону. Или, быть может, модели сеансов нуждаются в пересмотре, может там какие-то вычисляемые поля обновляются. Или там что-то происходит с самим списком этих моделей? Пока не прочитаешь код — не поймешь.

Понятно, автор этого метода сократил, чтобы не писать километровые имена. Но Мартин как раз говорит о том, что так делать не нужно. Название метода, в идеале, должно говорить о том ЧТО он делает и давать представление о том КАК он это делает, хотя бы приблизительно. Как по мне, в этом вся суть.

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

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

Помните шутку о том, что качество кода определяется по частоте восклицаний WTF при ревью? Так вот в жизни код тем читабельнее, чем реже ревьюверу приходится открывать доки или искать по исходникам вычитывая комментарии. Это не булево значение, четко разделяющее «читабельный код» и «резко нет».

От терминологии предметной области, конечно, не уйдешь. Но речь немного о другом, о случаях когда классы называют AppInit вместо AppStartupConfigurator или методы вида updateRequests() вместо deleteTimedOutRequests(). Такие вещи находятся полностью во власти программиста и их нельзя оправдать «терминологией проекта».

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

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

перфекционизм инженеров — известное зло.
конечно, в программерской тусовке он нередко объявляется великим достоинством :)

Я бы не стал называть деятельность, которая отнимает менее 5% времени, но в дальнейшем даёт профит в 100% и выше, именно перфекционизмом.

Когда добавление простенькой фичи отнимает в несколько раз больше времени, чем она того стоит, из-за высокой связанности вермишелеподобного кода, обычно всё начинается с простого — с неочевидных имен, пропущенного рефакторинга, непродуманной архитектуры.

Потом кто-то вмешивается со своим таском, совершенно ничего не понимает в коде, и тоже решает по-быстрому тыкнуть костыль. Запутанность раз за разом множится. И в итоге можно прийти к ситуации, когда время на поиск места, куда бы ткнуть новый костыль в сумме с отладкой получившегося добра, превышает время непосредственно написания кода в несколько раз. Ну и стоила того эта экономия в самом начале?

Обо всем этом когда-то тоже говорил Роберт, и, на мой взгляд, это не перфекционизм, а профессионализм.

мне коменты помогают читать код — быстрее.
и свои, и чужие.

обычно всё начинается с простого — с неочевидных имен, пропущенного рефакторинга, непродуманной архитектуры.

небо голубое, трава зеленая.

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

совершенно ничего не понимает в коде

вот коменты и призваны добавить этого понимания.

Обо всем этом когда-то тоже говорил Роберт

расшибания лбов перед иконой мартина да, популярное занятие.

как один написал, с чем в целом согласан:
IT-шечка — индустрия очень богатая. И, как везде, где вертятся деньги, вертится ворьё и шарлатаны. Но, если в других, давно устоявшихся индустриях — например в науке, с этим научились жить, то в IT-шке шарлатаны — чуть ли не главные игроки.

Нигде, ни в какой другой индустрии, нельзя представить себе того же Мартина Фаулера или Роберта Мартина. В той же науке — им бы на второй день провели бы коллективным *уем по губам. Но в IT-шке книга «Patterns of enterprise software» — набор заклинаний, типа «используйте ООП, но я вам не расскажу как», от которых даже сам Фаулер сто лет как переобулся — стабильно в топе книг
(конец цитаты)

Роберт Мартин — педагог, а не практикующий программист. как по мне — неплохой педагог.
И его советы часто именно педагогические, как нашумевшая школьная двойка, когда ребенок написал решение задачи:
5 * 2 = 10
а надо 2 * 5 = 10

расшибания лбов перед иконой мартина да, популярное занятие.

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

Я ещё в самом начале утверждал, что не следует самодокументирование кода отождествлять с требованием полного отсутствия комментариев.

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

Но комментариями не снабдишь вызов каждой функции. Функции должны иметь нормальные, понятные не только автору в момент написания имена. Также как и переменные. И классы. Конечно, бывают исключения, когда хорошее имя никак не придумать. Но это именно исключение, т.е. встречается редко. Но бывает. И даже когда сталкиваешься с ним, стоит ещё раз подумать, а нельзя ли переписать код каким-то таким образом, чтобы подобная ситуация исключалась. Потому что это признак возможной архитектурной ошибки. И опять же. Контекст. Если такая «не ошибка» случается в одном месте из ста, переписывать придется слишком много, а сама она сокрыта где-то в редкоиспользуемой части интерфейса — то и ладно, это того не стоит. Но когда чуть ли каждая функция называется черте-как, то это совсем другое дело.

Или, например, не следует каждый блок, осуществляющий некое отдельное действие в коде функции, пытаться обернуть в собственную функцию, как это делается в примерах Мартина. Это просто пример, а не непреложное правило. Маркер, который оповещает о такой возможности. Что о ней стоит задуматься. Возможно, она имеет смысл, а, может, и нет. Потому как куча приватных функций с длинными дурацкими именами определенно не сделают код читабельнее. А ведь смысл как раз в этом.

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

Функции должны иметь нормальные, понятные не только автору в момент написания имена.

А что делать, если у вашего компонента со стороны заказчика три разные продуктовые команды и каждая пользуется немного различной терминологией описывая бизнес логику? Пойдете к СЕО заказчика и будете требовать навести порядок в бизнес-процессах?)

А что делать, если у вашего компонента со стороны заказчика три разные продуктовые команды и каждая пользуется немного различной терминологией описывая бизнес логику? Пойдете к СЕО заказчика и будете требовать навести порядок в бизнес-процессах?)

Речь совсем не о терминологии. Или вы о том неправильно переведенном слове в моем примере? Про то что «кинокартина» != «киносеанс»? Но там это далеко не самое важное.

На это я обратил внимание вообще только потому что бросилось в глаза, ведь обычно подобные ошибки — признак более комплексной проблемы. Часто именно плохое знание английского языка и не позволяет автору называть методы ёмко, как и писать вменяемую документацию. А вовсе не какой-то «особый грязный уличный стиль» программирования =)

Речь как раз о терминологии, лол. Как вы собираетесь давать нормальные, понятные имена переменным в коде реализующем бизнес-логику, если нет общей с бизнесом терминологии?

Это вообще повсеместная беда, когда на какую-то генерализацию одни начинают молиться

Это не беда.
Это норма.
Недавно встретил очень популярно изложение причин:
Почему мышление — боль? [Veritasium на русском]
youtu.be/_zM8m4pRdt4

Разница только в том — у кого какие наборы догматов, предубеждений, какого уровня абстракции(группировки, обобщения феноменов), и количестве правил работы с этими догматами.

А другие, посмотрев на первых, решают, что вся парадигма — туфта.

И обычно — чем меньше этот набор правил, и чем более примитивные догматы — тем фанатичней, ортодоксальней такое мышление.

«23летний синьор, 25летний архитектор» — это 3.14ец какие фанатики.
а это и есть — основная категория программерских форумов :)

(например такие мнения — dou.ua/...​rums/topic/35472/#2280998 вызывают у них бурю праведного негодования)

Комментарии должны описывать

Код на ЯП — это набор инструкций транслятору для построения системы по переработке информации.

Чтобы вносить изменения или дописывать такие инструкции — нужно прочесть, т.е. понять контекст, в котором задумывалась эта система или ее часть.
Поэтому уже высказался в
dou.ua/...​rums/topic/35450/#2280696

Могу еще добавить что вот те пресловутые митинги, что «всех достали» — призваны делать тоже самое — передавать контекст членам команды, который отсутствует в программном коде. а часто и сложно отыскивается в остальной документации проекта.

комментирование неочевидных, сложных мест в коде — это всего лишь одна из ролей для коментов.

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

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

оверинжиниринг — обычно никакого отношения к инженерии не имеет. Он следствие попытки не думать, а свести решение к механически повторяемым действиям: «если повесить подкову над дверью», «если помолиться святым мартину и фаулеру», ..

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

То есть проблема выбора между этими крайностями «скорость разработки» и «эксплуатационные характеристики и.с.»- не имеет общего решения.
Это всегда компромис, т.е. с одновременными потерями как читабельности, так и эффективности и.с. и его выбор обычно — эмпирический выбор, а не аналитический.

и комментарии — это средство добавить читабельности к нечитабельному коду.
на всяк случай продублирую:
1. а становится он нечитабельным потому что требуются определенные эксплуатационные характеристики, а не удовольствие от чтения
2. развитие проекта идет по никем и никак не прогнозируемому пути, потому что на старте этот путь никто в проекте и не мог знать, с такой детализацией, какая и описывается кодом на ЯП.

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

да!
нужно делать правильно! а неправильно — не нужно делать!

Именно это, насколько я понимаю, и имеет в виду Мартин.

но массово трактуется — что он против комментов вообще :)
вона, один написал что запрещает даже комментировать :)

Название метода, в идеале, должно говорить о том ЧТО он делает и давать представление о том КАК он это делает

но даже такое, идеальное, ничего не скажет — почему эти ЧТО и КАК такие, а не другие.
программирование не математика ж, можно было и по другому сделать

мало того, КАК он это делает — это уже нарушение инкапсуляции. Должно быть пофик — как там оно делается. А когда проблема — то загляни в исходник, и посмотри это КАК. Оно ж кодом написано, и, еще и комментариями. даже в приватных методах. По крайней мере внутренности основных фреймворков что мы используем сейчас в проекте — прекрасно откоментированы. Я и доку к ним перестал читать, все есть там же — в исходнике.
нубы писали, «мартина» не слушали, а коментировали, коментировали... а другие нубы этим нубам звезд на гитхабе наставили, и в проекты свои фундаментом кладут.

программирование не математика ж, можно было и по другому сделать

А что, в математике по другому нельзя? По-моему, как раз в математике и так можно доказать, и так можно, почти всегда доказательства будут разные. Более того, метод, в котором выполнено докательство, обычно никому и не интересен, кроме верификатора. Доказал ты какое-то свойство программы, верификатор схавал, всё, всопринимай это как данность, тебе по сути нужна только сигнатура метода, и что его можно как-то написать его тело.

По-моему, как раз в математике и так можно доказать, и так можно, почти всегда доказательства будут разные

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

потому что:

Более того, метод, в котором выполнено докательство, обычно никому и не интересен

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

буквально недавно один такой баг наконец пофиксили, мне на емайл пришло что приняли.

а публичное описание функционала — не поменялось

в математике же если нечто доказано — то что менять в доказательстве и по какой причине?
какая может быть потребность?

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

а в программировании как раз интересен.

Дык я про программирование и пишу, в некоторых ФП метод, конструирующие значение некоторого типа, является конструктивным доказательством формулы, которую этот тип представляет (изоморфизм Карри-Говарда). Поэтому и получается некоторый микс программирования и математики.

но даже такое, идеальное, ничего не скажет — почему эти ЧТО и КАК такие, а не другие.
программирование не математика ж, можно было и по другому сделать

Под КАК я имел в виду не детали реализации, а подробности самого действия. В приводимом примере это название метода, просто содержащее глагол «обновить». В зависимости от контекста, какому-нибудь классу может быть достаточно и метода с названием «update()», но только если это не приводит к путанице и кристально ясно что и каким образом этот метод делает. Например, метод update() у модели ORM. Из того, что существует команда SQL с таким же именем, то можно свободно допускать, что одноименный метод будет выполнять именно её, а не, скажем, обновлять свойства объекта в памяти. Но в конкретном случае примера совершенно не ясно КАК метод будет обновлять список: что-то пересчитывать, изменять сам список, писать из памяти — в базу, из базы — в память, из сервиса — в память и прочие комбинации.

В приводимом примере это название метода, просто содержащее глагол «обновить» ... метод update() у модели ORM. Из того, что существует команда SQL

а я под КАК я подразумеваю именно детали реализации.
один из патчей в известном фреймворке у меня для метода populateXXX
внутри данные записываются в хэшмапу, но если не было такого ключа для rawRows.
а в проекте логичнее чтобы при сортировке в конечном SQL — в итоговой коллекции были самые последние строки. всегда, не придумалось случая когда нужно чтобы первые.
populateXXX же этот — protected метод в глубинах, и чтобы снаружи добиться нужного поведения — надо будет писать неочевидный код, да еще неоптимальный с точки зрения БД.

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

тобто, в якомусь ідеальному світі код, тех завдання, спеки, описи тасок, і т.д повинні утворювати таку собі вікісистему.
звісно, зараз немає такого інструментарія

Ну ось у мене як раз такий інструментарій і є, де клік на комміт веде до воркайтему з тех завданням. А щоб ті завдання були зрозумілі, то є послідовний процес ревью технічного завдання. Так, ми робимо довго, але надійно. Учора прислали вдосконалений перелік стадій розробки нових фіч — там десь 23 пункти з купою ревью. Коли ТЗ добре написане та перевірене — чітко видно, що треба робити (або ретроспективно вияснити, чому було так зроблено). Я ще вимагаю робити окремі комміти для 1) заготовки для тестів, 2) самі тести і 3) реалізація фічі.
Це довго, та ми нікуди не поспішаємо

Ну тобто ще трохі, і можна буде написати генератор коду, Copilot++, на основі специфікацій та технічного завдання.

Тут я з вами згоден, суто кодери — зайва ланка у розробці

Я про те давно мрію, коли технології розробки вийдуть на рівень використання мов семантичної потужності ложбана або ифкуіля, і писати тоді треба буде тількі спеки та тз на них. Але то зовсім офтоп

Головна проблема таких статей полягає у тому, що автор свій власний досвід з обмеженної кількостю мов, парадігм, типів проектів намагається розповсюдити на усе та уся. Один борець за чистоту назв змінних навіть пропонував переписати усі підручники з математики та фізики, щоб порефакторити літери як незмістовні ідентифікатори.

в тритомнику Роджерса всі формули записані зі змістовними змінними, і дублюються з (x, y, z). Коли побачив — дуже зрадів, бо з часом цих змінних стає набагато більше чим грецького алфавіту.

www.google.com/...​q=роджерс физика&tbm=isch

Там формул на всю книжку як у Ландавщиці на одній сторінки. Не кажучи про рівень викладання.

дизлайк, ландау ліфшиць то інший трохи рівень, книжки роджерса десь на рівні з ландсбергом, для школи

Вот и получается, что разные требования порождают разные подходы. Если мы пишем книгу для домохозяек, то надо писать заглавными буквами СКОРОСТЬ. А если мы пишем для специалистов, то часто нам гораздо важнее структура формула, чем какие-то частности вроде что конкректно обозначено какой буквой. И там мы концентрируем внимание на отдельные фрагменты, чекаем размерность, находим подформулы со знакомым смыслов.

Понятно, что если топикстартер пишет бизнес логику, где всё изначально разделено на объекты, сложных формул там нет, то в общем-то ру́лит один подход. Но если взять bzip2, то мы попадаем немного в другой мир: хорошего естественного разделения на объекты не видно, часто переменными обозначаются сущности, которые даже идентификатором-рассказом не очень определить. И да, там уже будет код вида
huffman.c:33.

Если мы используем внутреннюю верификацию в каких-нить зависимых типах, например, вот в этом коде: braun-tree.agda, то мы тоже увидим много однобуквенных переменных большей частью потому, чтобы не засорять общий вид паттерн-матчинга, вывода, реврайтов и т. п. Сейчас код более-менее читабелен, а вот если позаменять идентификаторы на читабельные, то будет просто месиво.

И проблема таких вот общих рекомендаций в том, что автор делится своим опытом в узком конкректном стеке, но явно это не оговаривает и возникает как бы претензия на всё.

Не треба писати коментарі, вони не зроблять незрозумілий код краще.

пропоную автору експеримент: відкрити код будь-якого оптимізатора (наприклад, pytorch.org/...​orch/optim/adam.html#Adam ) чи будь-якої реалізації іншого математичного алгоритму і уявити, що коментарів нема. Чи автор пропонує, наприклад, посилання на роботу, де описано ЧОМУ в коді використані такі, а не інші формули, вписати в назви змінних? ;)
Люблю, знаєте, універсальні рецепти ))

Напевно, кожен читав якусь стару товсту книгу, в якій відбувається щось дивне, і виносками пояснюється, що насправді мав на увазі автор в контексті його часу та положення. Це і є коментарі, які пояснюють код.

Ну не пощастило автору зі старими книгами, буває )))

, як і розробники на Cobol.

і має широкий кругозір ))
www.quora.com/...​t-of-switching-is-so-high

Гарна та пізнавальна стаття.
Але особливо тішить, шо стаття написана державною (українською) мовою.
Дякую. Пишіть ще!

Не дуже правда зрозуміло, та мова називається укріш чи таки анукр.

Дуже просте правило: якщо ти не в змозі швидко написати простий тест, то код треба рефакторити до тих пір, поки тест не буде значно простіший за код.

А чтоб рефакторить нужно сначала написать тесты, как дед Фаулер завещал.

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

Почему все считают что человек который не может внятно себя выразить через код — способен внятно выразиться через коментарии ?)

Потому что
а) код предназначен не для выражения себя, а для выражения business/application/etc логики;
б) в естественном языке есть ряд отличий от кода, из-за которых некоторые вещи выражаются куда компактней.

Почему все считают что человек который не может внятно себя выразить через код — способен внятно выразиться через коментарии ?)

Сразу приходит в голову несколько вариантов

1. Трэйсинг нетривиальных бизнес-требований, реализованных в коде. Типа, «для всех желтых Фордов 2010 года скидка на страхование в 34.56%». В коде описывается просто, но потом, через год для нового разработчика понять почему так было сделано — задача весьма непростая. И простой комментарий типа «according to the business requirement BR75-124» очень сильно помогает.

2. Парсинг данных. С участием сложных регэкспов, либо кастомных бинарных форматов, да хотя бы просто длинные строки с разделителями. Комментарии по делу (хотя бы просто пара примеров ожидаемых данных ) экономят массу времени в случае когда надо сопровождать такой код

3. Обработка ошибок, сложнее чем одноуровневый try-catch — тут комментарии полезны более чем всегда.

В регэкспах можно ведь называть группы внятными именами. В парсинге данных (например, массив comma-separated string) я не разрешаю обращаться к элементу массива array[1] но можно объявить const int NameColumnIndex = 1 и брать array[NameColumnIndex] — и все читается легко и красиво
В обработке ошибок можно напридумывать свои внятно названные exceptions и отлавливать их

можно. но проще=быстрее в коменте поставить примеры строк которые и парсит.

Я не згоден із вами [про українських розробників і розробників бібліотек] і цілком поділяю думку автора. Гарно написаний код без коментарів краще погано написаного, але прокоментованого. Стосовно бібліотек, то в тому ж C++ їхній код скомпільований і єдиний спосіб пояснити аспекти — писати коментарі, тому приклад притягнутий за вуха.

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

Гарно написаний код без коментарів краще погано написаного, але прокоментованого

коменти бувають різні. як і код

наприклад якщо практикується «аджайл проектування» як я його називаю
ми спочатку пишемо що буде, треба написати — коментарями
потім — пишем зовнішні інтерфейси, сігнатурно
а потім реалізацію
такий підхид обов’язковий коли є дизайн-інтерв’ю. бо от те і рев’ювається — плани написання коду. які за об’ємом менші, та абстраговані від дрібниць, які точно прийдеться написати.

і коли написали код — то навіщо видаляті оті коментарі по яким рухались коли його писали?

Щоб було одно джерело правди, треба видалити той комент. А замість коментів можна писати тести.

тести тестують той функціонал згадку про який було видалено. вона була у коментах.

а джерело правди завжди єдине, на кожному проекті.
то і є отой код. який вже вийшов

а не спека, тз, і інші документи

код — то останній документ у якому і записана реальна картина проекту.

отож бо. Тре його робити легким для читання, а застарілі коменти видаляти

що такє — читання, на вашу думку?

і чому комент який пояснює до якого функціоналу оцей код — застарів?
якщо є код — то є отой функціонал?
якщо нема — то звісно він, комент був видалений разом з кодом.

як так може комент застаріти сам по собі, без коду до якого він написаний?

p.s.
вирішив таки глянути, у перший же не свій код, а ліби, RadioButtonGroup:
млін:
// Delay just a wee bit so Chrome doesn’t missing turning the button on.
// Chrome behaves differently in that focus is given to radio buttons
// when the user selects one, unlike Safari and Firefox.
setTimeout(function () {

// if focus is within the RadioButtonGroup, determine
// which radio button should be the active one
var focusable = ...

focus: focus && focusable // when contained in a FormField, focusIndicator = false, ...

tabIndex: focusable ? ’0′ : ’-1′ // necessary for Firefox

// force string
...
и так далее

нуби короче. не вміють писати без коментів

ви якою лібою, чи фреймворком користуєтесь, з відкритим кодом?
дайте подивитися як там — нема коментів

а то мені не везе, що не візьму, хоть на php, хоть на js — усюди оті трикляті коменти

Читання — процес отримання інформації чимось одним з чогось іншого. Якщо просто. А як Ви вважаєте, що таке читання?

До речі не намагаюсь змінити Вашу думку, робіть як Вам нра.
Звичайно інколи бувають ситуації коли треба щось написати, бо заскладна логіка. Але мені все ж подобається рух в бік того, щоб коментарів було якумого менше. Тому вважаю що треба вкладати достатньо зусиль у неймінгі керуясь чіткими правилами — це може навіть комусь піти на користь...

Наприклад щось на кшталт цього:

// Run all validations and return the result
const runAllValidations = React.useCallback(

— як на мене виглядає дивним ... Типу комент заради коменту... і це приклад з коду Formik.

А що до застарілих коментів. Так таке дійсно буває. Буває навіть коли хтось скопіював функцію з коментарем, підрехтував її для іншої таски, а деякі коменти не виправив. То як на мене краще б він їх видалив просто.

Я до речі не на стільки високої про себе думки щоб когось вважати гірше за себе(нубом), через те що хтось вважає інакше від мене. Сподіваюсь Ви так само.

Проблема в том, что у кода есть очень четкая нижняя граница сложности/некостыльности — код не может быть проще/некостыльней domain логики, которую он реализует. А domain логика в большинстве случаев находится вне контроля всего R&D, не то что разработчика.

Потому зачастую код невозможно сделать легким для чтения даже если есть на это ресурсы и желание.

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

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

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

Тогда уже литературное программирование...

названия методов и классов с десятка слов, это оно и есть. попытка писать на ЯП как на английском.

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

а не:
Я живу хорошо... просто замечательно... У меня всё есть, есть свой дом — он тёплый. В нём одна комната и кухня. Я без вас очень скучаю, особенно по вечерам. А здоровье моё не очень... то лапы ломит, то хвост отваливается. А на днях я линять начал. Старая шерсть с меня сыплется, хоть в дом не заходи. Зато новая растёт — чистая, шелковистая. Так что лохматость у меня повысилась. До свидания, ваш сын дядя Шарик

И все ж правильно написано, орфографических ошибок нет, фразы построены правильно
А чего ж — бред?

названия методов и классов с десятка слов, это оно и есть. попытка писать на ЯП как на английском.

Литературное программирование это не длинные названия методов и классов. Это концепция программирования, разработанная Д. Кнутом, в которой документация и текст программы объединены в одном исходнике, и на выходе после копмиляции получается как выполняемый файл, так и TeX (который компилируется в PDF) документ.

Как раз у Д. Кнута очень много сокращений в исходниках, хотя бы потому, что TeX разрабатывадся в конце 70-х и тогда у многих комипляторов были ограничения на длину переменных вплоть до 16-ти символов.

Литературное программирование это ещё и коментарии такого рода

Data structures for math mode. When TEX reads a formula that is enclosed between $’s, it constructs an mlist, which is essentially a tree structure representing that formula. An mlist is a linear sequence of items, but we can regard it as a tree structure because mlists can appear within mlists. For
example, many of the entries can be subscripted or superscripted, and such «scripts» are mlists in their own right.
An entire formula is parsed into such a tree before any of the actual typesetting is done, because the current style of type is usually not known until the formula has been fully scanned. For example, when the formula ‘$a+b \over c+d$’ is being read, there is no way to tell that ‘a+b’ will be in script size until ‘\over’ has appeared.

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

Минутка буквоедства. То, о чем вы пишите, называется Literate Programming, что переводится как «грамотное» программирование, а не литературное. Сути не меняет, just fyi.

Такие комментарии даже стандартизированы, для автоматической генерации документации.

Так что выходит оно кругом, литературное программирование. В приличных и публичных проектах.
И IDE даже заготовки добавляют

Подписаться на комментарии