Чистые комментарии к коду против документации класса

83

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

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

public Product GetById(int productId) {...}

Я добавляю следующую сводку метода

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary

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

Однако мои коллеги считают, что такого рода комментарии являются « запахом кода » и что «комментарии всегда являются ошибками» ( Роберт К. Мартин ).

Есть ли способ выразить и передать эти типы знаний без добавления комментариев? Поскольку я большой поклонник Роберта С. Мартина, я немного запутался. Являются ли резюме такими же, как комментарии, и, следовательно, всегда неудачи?

Это не вопрос о встроенных комментариях.

Bjorn
источник
38
Роберт Мартин сказал: «Комментарии - это всегда неудачи»? Ну, тогда он крайний экстремист, и его нужно взять с щепоткой соли. (Да, я знаю, что он пишет так в риторических целях, чтобы донести свое послание. Мое
мнение таково
18
Книги дяди Боба должны прийти с 1 кг мешка соли ...
AK_
6
Если вы следуете за Робертом Мартином, документация для нулевого случая должна быть проверкой. То есть у вас должен быть тест, показывающий, в каком случае метод может возвращать ноль. Кроме того, поскольку это Java, аннотация @Nullable также будет лучше, чем комментарий.
Мартин Эпс,
15
@Bjorn У меня есть копия Чистого кода, и я прочитал ее на обложке, чтобы покрыть ее не раз. Да, дядя Боб предпочитает самодокументируемый код, но в книге есть несколько примеров комментариев в его собственном коде . Дело в том, что если вы чувствуете необходимость написать комментарий, постарайтесь изменить код, а не добавлять комментарий, но не запрещайте комментарии полностью (даже встроенные комментарии).
6
Метод должен называться TryGetById, а комментарий должен быть удален.
usr

Ответы:

116

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

Учитывая это, мы можем применить тот же принцип СУХОЙ . Означает ли комментарий то же самое, что и подпись? Давайте посмотрим на ваш пример:

Получает продукт по его идентификатору

Эта часть просто повторяет то, что мы уже видим из имени GetByIdи типа возврата Product. Также возникает вопрос, в чем разница между «получением» и «извлечением», и какое отношение имеет код к комментарию в отношении этого различия. Так что это ненужно и немного сбивает с толку. Во всяком случае, это мешает действительно полезной второй части комментария:

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

Ах! Это то, что мы определенно не можем знать наверняка только из подписи, и предоставляет полезную информацию.


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

Поэтому, если ваши коллеги говорят вам, что этот комментарий о нуле - это запах кода, вы должны просто спросить их: «Хорошо, как мне тогда выразить это?» Если у них есть выполнимый ответ, вы чему-то научились. Если нет, это, вероятно, убьет их жалобы мертвыми.


Что касается этого конкретного случая, то, как правило, нулевая проблема, как известно, является сложной. Есть основания кода причины, изобилующие защитными предложениями, почему проверки нуля являются популярным предварительным условием для контрактов кода, почему существование нуля было названо «ошибкой в ​​миллиард долларов». Не так много жизнеспособных вариантов. Тем не менее, одним из самых популярных в C # является Try...соглашение:

public bool TryGetById(int productId, out Product product);

В других языках может быть идиоматично использовать тип (часто называемый чем-то вроде Optionalили Maybe), чтобы указать результат, который может или не может быть:

public Optional<Product> GetById(int productId);

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

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

Бен Ааронсон
источник
9
Или Linq-эквивалентно из Try..., ...OrDefault, возвращающих default(T)если предложение приведет к пустому результату.
Барт ван Ниероп
4
Я очень ценю ваше различие между комментариями к встроенному коду и комментариями к документации и приведенными примерами :)
Рэйчел
2
Возможные возвращаемые значения функции должны быть очевидны по ее сигнатуре. TryGetValueКартина является разумным способом сделать это в C #, но большинство функциональных языков есть лучший способ представления недостающего значения. Подробнее здесь
AlexFoxGill
2
@BenAaronson: Если кто-то хочет иметь универсальный интерфейс, который может поддерживать ковариацию, его можно использовать либо T TryGetValue(params, ref bool success)для любого типа T, либо T TryGetValue(params)с нулевым значением, указывающим на сбой, для типа T с ограниченным классом, но TryGetXXвозвращаемый шаблон boolнесовместим с ковариацией.
Суперкат
6
В Java 8 вы можете возвращать, Optional<Product>чтобы указать, что не может быть Продукт, возвращенный из метода.
Вим Deblauwe
102

Цитата Роберта К. Мартина вырвана из контекста. Вот цитата с немного большим контекстом:

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

