Имена методов должны меняться там, где они должны. Если у Вас метод загрузки из некоторого абстракного хранилища, может БД, может файлов, может еще чего, то имя метода Load говорит только, что это загрузка. И очень странно было бы, если бы Вы подменив загрузку из базы, на загрузку из файлов, именно в этом методе изменили только аннотацию, не меняя имя. Либо имя меняется и аннотация, если есть, либо ни то ни другое. Внутри метода может быть вы делегируете работу методу LoadFromFile. Но это внутри.
По поводу Вашего примера с комментарием и физикой и всеми примерами, которые проводили, у меня свое мнение. Развожу руки. Любой из вариантов подойдет.
Во-первых, подойдет Ваш первоначальный вариант, только без комментария. Ваш комментарий говорит довольно очевидные для школьника вещи. Интересно, что за программист читает код и не знает второго закона Ньютона и закона всемирного тяготения. Даже если так, то код не обязан быть учебником по предметной области. Иначе, в коде можно еще и научить задачки решать детей.
В любой области код. Будете писать код для, например, юристов, не надо в коде расшифровывать юридические термины. Будете писать код для какой-то электроники, не нужно в коде обучать законам Кирхгофа.
Я считаю, что код не должен читать человек, который не знает языка программирования и который не знает предметной области. Код — не учебник по этим вещам. Код создает нечто новое на стыке этих известных до этого кода знаний. И если человек не обладает знаниями языка программирования (ему разжевывают в комментариях), или не имеет минимальных представлений о предметной области — то и читать код ему не зачем, чем меньше он знает о коде и где он лежит, тем лучше для кода.
Но там, в принципе, Вы сами решаете, какая публика читать будет код. Маленький комментарий может и не помешает.
Точно также я не вижу ничего плохого в том, что Вам ответили, разные варианты. Чем Вам не нравится этот пример кода функции? Читается слева направо без проблем. Имена должны быть понимаемыми. В такой последовательности выбирается:
1. Короткое понятное имя лучше длинного понятного.
2. Длинное понятное лучше (гораздо) короткого непонятного.
Поэтому, не вижу никаких проблем с длинным именем.
Хотя, я бы именно
function getMassFromForcePlanetMassAndRadius(force, planetMass, radius)
не стал так называть. Есть разные т.з. на формальные параметры. Часто считается, что они вообще локальные и извне их не видно. И да, скорее всего будут передаваться либо числами константами в каком-то порядке, либо внешними переменными с другими именами.
Но все же, я считаю, что лучше сократить имя:
function getBodyMass(gravityForce, planetMass, distanceFromBodyToPlanetCentre)
Т.е. имена параметров уже говорят из чего будет производиться вычисление. И если не числа хардкодом передавать в вызовах, а называть адекватно переменные, код будет читаться.
Вы сейчас говорите странную вещь. Если меняются требования, то Вы считаете, что лучше, чтобы это не отражалось на именах в коде, а менять только комментарии?
Я, лично, вообще не вижу никаких проблем менять имена функциям хоть каждые полчаса. Есть только нюансы с коллективной работой. Но то — проблемы индейцев, организационные вопросы должны мало отражаться на коде и не заставлять писать говнокод. Те вопросы решаются другими путями.
А еще, есть одна мысль, которую я не сказал, но и нигде здесь не прочитал. Любая документация, отличающаяся от кода, будь-то комментарии, будь-то схемы или любые другие файлы — совсем не очевидно, что помогает вообще, если брать в перспективе. Код — единственная вещь, которая говорит, как оно на самом деле сделано. И сколько я не разбирался с чужим кодом, всегда наступал момент, когда приходилось сесть и основательно просмотреть код. Т.е. если у Вас есть документация, то читаете ее. Редко видел ее полезной. Но допустим. Эта полезность выльется в то, что Вы себе представите как оно приблизительно работает. Но с такими знаниями лезть в код и что-то менять — дико опасно. Если допустим разовое изменение и забыли, возможно такой способ подойдет. Но не помню ни разу, чтобы так всё и происходило. Если Вы сейчас потратите полдня разбираясь с каким-то модулем в коде, а не 15 минут, то в перспективе Вы эти полдня не потратили зря, Вы уже знаете этот модуль изнутри. При следующих разах Вы уже будете значительно экономить время.
Вот поэтому гораздо важнее читаемость кода.
// // Далее мы ищем сумму пирожков во всех корзинках. Массив a[] содержит число пирожков в каждой корзинке
int c = a.Length();
int s = 0;
for (int i = 0; i < c; i++)
{
s += a[i];
}
Здесь без комментария и правда не разберешься, зачем этот код. Но присмотревшись, видим, что почему-то смысл происходящего описан только в комментарии. Когда как имена переменных ни о чем не говорят. Меняем ситуацию. Также переименовываем и в комментарии, чтобы не устарел
// Далее мы ищем cумму пирожков во всех корзинках. Массив pattyCountsInBaskets[] содержит число пирожков в каждой корзинке
int pattySum = 0;
for (int i = 0; i < pattyCountsInBaskets.Length(); i++)
{
pattySum += pattyCountsInBaskets[i];
}
Замечаем, что простое переименоваие сделало вторую фразу в комментарии бессмысленной. Убираем
// Далее мы ищем cумму пирожков во всех корзинках.
int pattySum = 0;
for (int i = 0; i < pattyCountsInBaskets.Length(); i++)
{
pattySum += pattyCountsInBaskets[i];
}
В принципе уже можно удалять и весь комментарий. И так понятно по переменной, что мы ищем и код не слишком большой, чтобы понять смысл. Но смотрим дальше. Нам надо найти сумму. С чего вдруг у нас обход массива от первого элемента до последнего? А почему не наоборот? Похоже тут лишняя информация. Замысел у нас короче — просто найти сумму. Переделываем.
int pattySum = 0;
foreach (int puttyCount in pattyCountsInBaskets)
{
pattySum += puttyCount;
}
Уже понятно, что мы складываем элементы (пирожки), просто. В не волнующем нас порядке. Уже лучше. Но все таки складывание — что-то лишнее. Находим метод суммы и пользуемся им:
int pattySum = pattyCountsInBaskets.Sum();
Вот здесь уже никто не упрекнет, что строка императивная и расписывает как делать, а не говорит что. Пример, конечно, вымышленный. Но улучшение кода внутри методов, для C#, не намного отличается. Там есть еще Linq, так что не только сумму можно найти. Если же в языке, допустим, нет такого средства, то тот кусок кода точно также можно было представить:
Э… Я в крайности не бросаюсь. Почти в каждом (здесь) комментарии писал: комментарии — худшее средство (или последнее средство) улучшения читаемости кода. Т.е. запасное, на всякий самый плохой случай. Но если код не читается даже при применении всех техник или если его нельзя делать читаемым ввиду оптимизации, то комментарии пишутся. Комментариев должно быть как можно меньше. Но только за счет хорошего кода. А не принципиально не писать.
Понимаете, задача документирования в идеале вообще не должна стоять. Код — это язык и это же документация. Заблуждение изначально, по моему мнению, конечно, в том, что когда-то решили, что код — это материальный объект. Что-то вроде дома или автомобиля. А документация — это чертежи, по которому его делают.
А вот и не правильно. Код — это тоже чертежи. Кто-то вдалбливает в голову на уровне подсознания, наверное, в ВУЗах, что так правильно с инженерной т.з. (и все себя в касках представляют деволоперами, конструкторское бюро еще есть). Когда как это не стройка, это не создание конструкций. Это перевод. Поэтому два перевода с языка заказчика держать глупо, неправильно принципиально. Еще интересно, когда еще и делают двойной перевод. Т.е. когда вначале рисуют схемы и пишут документацию, а потом с нее делают перевод уже на язык программирования.
Ладно, напишу ка я на примере ниже. Вроде ж просто всё и примеры можно приводить, как отказываться от комментариев.
судя по минусам вообще всем людям, которые против комментариев, такое ощущение, что здесь собрались враги языков программирования )))
Язык программирования — это язык. Выражая логику и смысл на нем, Вы, кроме этого, не дублируете свою работу. На нем в любом случае должна быть выражена логика, чтобы программа заработала. Кроме того, выражая на нем то, что вы задумали, полнее, вы еще и даете возможность компилятору эту логику проверять. Смысл (требования) — это всегда ограничения. Вы можете выбирать общий тип, для бОльшей гибкости и меньших ограничений, например, указатель на сырую память, передавая там число — возраст человека. И напишете комментарий, что там возраст. Это не утрирование, а доведение до крайности идеи с комментариями. А можете создать типы, точно ограничивающие данные, поведение, как и в требованиях. Последний подход — и есть выражение смысла в коде. Компилятор тогда будет с его (допустим) статической типизацией работать с высоким КПД и выдавать надежный машинный код. Смысл комментариев на этом фоне просто теряется.
То, что Вы проще понимаете человеческий язык… Не совсем верно. Вы думаете кучей языков, кроме естественного. Например, математика. Представьте себе школьную задачу — бросание камня под углом к горизонту. Естественным языком решение звучало бы так: ну примерно, как кажется, метров на 20-30. Язык же формул позволяет выдать точный ответ.
Естественные языки очень плохо подходят вообще для думать. Вы, когда думаете, еще и кучу всего моделируете, в том числе интуитивно используете математику.
Ну это лирика. Действительно, требования чаще всего выражаются естественным языком. Поэтому я и писал, что языки программирования не идеальны. Не близки к естественному, точнее, не одинаково близки. Будем ждать будущих языков.
Но из этого и не следует, что не нужно пытаться приблизить код к естественному языку, а надо писать говнокод и покрывать его комментариями, чтобы люди поняли.
Вообще, мне кажется, не только можно, но и нужно так говорить. Хотя бы потому, что есть две точки зрения:
1. Не важно как написан код, любой код считаем идентичным, если он выполняется правильно.
2. Код от кода сильно отличаются в плане читаемости, поддержки и т.д.
Если мы принимаем второе, то «куда стремиться» — это практика улучшения кода. Формально да, и комментарии — часть кода. У нас цель — улучшить читаемость и облегчить поддержку кода. Есть разные способы улучшения кода. Так комментарии — самый последний и самый худший. Можно код, например, упростить. Я вот недавно проект переписывал. Люди потратили на него два человеко-года. Я написал заново за 2 месяца (именно заново, не брал оттуда ни одной глупейшей идеи) и в итоге кода стало в 10 раз меньше. 40 000 строк против 4000. Думаю, мой код гораздо читабельнее, хотя бы в силу того, что с меньшим объемом надо разбираться.
А можно было бы разобраться с их кодом и покрыть комментариями. На самом деле причина переписывания была в том, что тот код невозможно было развивать никак. Хотя не костыли, а весь по задумкам автора на абстракциях и паттернах. Комментарии тому коду никак бы не помогли. Ну разобрались бы другие люди как работает. А изменять код все равно не возможно.
Код, по моему, надо рассматривать во многих срезах одновременно. И механический рефакторинг (DRY) и читабельность. Т.е. писать его или рефакторить так, чтобы он читался и в нем были видны намерения. В общем случае это невозможно. Для любых ситуаций. Для этого комментарии — как подстраховка. И тут не золотая середина нужна. Тут нужен золотой минимум для комментариев. Не имея критериев для улучшения кода, вы и не сможете улучшать.
Вот, мои критерии. Все они в разных плоскостях и надо смотреть на каждый и стремиться к улучшению каждого.
1. Размер кода. Есть некоторая корреляция между краткостью и поддерживаемостью, читаемостью. Грубая оценка. Но если код слишком большой для небольшой задачи, должны возникать подозрения.
2. DRY. Заметил на глаз, без какого-то анализа, что что-то повторяется (дежавю), надо разбираться, почему так получилось. Есть кандидаты на вынос в отдельный метод, в базовый класс и т.д.
3. Вынос логических кусков в отдельный метод. Та самая читаемость. Если хочется кусок прокомментировать — лучше дать ему имя, сделать отдельным методом. Тут нужен баланс. Так делать не всегда нужно. Вынос куска кода, который используется один раз, не требуется по DRY. Но и не нарушает этот принцип. Но вынос отдельного куска в отдельный метод — это также создание нового имени. Нарушение бритвы Оккама. Создание новой «сущности», а значит дополнительная смысловая нагрузка на читателя кода. Комментарии, кстати, ничем не лучше. Это тоже дополнительная нагрузка. Таким образом, надо всегда смотреть, насколько выгодно будет с т.з. читаемости выносить метод. Дело в его названии. Чтобы уменьшить смысловую нагрузку, имя в идеале должно быть уже известным и понятным читателю. Чтобы ему не надо было открывать метод.
4. Всё должно выражаться по возможности средствами языка программирования. Работа программиста – это работа переводчика. Если вы переводите с китайского на английский, то нечего там оставлять куски еще и на русском, которые вы не сумели перевести. Это говорит о вас, как о плохом переводчике. При этом средства языка программирования – я подразумеваю его родную семантику и синтаксис. Например – отражение в дотнете – архиплохая вещь. Иногда нужна, но она уже выходит за пределы языка. Когда вы говорите «корова», вы передаете смысл, а не считаете количество букв «О» и в каком порядке они идут. Язык – это средство передачи смысла, а не способ в нем самом искать глубокий смысл. Если представлять язык программирования – как язык, а не как конструктор для конструкций в виде стимпанка, то станет яснее, что такое кратко, точно и без искажений выразить мысль – требование заказчика.
5. Писать нужно как можно декларативнее. Вообще, по-моему, в императивности и декларативности языков есть немного лукавство. Даже в самом декларативном языке вы описываете также и логику и задаете направлении работы программы. Известный пример с вычислением квадратного корня. Декларативно задать программу – это указать, что квадрат искомого числа будет равен исходному. Но особо никакой язык эту задачу не решит, не имея аппарата исследования функций. Далее, вы в декларативном стиле на более низком уровне абстракции уже декларируете, что такое метод Ньютона. А в совокупности, это уже императивная программа.
Также и в императивном, особенно в ООП языке – вы можете большую часть кода выразить декларативно. Методы с ветвлениями, циклами и зашитым порядком инструкций – императивные. Классы, их связи – декларативные. Сами методы, даже если они внутри императивные, являются декларацией. Т.е. название метода – это декларация того, что вы хотите сделать. Когда вы пишете вызов метода – вы декларируете, что хотите некоторое действие и вам не важно, как оно выполнится. Как – это внутри того метода. Теперь, если ваш метод, не смотря на то, что он имеет какой-то последовательный код, он частично состоит из вызовов других методов. И вот, стремиться надо в ту сторону, чтобы методы читались целиком и не было желания у читателя заглядывать еще дальше внутрь вызовов. Опять встает вопрос баланса. Не стоит код превращать в балаган названий, скрывая все его конструкции. Где-то они всё равно будут и в совокупности, код это не упростит.
А вот здесь не о чем спорить. Всё так. Я и писал: это пост о том, к чему надо стремиться. Не всё можно сделать без комментариев отлично читаемым. Было бы прекрасно, если бы так получилось.
Другое дело, что часто программисты идеалом считают именно комментированный код. Т.е. стремятся не в ту сторону.
Кстати, устаревали комментарии как раз потому, что пока я их писал и дописывал потом код, настойчиво думал, что не так в коде? Почему пришлось комментарий писать? В итоге в большинстве случаев выкашивал комментарий и находил способ выразить его в коде, сделать код проще.
Соблазн не писать ерунду? Или если заставлять писать ерунду, то везде?
Методы с аннотацией ни на один бит не более документированы, чем методы без аннотации, если там тупо повторение названия методов и переменных.
Мы исходим из разных положений. Вы по-умолчанию считаете, что комментарии — это хорошо. Поэтому видимо такой вывод: создает нехорошие соблазны их не писать.
Я же думаю наоборот. Иногда комментарии полезны. Ну не сверхчеловек я, точнее, не сверхпрограммист. Чтобы смысл идеально закодить, чтобы код читался как книга, был кратким, ясным, лаконичным. И вот тогда появляются комментарии — как признание своего поражения. Иногда пишу аннотацию. Но только на тот параметр, который непонятен. Например, возврат булевского значения, а имя метода и так перегружено, чтобы понять, что значит истина, что ложь. Когда редко появляется комментарий, то он становится более полезным на фоне их отсутствия. Он больше притягивает внимание. Зачем писать бесполезный мусор? Это анти-DRY. Потом, при любом рефакторинге в смысле переименования (из другого места в коде), добавления переменных, изменения интерфейсов — аннотации устаревают и вводят в заблуждение.
Недавно писал сравнительно большой проект. Он зависел не только от моего кода, но была уже БД, поэтому был местами связан с кривым кодом. Пришлось писать комментарии в местах, чтобы пояснить, почему я так нестандартно написал код.
Комментария было за всё время штук 10. Но они так быстро устаревали, еще до того, как я класс допишу. В итоге осталось штук 2 комментария.
Да, и аннотации — это еще вопрос стиля, принятого в команде. Вообще, тут не о чем спорить, писать их не так напряжно. А для библиотек для внешнего использования может быть даже соглашусь с натяжкой, что нужны. Ну там, в док-файл выгрузить, схемы построить.
Код надо (в идеале) писать так, чтобы он выражал требования. А не реализацию. И правильно писали, что вместо комментариев эти требования прекрасно выражаются еще и тестами, если кодом не удается.
Суть поста, насколько я понял, и того, что я думаю — не в том, что надо запретить комментарии, а в том, чтобы определить куда стремиться и что хорошо, что плохо. Комментарии — это плохо. И их надо писать, когда уже не осталось других способов. Комментарии — это худший способ улучшить читаемость.
Чтобы немного сместить взгляд, представьте себе, что такое функция и что такое класс в другом русле. Тут где-то было и в комментариях к другим постам, что не имеет смысла выносить код в функцию, который используется один раз. Это механический способ рефакторинга, когда вы следуете DRY. Но можно кроме механики, ввести другой критерий. Допустим, вы написали довольно длинное полотно — код функции. Далее, хотите поставить комментарии на какие-то куски, объясняя, что они делают или как. Именно в этот момент, когда рука потянется комментировать, этот кусок и становится кандидатом для получения названия. И комментарий — по сути название новой функции. Тогда ваш код станет легко читать, как и комментированный. С той разницей, что смысл выражен в коде, а не в комментариях.
Всё это конечно спорно и требует чувства баланса. Языки программирования к сожалению не идеальны. Или я таких не знаю. Сила выражения мыслей на языке программирования зависит от языка, очевидно. Например, на Си, где нет эксепшинов, даже маленькое действие в методе превратится в много проверок и выходов. Но в С#, на котором сейчас работаю, действительно можно неплохо выразить мысль, без никаких дополнительных комментариев.
Если так, то переменная и должна назваться ageOfPersonInDays. Если в примере написали код, оставив переменную с названием age, а написал, что она в днях, то здесь и кроется ошибка программиста. В том то и зло комментариев, что они скрывают говнокод.
Язык программирования первичен и именно на нем по возможности надо выражать мысли, а не в комментариях.
Какие еще могут быть хитрости у этого метода? Иногда нужна аннотация из-за невыразительности некоторых аспектов языка. Например, это был C# и там как-то в сигнатуре нельзя указать, какой эксепшин будет.
Может быть int не подходит, т.к. отрицательные значения имеет. Опять же, смотрим на эту ситуацию и сразу думаем о коде, потом о комментариях. Если в коде, то есть uint. Если надо любое число, до секунд, с отсутствием отрицательных значений, то опять же, глупо внутри городить проверки и эксепшины и описывать их в комментарии — можно ввести специальный тип Age. То же и с телефоном.
Сигнатуры — тоже код. Аннотации — тоже комментарии и на них распространяются те же аргументы. Как думаете, насколько информативно такое комментирование?
/// <summary>
/// Adds Person
/// </summary>
/// <param name="age">Age of Person</param>
/// <param name="phoneNumber">Phone Number of Person</param>
void AddPerson(int age, string phoneNumber)
Ответ — ни насколько. Думаете это рафинированная ситуация? Отнюдь. При нормальном наименовании переменных, имен методов, параметров, комментировать практически везде бессмысленно.
Другое дело, что совсем иногда, когда какая-то хитрость и нельзя очевидным образом ее в коде выразить — тогда и комментируем. Понимая, что зло как раз в хитрости и вы сдаетесь, пытаясь прикрыть ее комментарием как фиговым листочком.
Почему не надо?
Перечитайте еще раз на цитату Макконела orionll
Константы, в отличие от комментариев — это код. Со всеми вытекающими. Это значит, что коду больше внимания. Это значит, что имя константы устаревает гораздо реже. Лично я вообще не помню, чтобы они устаревали, т.к. IDE прекрасно справляются по переименованию константы. Комментарии не компилируются. И не переименовываются во всех местах с помощью каких-то технических средств.
Да и самое главное — язык программирования — это в первую очередь язык. Ваша задача — выразить замысел требований на языке программирования.
Если код читается плохо, надо учиться что-то с кодом делать, чтобы он читался лучше. Код для программиста должен стать родным языком. Ни ЮМЛ, ни комментарии. С чего вдруг программисты когда-то решили, что комментарии так нужны? Похоже, что это были либо программисты, для которых язык программирования не родной, либо уже такой язык программирования, не позволяющий кратко/емко выражать мысли. Приходится мысли дублировать на естественном языке, разжевывая, что делает код, или даже цель/намерение кода.
Код говорящий? — пусть новичок читает.
Код говорящий, новичок не умеет читать? — не умеющий читать тот язык, на котором пришел работать, не нужен проекту.
Код не говорящий? Переписываем код, потому что он говно.
Код не говорящий, но его переписать понятнее нельзя (потому как хитрая оправданная оптимизация, например) — тогда и начинаем думать о комментировании.
Да да. Меня всегда принцип Парето формально удивлял. Люди с ГСМ очень его любят. Но при этом никто не думает, что для того, чтобы 20 процентов выстрелило, надо пропахать и 80 процентов.
А в манифесте тоже формально смешно звучит «Боритесь за закон Парето». Если это не закон и себя не проявляет, то давайте бороться за 10 процентов, а лучше за 5.
Понимаете, решения не могут приниматься просто так. За каждое решение кто-то несёт ответственность.
Это и есть корень ваших заблуждений. Как раз это и связанно с психологией. Вы не представляете себе процессов, не построенных на иерархии и подчинении. Армейско-зоновский вариант управления. Водопад. Поиск виновного. Вроде про это уже не мало написано. В программировании это несет только негативные последствия.
Какая ответственность, вы о чем? Людей должна мотивировать не ответственность, а заинтересованность в конечном результате и вовлеченность.
безусловно, держать в голове всю реализацию системы — не возможно. А вот какую то её часть, или общую схему — вполне.
конечно
Да, люди, выполняющие роль архитектора могут меняться. Но в данный конкретный момент времени должен быть конкретный человек, который отвечает за некую часть архитектуры (или за архитектуру в целом).
Тут где-то я пропустил целый пласт логики — вывод, что нужен/нужны архитекторы. Подмените кругом слово «архитектура» на слово «код», уберите слова «отвечает» — потому как программист не отвечает ничем и времена инквизиции прошли, а в тюрьму не посадят — и всё снова сходится.
В противном случае, на вопрос «почему мы потеряли гибкость системы» Вы получите ответ в стиле «ну… так получилось».
Так и получается. Вне зависимости, «отвечаете» вы или нет.
Архитектор и рядовой программист — такое деление хуже чем по рассам. Это подразумевает разделение работ. Т.е. будет значит некто, кто «творит» и кто это воплощает. Просто это и есть нонсенсом. Если должен человек держать в голове кусок абстракции — как работает система, то лучше, чем тот кто этот кусок и пишет — никто знать не может. Поэтому архитекторы, как выделенные люди, не нужны.
По поводу Вашего примера с комментарием и физикой и всеми примерами, которые проводили, у меня свое мнение. Развожу руки. Любой из вариантов подойдет.
Во-первых, подойдет Ваш первоначальный вариант, только без комментария. Ваш комментарий говорит довольно очевидные для школьника вещи. Интересно, что за программист читает код и не знает второго закона Ньютона и закона всемирного тяготения. Даже если так, то код не обязан быть учебником по предметной области. Иначе, в коде можно еще и научить задачки решать детей.
В любой области код. Будете писать код для, например, юристов, не надо в коде расшифровывать юридические термины. Будете писать код для какой-то электроники, не нужно в коде обучать законам Кирхгофа.
Я считаю, что код не должен читать человек, который не знает языка программирования и который не знает предметной области. Код — не учебник по этим вещам. Код создает нечто новое на стыке этих известных до этого кода знаний. И если человек не обладает знаниями языка программирования (ему разжевывают в комментариях), или не имеет минимальных представлений о предметной области — то и читать код ему не зачем, чем меньше он знает о коде и где он лежит, тем лучше для кода.
Но там, в принципе, Вы сами решаете, какая публика читать будет код. Маленький комментарий может и не помешает.
Точно также я не вижу ничего плохого в том, что Вам ответили, разные варианты. Чем Вам не нравится этот пример кода функции? Читается слева направо без проблем. Имена должны быть понимаемыми. В такой последовательности выбирается:
1. Короткое понятное имя лучше длинного понятного.
2. Длинное понятное лучше (гораздо) короткого непонятного.
Поэтому, не вижу никаких проблем с длинным именем.
Хотя, я бы именно
не стал так называть. Есть разные т.з. на формальные параметры. Часто считается, что они вообще локальные и извне их не видно. И да, скорее всего будут передаваться либо числами константами в каком-то порядке, либо внешними переменными с другими именами.
Но все же, я считаю, что лучше сократить имя:
Т.е. имена параметров уже говорят из чего будет производиться вычисление. И если не числа хардкодом передавать в вызовах, а называть адекватно переменные, код будет читаться.
Я, лично, вообще не вижу никаких проблем менять имена функциям хоть каждые полчаса. Есть только нюансы с коллективной работой. Но то — проблемы индейцев, организационные вопросы должны мало отражаться на коде и не заставлять писать говнокод. Те вопросы решаются другими путями.
А еще, есть одна мысль, которую я не сказал, но и нигде здесь не прочитал. Любая документация, отличающаяся от кода, будь-то комментарии, будь-то схемы или любые другие файлы — совсем не очевидно, что помогает вообще, если брать в перспективе. Код — единственная вещь, которая говорит, как оно на самом деле сделано. И сколько я не разбирался с чужим кодом, всегда наступал момент, когда приходилось сесть и основательно просмотреть код. Т.е. если у Вас есть документация, то читаете ее. Редко видел ее полезной. Но допустим. Эта полезность выльется в то, что Вы себе представите как оно приблизительно работает. Но с такими знаниями лезть в код и что-то менять — дико опасно. Если допустим разовое изменение и забыли, возможно такой способ подойдет. Но не помню ни разу, чтобы так всё и происходило. Если Вы сейчас потратите полдня разбираясь с каким-то модулем в коде, а не 15 минут, то в перспективе Вы эти полдня не потратили зря, Вы уже знаете этот модуль изнутри. При следующих разах Вы уже будете значительно экономить время.
Вот поэтому гораздо важнее читаемость кода.
Разберем первую строку. Просто меняю имя переменным и комментарий сразу становится бессмысленным повторением кода:
Если еще ввести некоторые элементы языка для повышения читаемости, то:
И т.д. Обычно комментарии всегда можно выкосить. Они показывают то, о чем должен говорить сам код.
PS. Не знаю, почему так жутко раскрашивается текст C#
Здесь без комментария и правда не разберешься, зачем этот код. Но присмотревшись, видим, что почему-то смысл происходящего описан только в комментарии. Когда как имена переменных ни о чем не говорят. Меняем ситуацию. Также переименовываем и в комментарии, чтобы не устарел
Замечаем, что простое переименоваие сделало вторую фразу в комментарии бессмысленной. Убираем
В принципе уже можно удалять и весь комментарий. И так понятно по переменной, что мы ищем и код не слишком большой, чтобы понять смысл. Но смотрим дальше. Нам надо найти сумму. С чего вдруг у нас обход массива от первого элемента до последнего? А почему не наоборот? Похоже тут лишняя информация. Замысел у нас короче — просто найти сумму. Переделываем.
Уже понятно, что мы складываем элементы (пирожки), просто. В не волнующем нас порядке. Уже лучше. Но все таки складывание — что-то лишнее. Находим метод суммы и пользуемся им:
Вот здесь уже никто не упрекнет, что строка императивная и расписывает как делать, а не говорит что. Пример, конечно, вымышленный. Но улучшение кода внутри методов, для C#, не намного отличается. Там есть еще Linq, так что не только сумму можно найти. Если же в языке, допустим, нет такого средства, то тот кусок кода точно также можно было представить:
или если массив является полем:
А вот и не правильно. Код — это тоже чертежи. Кто-то вдалбливает в голову на уровне подсознания, наверное, в ВУЗах, что так правильно с инженерной т.з. (и все себя в касках представляют деволоперами, конструкторское бюро еще есть). Когда как это не стройка, это не создание конструкций. Это перевод. Поэтому два перевода с языка заказчика держать глупо, неправильно принципиально. Еще интересно, когда еще и делают двойной перевод. Т.е. когда вначале рисуют схемы и пишут документацию, а потом с нее делают перевод уже на язык программирования.
Ладно, напишу ка я на примере ниже. Вроде ж просто всё и примеры можно приводить, как отказываться от комментариев.
Язык программирования — это язык. Выражая логику и смысл на нем, Вы, кроме этого, не дублируете свою работу. На нем в любом случае должна быть выражена логика, чтобы программа заработала. Кроме того, выражая на нем то, что вы задумали, полнее, вы еще и даете возможность компилятору эту логику проверять. Смысл (требования) — это всегда ограничения. Вы можете выбирать общий тип, для бОльшей гибкости и меньших ограничений, например, указатель на сырую память, передавая там число — возраст человека. И напишете комментарий, что там возраст. Это не утрирование, а доведение до крайности идеи с комментариями. А можете создать типы, точно ограничивающие данные, поведение, как и в требованиях. Последний подход — и есть выражение смысла в коде. Компилятор тогда будет с его (допустим) статической типизацией работать с высоким КПД и выдавать надежный машинный код. Смысл комментариев на этом фоне просто теряется.
То, что Вы проще понимаете человеческий язык… Не совсем верно. Вы думаете кучей языков, кроме естественного. Например, математика. Представьте себе школьную задачу — бросание камня под углом к горизонту. Естественным языком решение звучало бы так: ну примерно, как кажется, метров на 20-30. Язык же формул позволяет выдать точный ответ.
Естественные языки очень плохо подходят вообще для думать. Вы, когда думаете, еще и кучу всего моделируете, в том числе интуитивно используете математику.
Ну это лирика. Действительно, требования чаще всего выражаются естественным языком. Поэтому я и писал, что языки программирования не идеальны. Не близки к естественному, точнее, не одинаково близки. Будем ждать будущих языков.
Но из этого и не следует, что не нужно пытаться приблизить код к естественному языку, а надо писать говнокод и покрывать его комментариями, чтобы люди поняли.
1. Не важно как написан код, любой код считаем идентичным, если он выполняется правильно.
2. Код от кода сильно отличаются в плане читаемости, поддержки и т.д.
Если мы принимаем второе, то «куда стремиться» — это практика улучшения кода. Формально да, и комментарии — часть кода. У нас цель — улучшить читаемость и облегчить поддержку кода. Есть разные способы улучшения кода. Так комментарии — самый последний и самый худший. Можно код, например, упростить. Я вот недавно проект переписывал. Люди потратили на него два человеко-года. Я написал заново за 2 месяца (именно заново, не брал оттуда ни одной глупейшей идеи) и в итоге кода стало в 10 раз меньше. 40 000 строк против 4000. Думаю, мой код гораздо читабельнее, хотя бы в силу того, что с меньшим объемом надо разбираться.
А можно было бы разобраться с их кодом и покрыть комментариями. На самом деле причина переписывания была в том, что тот код невозможно было развивать никак. Хотя не костыли, а весь по задумкам автора на абстракциях и паттернах. Комментарии тому коду никак бы не помогли. Ну разобрались бы другие люди как работает. А изменять код все равно не возможно.
Код, по моему, надо рассматривать во многих срезах одновременно. И механический рефакторинг (DRY) и читабельность. Т.е. писать его или рефакторить так, чтобы он читался и в нем были видны намерения. В общем случае это невозможно. Для любых ситуаций. Для этого комментарии — как подстраховка. И тут не золотая середина нужна. Тут нужен золотой минимум для комментариев. Не имея критериев для улучшения кода, вы и не сможете улучшать.
Вот, мои критерии. Все они в разных плоскостях и надо смотреть на каждый и стремиться к улучшению каждого.
1. Размер кода. Есть некоторая корреляция между краткостью и поддерживаемостью, читаемостью. Грубая оценка. Но если код слишком большой для небольшой задачи, должны возникать подозрения.
2. DRY. Заметил на глаз, без какого-то анализа, что что-то повторяется (дежавю), надо разбираться, почему так получилось. Есть кандидаты на вынос в отдельный метод, в базовый класс и т.д.
3. Вынос логических кусков в отдельный метод. Та самая читаемость. Если хочется кусок прокомментировать — лучше дать ему имя, сделать отдельным методом. Тут нужен баланс. Так делать не всегда нужно. Вынос куска кода, который используется один раз, не требуется по DRY. Но и не нарушает этот принцип. Но вынос отдельного куска в отдельный метод — это также создание нового имени. Нарушение бритвы Оккама. Создание новой «сущности», а значит дополнительная смысловая нагрузка на читателя кода. Комментарии, кстати, ничем не лучше. Это тоже дополнительная нагрузка. Таким образом, надо всегда смотреть, насколько выгодно будет с т.з. читаемости выносить метод. Дело в его названии. Чтобы уменьшить смысловую нагрузку, имя в идеале должно быть уже известным и понятным читателю. Чтобы ему не надо было открывать метод.
4. Всё должно выражаться по возможности средствами языка программирования. Работа программиста – это работа переводчика. Если вы переводите с китайского на английский, то нечего там оставлять куски еще и на русском, которые вы не сумели перевести. Это говорит о вас, как о плохом переводчике. При этом средства языка программирования – я подразумеваю его родную семантику и синтаксис. Например – отражение в дотнете – архиплохая вещь. Иногда нужна, но она уже выходит за пределы языка. Когда вы говорите «корова», вы передаете смысл, а не считаете количество букв «О» и в каком порядке они идут. Язык – это средство передачи смысла, а не способ в нем самом искать глубокий смысл. Если представлять язык программирования – как язык, а не как конструктор для конструкций в виде стимпанка, то станет яснее, что такое кратко, точно и без искажений выразить мысль – требование заказчика.
5. Писать нужно как можно декларативнее. Вообще, по-моему, в императивности и декларативности языков есть немного лукавство. Даже в самом декларативном языке вы описываете также и логику и задаете направлении работы программы. Известный пример с вычислением квадратного корня. Декларативно задать программу – это указать, что квадрат искомого числа будет равен исходному. Но особо никакой язык эту задачу не решит, не имея аппарата исследования функций. Далее, вы в декларативном стиле на более низком уровне абстракции уже декларируете, что такое метод Ньютона. А в совокупности, это уже императивная программа.
Также и в императивном, особенно в ООП языке – вы можете большую часть кода выразить декларативно. Методы с ветвлениями, циклами и зашитым порядком инструкций – императивные. Классы, их связи – декларативные. Сами методы, даже если они внутри императивные, являются декларацией. Т.е. название метода – это декларация того, что вы хотите сделать. Когда вы пишете вызов метода – вы декларируете, что хотите некоторое действие и вам не важно, как оно выполнится. Как – это внутри того метода. Теперь, если ваш метод, не смотря на то, что он имеет какой-то последовательный код, он частично состоит из вызовов других методов. И вот, стремиться надо в ту сторону, чтобы методы читались целиком и не было желания у читателя заглядывать еще дальше внутрь вызовов. Опять встает вопрос баланса. Не стоит код превращать в балаган названий, скрывая все его конструкции. Где-то они всё равно будут и в совокупности, код это не упростит.
Другое дело, что часто программисты идеалом считают именно комментированный код. Т.е. стремятся не в ту сторону.
Соблазн не писать ерунду? Или если заставлять писать ерунду, то везде?
Методы с аннотацией ни на один бит не более документированы, чем методы без аннотации, если там тупо повторение названия методов и переменных.
Мы исходим из разных положений. Вы по-умолчанию считаете, что комментарии — это хорошо. Поэтому видимо такой вывод: создает нехорошие соблазны их не писать.
Я же думаю наоборот. Иногда комментарии полезны. Ну не сверхчеловек я, точнее, не сверхпрограммист. Чтобы смысл идеально закодить, чтобы код читался как книга, был кратким, ясным, лаконичным. И вот тогда появляются комментарии — как признание своего поражения. Иногда пишу аннотацию. Но только на тот параметр, который непонятен. Например, возврат булевского значения, а имя метода и так перегружено, чтобы понять, что значит истина, что ложь. Когда редко появляется комментарий, то он становится более полезным на фоне их отсутствия. Он больше притягивает внимание. Зачем писать бесполезный мусор? Это анти-DRY. Потом, при любом рефакторинге в смысле переименования (из другого места в коде), добавления переменных, изменения интерфейсов — аннотации устаревают и вводят в заблуждение.
Недавно писал сравнительно большой проект. Он зависел не только от моего кода, но была уже БД, поэтому был местами связан с кривым кодом. Пришлось писать комментарии в местах, чтобы пояснить, почему я так нестандартно написал код.
Комментария было за всё время штук 10. Но они так быстро устаревали, еще до того, как я класс допишу. В итоге осталось штук 2 комментария.
Да, и аннотации — это еще вопрос стиля, принятого в команде. Вообще, тут не о чем спорить, писать их не так напряжно. А для библиотек для внешнего использования может быть даже соглашусь с натяжкой, что нужны. Ну там, в док-файл выгрузить, схемы построить.
Суть поста, насколько я понял, и того, что я думаю — не в том, что надо запретить комментарии, а в том, чтобы определить куда стремиться и что хорошо, что плохо. Комментарии — это плохо. И их надо писать, когда уже не осталось других способов. Комментарии — это худший способ улучшить читаемость.
Чтобы немного сместить взгляд, представьте себе, что такое функция и что такое класс в другом русле. Тут где-то было и в комментариях к другим постам, что не имеет смысла выносить код в функцию, который используется один раз. Это механический способ рефакторинга, когда вы следуете DRY. Но можно кроме механики, ввести другой критерий. Допустим, вы написали довольно длинное полотно — код функции. Далее, хотите поставить комментарии на какие-то куски, объясняя, что они делают или как. Именно в этот момент, когда рука потянется комментировать, этот кусок и становится кандидатом для получения названия. И комментарий — по сути название новой функции. Тогда ваш код станет легко читать, как и комментированный. С той разницей, что смысл выражен в коде, а не в комментариях.
Всё это конечно спорно и требует чувства баланса. Языки программирования к сожалению не идеальны. Или я таких не знаю. Сила выражения мыслей на языке программирования зависит от языка, очевидно. Например, на Си, где нет эксепшинов, даже маленькое действие в методе превратится в много проверок и выходов. Но в С#, на котором сейчас работаю, действительно можно неплохо выразить мысль, без никаких дополнительных комментариев.
Язык программирования первичен и именно на нем по возможности надо выражать мысли, а не в комментариях.
Какие еще могут быть хитрости у этого метода? Иногда нужна аннотация из-за невыразительности некоторых аспектов языка. Например, это был C# и там как-то в сигнатуре нельзя указать, какой эксепшин будет.
Может быть int не подходит, т.к. отрицательные значения имеет. Опять же, смотрим на эту ситуацию и сразу думаем о коде, потом о комментариях. Если в коде, то есть uint. Если надо любое число, до секунд, с отсутствием отрицательных значений, то опять же, глупо внутри городить проверки и эксепшины и описывать их в комментарии — можно ввести специальный тип Age. То же и с телефоном.
Ответ — ни насколько. Думаете это рафинированная ситуация? Отнюдь. При нормальном наименовании переменных, имен методов, параметров, комментировать практически везде бессмысленно.
Другое дело, что совсем иногда, когда какая-то хитрость и нельзя очевидным образом ее в коде выразить — тогда и комментируем. Понимая, что зло как раз в хитрости и вы сдаетесь, пытаясь прикрыть ее комментарием как фиговым листочком.
Перечитайте еще раз на цитату Макконела orionll
Константы, в отличие от комментариев — это код. Со всеми вытекающими. Это значит, что коду больше внимания. Это значит, что имя константы устаревает гораздо реже. Лично я вообще не помню, чтобы они устаревали, т.к. IDE прекрасно справляются по переименованию константы. Комментарии не компилируются. И не переименовываются во всех местах с помощью каких-то технических средств.
Да и самое главное — язык программирования — это в первую очередь язык. Ваша задача — выразить замысел требований на языке программирования.
Если код читается плохо, надо учиться что-то с кодом делать, чтобы он читался лучше. Код для программиста должен стать родным языком. Ни ЮМЛ, ни комментарии. С чего вдруг программисты когда-то решили, что комментарии так нужны? Похоже, что это были либо программисты, для которых язык программирования не родной, либо уже такой язык программирования, не позволяющий кратко/емко выражать мысли. Приходится мысли дублировать на естественном языке, разжевывая, что делает код, или даже цель/намерение кода.
Код говорящий, новичок не умеет читать? — не умеющий читать тот язык, на котором пришел работать, не нужен проекту.
Код не говорящий? Переписываем код, потому что он говно.
Код не говорящий, но его переписать понятнее нельзя (потому как хитрая оправданная оптимизация, например) — тогда и начинаем думать о комментировании.
Выше цитата из Макконела где-то о том же.
А в манифесте тоже формально смешно звучит «Боритесь за закон Парето». Если это не закон и себя не проявляет, то давайте бороться за 10 процентов, а лучше за 5.
Это и есть корень ваших заблуждений. Как раз это и связанно с психологией. Вы не представляете себе процессов, не построенных на иерархии и подчинении. Армейско-зоновский вариант управления. Водопад. Поиск виновного. Вроде про это уже не мало написано. В программировании это несет только негативные последствия.
Какая ответственность, вы о чем? Людей должна мотивировать не ответственность, а заинтересованность в конечном результате и вовлеченность.
Есть
конечно
Тут где-то я пропустил целый пласт логики — вывод, что нужен/нужны архитекторы. Подмените кругом слово «архитектура» на слово «код», уберите слова «отвечает» — потому как программист не отвечает ничем и времена инквизиции прошли, а в тюрьму не посадят — и всё снова сходится.
Так и получается. Вне зависимости, «отвечаете» вы или нет.
Архитектор и рядовой программист — такое деление хуже чем по рассам. Это подразумевает разделение работ. Т.е. будет значит некто, кто «творит» и кто это воплощает. Просто это и есть нонсенсом. Если должен человек держать в голове кусок абстракции — как работает система, то лучше, чем тот кто этот кусок и пишет — никто знать не может. Поэтому архитекторы, как выделенные люди, не нужны.
Но в общем спор бессмыслен.
Это и есть большая выборка. В мире не всего лишь два программиста. И не обязательно на своих личных опытах выбора выводить закономерности.