Comments 34
5 за пересказ Мартина по памяти, 2 за копирование. Ну действительно, чуть ли не дословно переписано!
А у меня очень хорошая память, Так что двойку прошу не ставить ;)
Новичкам будет полезно.
А то что чуть ли не дословно — мхм, можно было на древнерусском языке, но смысл. Ниже приведены слова из книги Питера Гудлифа. Книги хоть и разные, контент очень похож.
Новичкам будет полезно.
А то что чуть ли не дословно — мхм, можно было на древнерусском языке, но смысл. Ниже приведены слова из книги Питера Гудлифа. Книги хоть и разные, контент очень похож.
Настоятельно рекомендую прочитать и автору статьи и тем, кто добавляет её в избранное:
Питер Гудлиф — Ремесло программиста. Практика написания хорошего кода
Питер Гудлиф — Ремесло программиста. Практика написания хорошего кода
«Золотые правила» из книги, описывающие данную статью:
Учитесь давать объектам прозрачные имена — они должны ясно описывать то, что за ними скрывается.
Чтобы придумать хорошее имя, главное — четко понимать, для кого оно предназначено. Только в этом случае имя может стать осмысленным. Если не удается придумать хорошее имя объекту, спросите себя, понятно ли вам его назначение.
Ясность имени предпочтительнее его краткости.
Предпочтительней такое правило именования, которое различает имена переменных и имена типов.
Давайте функциям имена с внешней точки зрения, в виде фраз, выражающих действие. Описывайте логическую операцию, а не способ реализации.
Качества хорошего имени:
1. Описательность
2. Техническая корректность
3. Идиоматичность
4. Тактичность (длина, стиль)
— Пишите код, который может прочесть нормальный человек, причем без напряжения. Компилятор как-нибудь справится.
Помещайте в код комментарии только в том случае, если не удается облегчить его понимание иными способами.
(с) Питер Гудлиф
Учитесь давать объектам прозрачные имена — они должны ясно описывать то, что за ними скрывается.
Чтобы придумать хорошее имя, главное — четко понимать, для кого оно предназначено. Только в этом случае имя может стать осмысленным. Если не удается придумать хорошее имя объекту, спросите себя, понятно ли вам его назначение.
Ясность имени предпочтительнее его краткости.
Предпочтительней такое правило именования, которое различает имена переменных и имена типов.
Давайте функциям имена с внешней точки зрения, в виде фраз, выражающих действие. Описывайте логическую операцию, а не способ реализации.
Качества хорошего имени:
1. Описательность
2. Техническая корректность
3. Идиоматичность
4. Тактичность (длина, стиль)
— Пишите код, который может прочесть нормальный человек, причем без напряжения. Компилятор как-нибудь справится.
Помещайте в код комментарии только в том случае, если не удается облегчить его понимание иными способами.
(с) Питер Гудлиф
… а еще у МакКоннела про это есть существенно больше одной главы. Ну то есть как минимум The Power of Variable Names + Good Routine Names.
Функция IsInRange() в посте — вообще непонятный шлак, да ещё и с ошибкой (одинаковый код в первых двух if). Что-то мне подсказывает, что так будет понятнее:
C# не знаю, поэтому написал на C++. Поведение функции поменялось
enum IntervalFlags
{
Interval_NotStrict = 0,
Interval_StrictLeft = 1 << 0,
Interval_StrictRight = 1 << 1,
Interval_Strict = Interval_StrictLeft | Interval_StrictRight
};
bool Date::IsInRange(const Date &left, const Date &right, IntervalFlags interval_flags)
{
return (range_flags & Interval_StrictLeft ? *this > left : *this >= left) &&
(range_flags & Interval_StrictRight ? *this < right : *this <= right);
}
C# не знаю, поэтому написал на C++. Поведение функции поменялось
Прошу прощения, отправил слишком рано.
Поведение функции поменялось немного, на первый взгляд, но никто не мешает прототип объявить так:
Тогда по умолчанию будет использоваться строгое неравенство, как и в оригинале. Кстати, возможно, название IntervalFlags не самое удачное, и должно быть что-то, связанное с relations.
Поведение функции поменялось немного, на первый взгляд, но никто не мешает прототип объявить так:
bool IsInRange(const Date &left, const Date &right, IntervalFlags interval_flags = Interval_Strict);
Тогда по умолчанию будет использоваться строгое неравенство, как и в оригинале. Кстати, возможно, название IntervalFlags не самое удачное, и должно быть что-то, связанное с relations.
считаю приведенную функцию — мало понятной. С таким же успехом можно наваять множество функций из одной строки но в сотни символов в длину, и что? это не самоцель. Код должен быть понятным, а не показывать какой автор молодец, что все в одну строку запихал. Считаю это кандидатом на рефакторинг.
P.S. спасибо за указание ошибки. поправил статью
А можете полному нубу в плюсах объяснить смысл строчек:
Зачем использовать сдвиг в объявлении енума?
Interval_StrictLeft = 1 << 0,
Interval_StrictRight = 1 << 1,
Зачем использовать сдвиг в объявлении енума?
Спасибо 1с за
ТипПроекцииГеографическойСхемы.ПсевдоцилиндрическаяПлоскоПолярнаяПроекцияЧетвертогоПорядкаМакБрайдаТомаса
Ну и всякие ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначенийИмениБорисаГеоргиевичаНуралиева
Это я к чему? Везде важен баланс…
ТипПроекцииГеографическойСхемы.ПсевдоцилиндрическаяПлоскоПолярнаяПроекцияЧетвертогоПорядкаМакБрайдаТомаса
Ну и всякие ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначенийИмениБорисаГеоргиевичаНуралиева
Это я к чему? Везде важен баланс…
А почему вы не говорите о том, что все должно быть задокументировано?
Когда читаешь чей-то код и у него нет документации, хочется руки поотрывать.
enum Dates{
/// <summary>
/// Дата первая
/// </summary>
GET_FIRST,
/// <summary>
/// Дата вторая
/// </summary>
GET_SECOND,
/// <summary>
/// Дата еще какая-то
/// </summary>
GET_BOTH,
/// <summary>
/// Дата никакая
/// </summary>
None
}
Когда читаешь чей-то код и у него нет документации, хочется руки поотрывать.
когда читаешь чей то код, идеальная документация — это сам код. Код не обманет (ну как правило).
Как я уже писал, комменты — это признак того, что из названия непонятно, что делает та или иная функция/переменная.
Бывает когда глянешь в чужой код (написанный хорошим программистом (без сарказма)) и удивляешься как все просто и лаконично — все интуитивно понятно. Причем как правило комменты там отсутствовали и нужды в них не было. Вот идеальная документация.
P.S. между кодом с комментами и чистым кодом без комментов я выберу второе. Код может быть обновлен, а комменты будут за ленью/или по др. причине забыты. В итоге комменты оторваны от кода. А это зло.
Как я уже писал, комменты — это признак того, что из названия непонятно, что делает та или иная функция/переменная.
Бывает когда глянешь в чужой код (написанный хорошим программистом (без сарказма)) и удивляешься как все просто и лаконично — все интуитивно понятно. Причем как правило комменты там отсутствовали и нужды в них не было. Вот идеальная документация.
P.S. между кодом с комментами и чистым кодом без комментов я выберу второе. Код может быть обновлен, а комменты будут за ленью/или по др. причине забыты. В итоге комменты оторваны от кода. А это зло.
А ещё лучше чистый код с каментами:)
Всё-таки каменты нужно — не всё можно объяснить именами переменных/функций.
Всё-таки каменты нужно — не всё можно объяснить именами переменных/функций.
понятно, что не все. Это не должно становится самоцелью. Но плодить коммента как документацию — увольте.
К вам вопрос — много комментво пишите? не надоедает? Я лично устаю быстро их писать.
/// ///Находится в состоянии загрузки
///
private bool isLoading;
/// /// Применить изменения
///
В таком
private void ApplyChanges(){
…
}
Не является ли это самоцелью?
К вам вопрос — много комментво пишите? не надоедает? Я лично устаю быстро их писать.
/// ///Находится в состоянии загрузки
///
private bool isLoading;
/// /// Применить изменения
///
В таком
private void ApplyChanges(){
…
}
Не является ли это самоцелью?
>К вам вопрос — много комментво пишите?
достаточно много, у нас это регламинтируется стандартом — каждый член класса обязательно должен иметь комментарии…
>Не является ли это самоцелью?
тут конечно согласен, в таких ситуациях каменты излишни.
сам уже устал генерировать коменты в стиле Капитана О.
достаточно много, у нас это регламинтируется стандартом — каждый член класса обязательно должен иметь комментарии…
>Не является ли это самоцелью?
тут конечно согласен, в таких ситуациях каменты излишни.
сам уже устал генерировать коменты в стиле Капитана О.
Комментарии позволяют указать требования для вызова функции без необходимости понимать, как она работает.
Хорошее имя функции сделает тоже самое. Понимаю что не всегда это достижимо, но как правило более чем возможно.
и еще вот к примеру. Есть класс с функциями. У функций есть комменты. Решили сделать рефакторинг дабы привести в порядок содержимое самих функций. В итоге некоторые функции разбились на несколько новых, пара функций была смержена, и т.д.
В случае цели писать комменты, придется для всех модифицированных функций проверять соответствие комментария с назначением функций. А если вы упустили одну из функций из вида, тогда комментарий будет вводить в заблуждение. После пары таких случаев программист начнет сомневаться в комментах. Дабл чекинг выходит.
В случае цели писать комменты, придется для всех модифицированных функций проверять соответствие комментария с назначением функций. А если вы упустили одну из функций из вида, тогда комментарий будет вводить в заблуждение. После пары таких случаев программист начнет сомневаться в комментах. Дабл чекинг выходит.
Писать ли комменты доки к приватным функциям ваших классов — это ваше дело. А вот описание публичных методов — будьте любезны предоставить, читать сотни строк кода ради того, чтобы понять, какие аргументы у функции допустимы и какие ошибки она генерит — недопустимо.
Тогда вопрос.
Допустим есть задача начисления зароботной платы.
есть функция
для функции GetCheck нужно описывать, все ошибки которые могут генериться среди вызываемых функций?
а те в свою очередь тоже что то могут генерить.
если меняется логика функции M2 вы легко можете забыть про какой нибудь коммент для функции M1 (где M1 вызывает M2).
Для Api безусловно нужны комментарии, а так, я не считаю, что они являются обязательным фактором.
P.S. всё вышесказанное является ИМХО и не хочу сказать что сказанное является абс. истинной. Кто то без комментов жить не может, а кто то легко обходится.
Допустим есть задача начисления зароботной платы.
есть функция
Check GetCheck(int empId){
....
var taxes=GetTaxes(empId, paymentType); // эта функция генерит свои ошибки
var fines=GetFines(empId); // эта тоже
return Calculate(taxes, fines, period) //и эта
}
для функции GetCheck нужно описывать, все ошибки которые могут генериться среди вызываемых функций?
а те в свою очередь тоже что то могут генерить.
если меняется логика функции M2 вы легко можете забыть про какой нибудь коммент для функции M1 (где M1 вызывает M2).
Для Api безусловно нужны комментарии, а так, я не считаю, что они являются обязательным фактором.
P.S. всё вышесказанное является ИМХО и не хочу сказать что сказанное является абс. истинной. Кто то без комментов жить не может, а кто то легко обходится.
Метод API — это черный ящик, что у него творится внутри — не важно. Поэтому и описывать внутреннее строение в комментах не нужно. А вот возможные возвращаемые значения и требования к аргументам — необходимо, на мой взгляд. Во-первых, это помогает понять, что делает функция, не заглядывая в код. Во-вторых, при разработке, комментирование помогает понять, что вообще требуется от такой функции. :)
В приведенном примере важно только, что такое Check, что возвращает функция GetCheck и что такое empId.
В приведенном примере важно только, что такое Check, что возвращает функция GetCheck и что такое empId.
>В приведенном примере важно только, что такое Check, что возвращает функция GetCheck и что такое empId.
В приведенном примере понятно что такое чек из названия, что возвращает GetCheck тоже, и суть параметра так же. Комменты излишни.
В приведенном примере понятно что такое чек из названия, что возвращает GetCheck тоже, и суть параметра так же. Комменты излишни.
А что возвратит функция в случае отрицательного/невалидного айдишника?
ArgumentException
Ну тогда это вот и надо задокументировать, по-хорошему. Потому что это совсем не очевидно. Я бы, например ожидал OutOfRangeException
у каждой команды своё видение того, как их система работает. Не хочу сказать, что у тебя неправильная логика, но как по мне, я бы скорее обошелся без документации, нежели с ней.
На счет типа ошибки, я погорячился чуть выше, ArgumentOutOfRangeException было бы лучше выкидывать.
На счет типа ошибки, я погорячился чуть выше, ArgumentOutOfRangeException было бы лучше выкидывать.
Хм. Возможно, вам все понятно, потому что это код из вашей системы?
Ну или я дурак. В любом случае, мне не очень ясно, что такое Check (я так понимаю, поля этого класса (структуры?) тоже не задокументированы?). Реальный «чек» — это бумажка с кучей информации и подписью. Наверное, тут что-то другое. Какая информация содержится в этом классе/структуре, сразу не ясно. Так же, как не ясно, почему ф-ция calculate возвращает Check, а не число, но этого я «как бы» ещё не видел.
Исходя из того, что название функции — GetCheck( emp id ), я могу только предполагать, что она возвращает.
Во-первых, не ясно, что произойдет, если id не совпал ни с одним из базы работников. Функция вывалится с исключением? Каким? Вернет какой-нибудь nullobject?
Во-вторых, не понятно, что на самом деле делает функция. Судя по сигнатуре, она возвращает некий чек, в котором, вероятно, содержится информация о какой-то зарплате сотрудника (ну, это из ваших слов выше, так бы я не догадался) за какой-то период времени.
Что функция вернет, если я её вызову с валидным id посреди месяца, если за прошлые месяцы зарплату сотруднику выдали и зарплату зачисляют раз в месяц? Чек с нулем в графе «бабло»? Рассчитанную по часам зарплату, начиная начала расчетного периода, заканчивая текущей датой? У меня ещё куча вариантов в голове. Нет, все, надо лезть в код метода, и в код функций, которых он вызывает.
Я бы сказал, что функция названа неудачно, а отсутствие комментариев усугубило ситуацию.
Ну или я дурак. В любом случае, мне не очень ясно, что такое Check (я так понимаю, поля этого класса (структуры?) тоже не задокументированы?). Реальный «чек» — это бумажка с кучей информации и подписью. Наверное, тут что-то другое. Какая информация содержится в этом классе/структуре, сразу не ясно. Так же, как не ясно, почему ф-ция calculate возвращает Check, а не число, но этого я «как бы» ещё не видел.
Исходя из того, что название функции — GetCheck( emp id ), я могу только предполагать, что она возвращает.
Во-первых, не ясно, что произойдет, если id не совпал ни с одним из базы работников. Функция вывалится с исключением? Каким? Вернет какой-нибудь nullobject?
Во-вторых, не понятно, что на самом деле делает функция. Судя по сигнатуре, она возвращает некий чек, в котором, вероятно, содержится информация о какой-то зарплате сотрудника (ну, это из ваших слов выше, так бы я не догадался) за какой-то период времени.
Что функция вернет, если я её вызову с валидным id посреди месяца, если за прошлые месяцы зарплату сотруднику выдали и зарплату зачисляют раз в месяц? Чек с нулем в графе «бабло»? Рассчитанную по часам зарплату, начиная начала расчетного периода, заканчивая текущей датой? У меня ещё куча вариантов в голове. Нет, все, надо лезть в код метода, и в код функций, которых он вызывает.
Я бы сказал, что функция названа неудачно, а отсутствие комментариев усугубило ситуацию.
Sign up to leave a comment.
Басни на ночь — Хорошие имена как залог успеха