Комментарии не похожи на список Шиндлера. Они не "чисто хорошие". Действительно, комментарии в лучшем случае являются неизбежным злом. Если бы наши языки программирования были достаточно выразительными, или если бы у нас был талант тонко владеть этими языками, чтобы выразить свое намерение, нам бы не понадобились комментарии очень сильно - возможно, вовсе нет.

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

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

(Скопировано здесь , но оригинальная цитата взята из Чистого кода: Справочник по мастерству гибкого программного обеспечения )

То, как эта цитата превращается в «Комментарии - всегда неудачи», является хорошим примером того, как некоторые люди вычтут разумную цитату из контекста и превратят ее в глупую догму.


Документация API (например, javadoc) должна документировать API, чтобы пользователь мог использовать его, не читая исходный код . Таким образом, в этом случае документация должна объяснить, что делает метод. Теперь вы можете утверждать, что «Извлечение продукта по его идентификатору» является избыточным, потому что оно уже указано именем метода, но информация, которая nullможет быть возвращена, определенно важна для документа, поскольку это ни в коей мере не очевидно.

Если вы хотите избежать необходимости комментария, вы должны устранить основную проблему (которая является использованием nullв качестве допустимого возвращаемого значения), сделав API более явным. Например, вы можете вернуть какой-то Option<Product>тип, так что сигнатура типа сама четко сообщает, что будет возвращено в случае, если продукт не найден.

Но в любом случае нереально полностью документировать API только через имена методов и сигнатуры типов. Используйте doc-комментарии для любой дополнительной неочевидной информации, которую должен знать пользователь. Взять хотя бы документацию по API из DateTime.AddMonths()BCL:

Метод AddMonths вычисляет итоговый месяц и год с учетом високосных годов и количества дней в месяце, а затем корректирует дневную часть результирующего объекта DateTime. Если результирующий день не является действительным днем ​​в результирующем месяце, используется последний действительный день результирующего месяца. Например, 31 марта + 1 месяц = ​​30 апреля. Часть времени дня в результирующем объекте DateTime остается такой же, как этот экземпляр.

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


Встроенные комментарии тоже неплохие.

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

// increment x by one
x++;

Комментарии, которые объясняют что-то, что можно прояснить, переименовывая переменную или метод или иным образом реструктурируя код, являются запахом кода:

// data1 is the collection of tasks which failed during execution
var data1 = getData1();

Вот такие комментарии Мартин против. Комментарий является признаком невозможности написания понятного кода - в этом случае использовать понятные имена для переменных и методов. Сам комментарий, конечно, не проблема, проблема в том, что нам нужен комментарий, чтобы понять код.

Но комментарии должны использоваться для объяснения всего, что не очевидно из кода, например, почему код написан определенным неочевидным способом:

// need to reset foo before calling bar due to a bug in the foo component.
foo.reset()
foo.bar();

Комментарии, которые объясняют, что делает излишне запутанный фрагмент кода, также являются запахом, но исправление не должно запрещать комментарии, исправление - это исправление кода! На самом деле, запутанный код действительно существует (надеюсь, только временно, пока не произойдет рефакторинг), но ни один обычный разработчик не пишет идеально чистый код с первого раза. Когда происходит запутанный код, гораздо лучше написать комментарий, объясняющий, что он делает, чем не писать комментарий. Этот комментарий также облегчит рефакторинг позже.

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

JacquesB
источник
13
Там также тот случай , когда ваш код обрабатывает ситуацию , которая просто является сложным, и не простой код не может справиться с этим.
gnasher729
6
Хороший вопрос, скучно. Это часто случается, когда вам приходится оптимизировать часть кода для повышения производительности.
JacquesB
9
Даже комментарий x++может быть хорошим, если это что-то вроде «увеличение х на единицу, обтекание, если это UINT32_MAX»; Любой, кто знает спецификацию языка, знал бы, что инкремент uint32_tзаворачивания будет увеличиваться , но без комментария можно не знать, была ли такая упаковка ожидаемой частью реализуемого алгоритма.
суперкат
5
@ l0b0: надеюсь, ты шутишь!
JacquesB
9
@ l0b0 Временного кода не существует. Код никогда не подвергается рефакторингу, потому что бизнес был доволен результатом и не одобрит финансирование для его исправления. Через пять лет какой-нибудь младший разработчик увидит этот код, вы даже не используете WizBug 4.0, поскольку заменили его на Bugtrocity v9, поэтому «Bug123» для него ничего не значит. Теперь он думает, что таким должен быть постоянный код, и продолжает быть ужасным разработчиком всю свою карьеру. Подумай о детях. Не пишите временный код.
CorsiKa
36

