Почему НЕ используйте опции в Swift?

Я читал о том, как программировать на Swift, и меня немного беспокоила концепция необязательных параметров. Не совсем с точки зрения того, зачем использовать опции, это имеет смысл, а скорее с точки зрения того, в каком случае вы не захотите использовать опции. Насколько я понимаю, необязательный параметр просто позволяет обнулить объект, так почему бы вам не захотеть использовать эту функцию? Разве установка объекта на nil не означает, что вы говорите ARC освободить объект? И разве большинство функций в Foundation и Cocoa не возвращают опции? Итак, помимо необходимости вводить дополнительный символ каждый раз для ссылки на объект, есть ли веская причина НЕ использовать необязательный тип вместо обычного?


person Keveloper    schedule 27.06.2014    source источник
comment
почему бы вам не захотеть эту функцию? Послушайте Тони Хоара. Вы также можете узнать кое-что об истории CS, что важнее, чем вы думаете.   -  person    schedule 27.06.2014
comment
Дело не обязательно в том, чтобы избегать нулевых значений где-либо в коде, а в том, чтобы более четко указать, где именно в коде вы знаете, что значения не могут быть нулевыми.   -  person jtbandes    schedule 27.06.2014
comment
Разве установка объекта на nil не означает, что вы указываете ARC освободить объект? Это один из способов освободить объект, но далеко не единственный. И обычно это не нужно.   -  person rickster    schedule 28.06.2014


Ответы (2)


Есть множество причин, по которым НЕ следует использовать option. Основная причина: вы хотите показать, что значение ДОЛЖНО быть доступно. Например, когда вы открываете файл, вы хотите, чтобы имя файла было строкой, а не дополнительной строкой. Использование nil в качестве имени файла просто не имеет смысла.

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

Для аргументов функции справедливо следующее: Если аргумент должен быть предоставлен, option не следует использовать. Если передача ничего допустима и является допустимым (задокументированным!) вводом, то передайте необязательный.

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

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

На самом деле, большинству API лучше использовать необязательные, а не необязательные параметры. В большинстве случаев просто передавать/получать, возможно, ничего — это не то, что вам нужно. Есть довольно мало случаев, когда ничего не вариант.

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

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

Но будьте осторожны!

Мой ответ может звучать так, как будто концепция необязательных параметров довольно дерьмовая. Все наоборот! Имея такую ​​​​концепцию, как опции, программист может объявить, допустимо ли ничего не передавать/не возвращать. Вызывающий функцию всегда знает об этом, и компилятор обеспечивает безопасность. Сравните это со старым добрым C: вы не могли объявить, может ли указатель быть null. Вы можете добавить комментарии к документации, которые указывают, может ли это быть null, но компилятор не навязывает такие комментарии. Если вызывающая сторона забыла проверить возвращаемое значение на null, вы получили segfault. С опционами вы можете быть уверены, что никто больше не будет разыменовывать указатель null.

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

person gexicide    schedule 27.06.2014
comment
На самом деле я могу привести примеры, когда передача nil в качестве имени файла имеет смысл, например, вам нужен временный файл, и вам все равно, как его зовут :) В общем, ваш ответ точен. - person David Berry; 27.06.2014
comment
@David: Конечно, всегда могут быть такие случаи, когда ничего не имеет особого значения. Тогда опционально все в порядке. Однако часто бывает наоборот. - person gexicide; 27.06.2014

Первоначальная идея опционалов (которая существовала задолго до Swift) состоит в том, чтобы заставить программиста проверять значение на nil перед его использованием — или предотвратить передачу nil внешним кодом там, где это не разрешено. Огромная часть сбоев в программном обеспечении, может быть, даже большинство из них, происходит по адресу 0x00000000 (или с NullPointerException, или подобным) именно потому, что слишком легко забыть о сценарии с нулевым указателем. (В 2009 году Тони Хоар извинился за изобретение нулевых указателей).

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

Но в настоящее время существующие фреймворки написаны на Obj-C без учета опций, поэтому автоматически генерируемые мосты между Swift и Obj-C просто должны принимать и возвращать опции, потому что невозможно автоматически глубоко проанализировать каждый метод и выяснить, какие аргументы и возвращаемые значения должны быть необязательными или нет. Я уверен, что со временем Apple вручную исправит каждый случай, когда они ошиблись; прямо сейчас вы не должны использовать эти фреймворки в качестве примера, потому что они определенно не очень хороши. (В качестве хороших примеров вы можете проверить популярный функциональный язык, такой как Haskell, в котором с самого начала были необязательные параметры).

person hamstergene    schedule 27.06.2014