Существует разница между комментированием вашего кода и документированием вашего кода .

  • Комментарии необходимы для поддержки кода позже, то есть для изменения самого кода.

    Комментарии действительно могут восприниматься как проблемные. Крайняя точка зрения - сказать, что они всегда указывают на проблему, либо внутри вашего кода (код слишком сложен для понимания), либо внутри языка (язык не может быть достаточно выразительным; например, тот факт, что метод никогда не возвращает, nullможет быть выражен через контракты кода в C #, но нет способа выразить это через код, скажем, в PHP).

  • Документация необходима для использования разработанных вами объектов (классов, интерфейсов). Целевая аудитория другая: мы говорим здесь не о тех, кто будет поддерживать ваш код и изменять его, а о тех, кому его нужно использовать .

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

Арсений Мурзенко
источник
Да, но, по крайней мере, часть идеи Мартина заключается в том, что при современных методах разработки тесты - это документация, а не сам код. Предполагая, что код тестируется с помощью тестовой системы в стиле BDD, например, specflow, сами тесты представляют собой непосредственно читаемое описание поведения метода («если дана база данных продуктов, когда GetById вызывается с идентификатором действительного продукта, то соответствующий объект Product возвращается [...], когда GetById вызывается с неверным идентификатором продукта, затем возвращается null "или что-то в этом роде).
Жюль
13

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

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

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

Так что твой коллега совершенно не прав. И продолжайте читать все книги, но подумайте сами.

PS. Я видел вашу фразу: «иногда это часть интерфейса, поэтому вы даже не знаете, какой код выполняется». Даже с помощью виртуальных функций вы не знаете, какой код выполняется. Хуже того, если вы написали абстрактный класс, даже кода не будет! Поэтому, если у вас есть абстрактный класс с абстрактной функцией, комментарии, которые вы добавляете к абстрактной функции, являются единственной вещью, которой должен руководствоваться разработчик конкретного класса. Эти комментарии также могут быть единственной вещью, которой могут руководствоваться пользователи класса, например, если у вас есть только абстрактный класс и фабрика, возвращающая конкретную реализацию, но вы никогда не увидите никакого исходного кода реализации. (И, конечно, я не должен смотреть на исходный код одной реализации).

gnasher729
источник
Я не комментировал код в 10 лет. Комментарии вздуты, фигня. Никто не комментирует код в эти дни. Мы концентрируемся на правильно сформированном и именованном коде, небольших модулях, развязке и т. Д. Это делает ваш код читабельным, а не комментариями. Тесты гарантируют, что если вы выбрасываете код, то ничего не происходит неправильно, а не комментарии. Тесты расскажут вам, как вы используете код, который вы пишете, как вы его называете, и почему они там находятся. Ты слишком старая школа, тебе нужно учиться тестированию и чистому коду, мой друг.
PositiveGuy
12

Есть два типа комментариев: те, которые видны людям с кодом, и те, которые используются для создания документации.

Тип комментария, на который ссылается дядя Боб, - это вид, который виден только людям с кодом. То, что он защищает, является формой СУХОГО . Для человека, который просматривает исходный код, исходный код должен быть необходимой документацией. Даже в случае, когда люди имеют доступ к исходному коду, комментарии не всегда плохие. Иногда алгоритмы сложны, или вам нужно понять, почему вы используете неочевидный подход, чтобы другие не заканчивали тем, что ломали ваш код, если пытались исправить ошибку или добавить новую функцию.

Комментарии, которые вы описываете, являются документацией API. Это вещи, которые видны людям, использующим вашу реализацию, но которые могут не иметь доступа к вашему исходному коду. Даже если они имеют доступ к вашему исходному коду, они могут работать с другими модулями и не смотреть на ваш исходный код. Этим людям было бы полезно иметь эту документацию доступной в их IDE, когда они пишут свой код.

Томас Оуэнс
источник
Честно говоря, я никогда не задумывался о применении DRY к коду + комментариям, но это имеет смысл. Вроде как пример "приращения X" в ответе @ JacquesB.
7

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

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary>

По стоимости и стоимости мы видим три вещи:

  1. Retrieves a product by its idповторяет то, что говорит название функции, так что это стоимость без значения. Это должно быть удалено.

  2. returns null if no product was foundэто очень ценная информация. Это, вероятно, уменьшает время, которое другие кодировщики должны будут смотреть на реализацию функции. Я совершенно уверен, что это экономит больше чтения, чем стоимость чтения, которую он представляет сам. Это должно остаться.

  3. Линии

    /// <summary>
    /// </summary>
    

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

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


Наблюдение, которое я не нашел ни в одном из других ответов:

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

//XXX: The obvious way to do this would have been ...
//     However, since we need this functionality primarily for ...
//     doing this the non-obvious way of ...
//     gives us the advantage of ...

Скорее всего, много текста, совершенно ненужного для понимания / использования кода. Однако это объясняет причину, по которой код выглядит так, как он выглядит. Это остановит людей, которые смотрят на код, удивятся, почему это не сделано очевидным образом, и начнет рефакторинг кода, пока они не поймут, почему код был написан именно так. И даже если читатель достаточно умен, чтобы не переходить к рефакторингу напрямую, ему все равно нужно выяснить, почему код выглядит так, как он это делает, прежде чем он поймет, что лучше всего оставаться таким, какой он есть. Этот комментарий может буквально сэкономить часы работы. Таким образом, стоимость выше, чем стоимость.

Кроме того, комментарии могут сообщать о намерениях кода, а не только о том, как он работает. И они могут нарисовать большую картину, которая обычно теряется в мельчайших деталях самого кода. Таким образом, вы правы, выступая в пользу комментариев класса. Я больше всего ценю комментарии класса, если они объясняют намерение класса, как он взаимодействует с другими классами, как его следует использовать и т. Д. Увы, я не большой автор таких комментариев ...

cmaster
источник
2
Ничего себе - изменить ваш генератор документов, потому что он требует несколько дополнительных строк HTML для анализа? Давай не будем
CorsiKa
2
@corsiKa YMMV, но я бы предпочел генератор документации, который сводит затраты в комментариях к минимуму. Конечно, я также предпочел бы прочитать хорошо написанный заголовочный файл, чем документацию по Doxygen, которая не синхронизирована с реальным кодом. Но, как я уже сказал, YMMV.
Мастер
4
Даже если имя метода блестяще описывает его назначение, повторение этой цели с использованием естественного языка может облегчить кому-то, читающему его, ассоциировать эту цель с любыми оговорками, которые следуют. Перефразирование того, что описано в названии, будет достаточно кратким, что, даже если значение низкое, стоимость также будет низкой. Поэтому я не согласен с первой частью вашего поста. +1, однако, для второй части. Документирование альтернативных подходов, которые были оценены и отклонены, может быть чрезвычайно полезным, но такой информации редко уделяется внимание, которого она заслуживает.
суперкат
GetByIdставит вопрос, что такое id, а также, что и откуда. Комментарии к документации должны позволять среде разработки отображать ответы на эти вопросы. Если это не будет объяснено где-либо еще в комментариях к документу модуля, это также будет одно место, чтобы сказать, почему в любом случае можно получить идентификатор.
Хайд
Комментарии дуют, чистый код (самоописание), TDD (частая обратная связь и частая обратная связь с вашим дизайном) и тесты (дают вам уверенность и поведение документа)! ИСПЫТАНИЯ людей ИСПЫТАНИЯ. Никто здесь не говорит об этом. проснись
PositiveGuy
4

Некомментированный код - это плохой код. Это широко распространенный (если не универсальный) миф о том, что код может читаться почти так же, как, скажем, английский. Это нужно интерпретировать и для любого, кроме самого тривиального кода, который требует времени и усилий. Плюс ко всему, у каждого разный уровень возможностей как в чтении, так и в написании любого языка. Различия между авторским и читательским стилями и возможностями кодирования являются сильными барьерами для точной интерпретации. Это также миф, что вы можете извлечь намерение автора из реализации кода. По моему опыту, это редко неправильно добавлять дополнительные комментарии.

Роберт Мартин и соавт. Считайте это "неприятным запахом", потому что может быть, что код изменен, а комментарии - нет. Я говорю, что это хорошо (точно так же, как «плохой запах» добавляется к бытовому газу, чтобы предупредить пользователя об утечках). Чтение комментариев даст вам полезную отправную точку для интерпретации реального кода. Если они совпадают, у вас будет повышенная уверенность в коде. Если они различаются, значит, вы обнаружили предупреждающий запах, и вам необходимо провести дальнейшее расследование. Лекарство от "неприятного запаха" - это не устранение запаха, а устранение утечки.

Винс О'Салливан
источник
2
Учитывая, что вы умный автор, а текст предназначен для интеллектуальной аудитории; Вы рисуете линию, используя здравый смысл. Очевидно, что в нынешнем виде пример глуп, но это не значит, что не может быть очень веской причины для пояснения с комментарием, почему код включает i ++ в этот момент.
Винс О'Салливан
8
i++; // Adjust for leap years.
Винс О'Салливан
5
«Роберт Мартин и др. Считают это« неприятным запахом », потому что может случиться так, что код изменился, а комментарии нет». Это только часть запаха. Наихудший запах исходит от идеи, что программист решил не пытаться писать код более наглядным способом, а вместо этого решил «закрыть утечку» комментарием. Он утверждает, что вместо того, чтобы шлепать комментарий «// поправить на високосные годы», в самом коде, вероятно, следует использовать метод «AdjustForLeapYears ()» (или что-то подобное). Документация поставляется в форме тестов, которые осуществляют логику високосного года.
Эрик Кинг,
3
Я хотел бы рассмотреть возможность добавления вызова метода для замены одной строки кода излишним комментарием, особенно потому, что имя метода на самом деле является просто комментарием, который помечает фрагмент кода и не гарантирует лучшую точность документации. (Если бы эта строка встречалась в двух или более местах, то введение вызова метода, конечно, было бы совершенно правильным решением.)
Винс О'Салливан
1
@Jay Причина в том, что сделать ваши абстракции явными (например, путем введения методов) - это правило. Не делать этого, потому что вы можете получить метод с одной строкой - исключение. Позвольте мне перефразировать настоящее произвольное правило: «Используйте структуры вашего языка программирования (обычно методы и классы) для введения абстракций, если реализация этой абстракции не может быть выражена в виде одной строки кода, в этом случае укажите абстракцию на естественном языке , добавив комментарий."
Эрик
3

В некоторых языках (например, F #) весь этот комментарий / документация фактически может быть выражена в сигнатуре метода. Это связано с тем, что в F # значение null, как правило, не является допустимым значением, если оно не разрешено специально.

В F # (а также в некоторых других функциональных языках) распространено то, что вместо нуля вы используете тип опции, Option<T>который может быть Noneлибо Some(T). Затем язык поймет это и заставит вас (или предупредит вас, если вы этого не сделаете) в обоих случаях, когда вы попытаетесь его использовать.

Так, например, в F # вы можете иметь подпись, которая выглядит следующим образом

val GetProductById: int -> Option<Product>

И тогда это будет функция, которая принимает один параметр (int) и затем либо возвращает продукт, либо значение None.

И тогда вы могли бы использовать это так

let product = GetProduct 42
match product with
| None -> printfn "No product found!"
| Some p -> DoThingWithProduct p

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

Конечно, это требует, чтобы ваш язык был спроектирован таким образом, чего нет у многих распространенных языков, таких как C #, Java, C ++ и т. Д. Так что это может быть не полезно для вас в вашей текущей ситуации. Но (надеюсь) приятно знать, что существуют языки, которые позволяют вам выражать такую ​​информацию статически, без комментариев и т. Д. :)

wasatz
источник
1

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

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

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

Одна из них заключается в том, что язык может не предоставлять возможности для документирования того, что должно быть задокументировано четко и кратко. Поскольку компьютерные языки улучшаются, это становится все меньше и меньше проблемой. Но я не думаю, что это полностью прошло. В те дни, когда я писал на ассемблере, имело смысл добавить такой комментарий, как «общая цена = цена необлагаемых налогом предметов плюс цена облагаемых налогом предметов плюс цена облагаемых налогом предметов * ставка налога». То, что было в реестре в любой момент, не обязательно было очевидно. Потребовалось много шагов, чтобы сделать простую операцию. И т.д. Но если вы пишете на современном языке, такой комментарий будет просто повторением одной строки кода.

Я всегда раздражаюсь, когда вижу комментарии типа «x = x + 7; // добавляем 7 к x». Как, вау, спасибо, если бы я забыл, что означает знак плюс, который мог бы быть очень полезным. В действительности я могу запутаться, зная, что такое «х» или почему нужно было добавить 7 к нему в это конкретное время. Этот код можно сделать самодокументированным, если дать более значимое имя для «x» и использовать символическую константу вместо 7. Как если бы вы написали «total_price = total_price + MEMBERSHIP_FEE;», тогда комментарий, вероятно, вообще не нужен ,

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

Но на практике для имени функции часто невозможно полностью описать, что делает функция, без имени функции, если код, составляющий эту функцию. Собирается ли название сообщить нам, какие проверки выполняются по всем параметрам? Что происходит при исключительных условиях? Разобрать все возможные двусмысленности? В какой-то момент имя станет настолько длинным, что станет просто запутанным. Я бы принял String BuildFullName (имя строки, имя строки) в качестве приличной сигнатуры функции. Несмотря на то, что в нем не указано, указано ли имя «первый последний» или «последний, первый» или какой-либо другой вариант, что он делает, если одна или обе части имени не заполнены, если оно накладывает ограничения на общую длину и что он делает, если это превышено,

сойка
источник