Быть либеральным в том, что вы принимаете ... или нет?

45

[Отказ от ответственности: этот вопрос субъективен, но я бы предпочел получать ответы, подкрепленные фактами и / или размышлениями]

Я думаю, что все знают о принципе робастности , обычно описываемом законом Постеля:

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

Я согласен, что для разработки широко распространенного коммуникационного протокола это может иметь смысл (с целью обеспечения легкого расширения), однако я всегда думал, что его применение к HTML / CSS было полным провалом, каждый браузер реализовывал свой собственный бесшумный твик обнаружение / поведение, делающее практически невозможным получение согласованного рендеринга в нескольких браузерах.

Однако я замечаю, что в этом документе RFC протокола TCP считается допустимым «Silent Failure», если не указано иное ... что, по меньшей мере, является интересным поведением.

Существуют и другие примеры применения этого принципа в торговле программными продуктами, которые регулярно появляются, потому что они укусили разработчиков с головы до головы:

  • Вставка точек с запятой в Javascript
  • C (тихие) встроенные преобразования (что было бы не так плохо, если бы они не усекались ...)

и есть инструменты, помогающие реализовать «умное» поведение:

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

  • несколько субъективно, угадывает ли алгоритм «правильно», и поэтому он может идти вразрез с принципом наименьшего удивления
  • это делает реализацию более трудной, таким образом, больше шансов ввести ошибки (нарушение YAGNI ?)
  • это делает поведение более восприимчивым к изменению, поскольку любая модификация процедуры «угадай» может сломать старые программы, почти исключая возможности рефакторинга ... с самого начала!

И это то, что привело меня к следующему вопросу:

При проектировании интерфейса (библиотеки, класса, сообщения) вы склоняетесь к принципу надежности или нет?

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

Матье М.
источник
Интересно, в чем разница между HTML и общими данными? Принцип надежности - это общение. Один пишет - один читает. Почему сетевое общение отличается от визуального или API? У меня есть пример API, где принцип либеральности при принятии того, что мы принимаем, упрощает жизнь пользователей, которые являются программистами , уменьшает размер кода и, следовательно, улучшает производительность + устраняет ошибки. Посмотрите stackoverflow.com/questions/18576849
Val
@Val: на самом деле, ваш пример не совпадает. «быть либеральным в том, что вы принимаете» - это не просто вопрос основ / производных, это выход за рамки этого, а также принятие (и интерпретация) слегка ошибочных входных данных.
Матье М.
Как показ некоторых случаев не показывает этот случай?
Val

Ответы:

34

Я бы сказал, надежность, когда это не вносит двусмысленности .

Например: при разборе списка через запятую наличие или отсутствие пробела до / после запятой не меняет смысловой смысл.

При разборе строки guid он должен принимать любое количество распространенных форматов (с или без черточек, с или без окружающих фигурных скобок).

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

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

Davy8
источник
1
Я согласен, надежность, когда она не стоит дорого, стоит того.
Матье М.
2
Даже разделенный запятыми список вызывает проблемы, вроде: движок javascript в chrome и firefox, кажется, принимает {"key": "value",}как действительный, а IE - нет. Я часто сталкивался с этой конкретной проблемой, пока не улучшил процесс сборки с помощью JSlint.
Кепла
2
@keppla это проблемы с реализацией, а не дизайном. Я не уверен, допустимо ли это согласно спецификации javascript, и IE не следует за ним, или это «хорошая функция», добавленная FF и Chrome, но в Python она указана, чтобы быть действительной и реализованной как таковая. Если он указан как действительный, и он не работает, то это ошибочная реализация. Если он не указан, то на него не следует полагаться (хотя с практической точки зрения, если он не работает в главном браузере, его также можно рассматривать как не в спецификации, если вы не контролируете пользователя)
Davy8
7
@ Davy8: завершающая запятая, похоже, незаконна ( stackoverflow.com/questions/5139205/… ). Я не хочу полагаться на это, моя точка зрения такова, что когда достаточное количество людей принимает ввод, он становится де-факто стандартом (потому что никто не замечает, что это ошибка), что приводит к чему-то, с чем мы столкнулись в HTML: что ошибки стать настолько обычным делом, что вы не можете больше игнорировать их как плохой вклад.
Кепла
1
@keppla, это должно быть не в moz и Chrome. Будучи в первую очередь разработчиком JS, меня это бесит (как раньше в Moz). Это делает отладку сложнее, а не проще. IE делает то, что должен. Fail @ плохой код. HTML это одно. Нам не нужно это дерьмо на языке сценариев. Это пример ужасного применения принципа Robust, в котором производители браузеров преуспевают.
Эрик Реппен
15

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

Чрезвычайно недооцененный Написание твердого кода было огромным, поскольку он неоднократно подчеркивал необходимость и методы, позволяющие делать ошибки как трудно вводить или скрывать. Благодаря применению таких принципов, как «Устранить случайное поведение. Принудительно воспроизводить ошибки». и «Всегда ищите и устраняйте недостатки в ваших интерфейсах». Разработчики значительно улучшат качество своего программного обеспечения, устраняя неоднозначность и неконтролируемые побочные эффекты, которые являются причиной большого количества ошибок.

Huperniketes
источник
9

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

Чрезмерное применение правильности приводит к тому, что вы отказываете своим клиентам в праве совершать незначительные ошибки, и это нормально, пока они не пожалуются, что их материалы отлично работают на продукт вашего конкурента, и не скажут вам, что можно сделать с помощью стандарта на 5000 страниц, в котором есть слово. «ПРОЕКТ» все еще нацарапан на обложке карандашом, и, по крайней мере, 3 эксперта утверждают, что в корне ошибочны, и еще 200 честных экспертов говорят, что они не до конца понимают.

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

deworde
источник
+1 за амортизацию , это действительно важная концепция, и я удивлен, что до сих пор ее не замечали.
Матье М.
9

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

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

ThomasX
источник
Цитирую себя (должно быть, старею): «Однако я всегда думал, что его применение к HTML / CSS было полным провалом»
Matthieu M.
3
Правда, но такая же отказоустойчивость также помогла сделать Интернет таким популярным.
MaR
Поставщики браузеров не смогли на этом. В случае с типами документов у нас была возможность сделать свой собственный выбор в этом отношении, но в конце дня все в значительной степени вело себя так же, как если бы вы объявили какой-либо тип документа. Теперь они думают, что решение представляет собой сверхсложный набор строгих правил, которым необходимо следовать в отношении того, как бороться с неудачей? Я думаю, что они не могут определить проблему.
Эрик Реппен
Вы говорите, что fail-fast, который противоположен «здравому», более эффективен.
Val
@MaR: это так? Очень спорный, гораздо более вероятно, что особенности были важны.
Дедупликатор
6

Я делю интерфейсы на несколько групп (добавьте больше, если хотите):

  1. те, что находятся под вашим контролем, должны быть строгими (обычно классы)
  2. библиотечные API, которые также должны быть строгими, но рекомендуется дополнительная проверка
  3. общедоступные интерфейсы, которые должны обрабатывать все виды злоупотреблений (обычно протоколы, пользовательские вводы и т. д.). Здесь надежность ввода действительно окупается, вы не можете ожидать, что все исправят свои проблемы. И помните, что для пользователя это будет ваша вина, если приложение не будет работать, а не сторона, отправившая какую-то плохо отформатированную чушь.

Вывод всегда должен быть строгим.

MaR
источник
5

Я думаю, что HTML и Всемирная паутина обеспечили широкомасштабную проверку принципа надежности в реальном мире и показали, что это огромный провал. Он несет прямую ответственность за запутанный беспорядок конкурирующих почти стандартов HTML, который делает жизнь веб-разработчиков (и их пользователей) несчастной и ухудшается с каждым новым выпуском Internet Explorer.

Мы знаем с 1950-х годов, как правильно проверять код. Запустите его через строгий анализатор и, если что-то не так синтаксически правильно, выдайте ошибку и прервите работу. Не проходите мимо, не собирайте 200 долларов, и ради любви ко всему двоичному не позволяйте какой-нибудь компьютерной программе пытаться прочитать мысли кодера, если он допустил ошибку!

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

Мейсон Уилер
источник
4
@ChaosPandion: проблема не в самом Internet Explorer, я думаю, а во всех нестандартных веб-страницах, которые были приняты в предыдущих версиях и с которыми теперь все должны жить ... и пытаются более или менее успешно разместить их.
Матье М.
5
Я действительно думаю, что команда IE находится в худшем положении из всех разработчиков браузеров. Джоэл довольно мило подводит итог моих мыслей .
Дин Хардинг
3
Возможно, это сделало жизнь разработчиков и дизайнеров несчастной, но тогда мы застряли бы в очень медленно развивающемся и статичном стандарте - я сомневаюсь, что сеть будет такой, как сейчас. Настоящими победителями стали люди, просматривающие Интернет, а в конце концов - люди, которые считают.
FinnNk 30.10.10
4
Кроме того, хотя принцип робастности может усложнить жизнь веб-разработчикам, трудно назвать Всемирную паутину (которая сейчас является неотъемлемой частью почти каждого крупного учреждения на планете) огромным провалом .
deworde
3
«Мы знаем с 1950-х годов, как правильно проверять код. Запустите его через строгий синтаксический анализатор, и если что-то не будет синтаксически правильным, выдайте ошибку и прервите». Чтобы применить это к реальному сценарию: если я ввернул одну иконку в правом нижнем углу моей страницы чуть ниже обрезки, то отказ от всей страницы - это действительно хороший способ отправить кого-то, ищущего в другом месте, из-за проблема, которую они бы даже не заметили. Да, вы можете утверждать, что я не должен был ошибиться. Но это скорее предполагает, что я еще не пошел к вашему более сильному конкуренту и больше не отвечаю на ваши звонки.
deworde
3

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

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

В Jargon File также есть страшная история о «угадывании» намерений пользователя.

Фрэнк Шиарар
источник
Очень забавная история :) Я понимаю, что вам может понадобиться больше свободы, когда вы пытаетесь взаимодействовать с существующими системами, так как если это не сработает, вас обвинят.
Матье М.
На самом деле, если ваш телефон не работает с большинством других телефонов, он плохой .
SamB
1
@SamB: Заменить плохо с сломаны .
deworde
3

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

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

Кроме того, я бы предположил, что «тихий сбой» разрешен в протоколе TCP, потому что в противном случае, если люди будут бросать вам некорректные пакеты, вы будете засыпаны сообщениями об ошибках. Это простая защита от DoS.

Примечание для себя - придумай имя
источник
1
«Если вы сделаете опечатку во время программирования, вы получите ошибку, как только вы скомпилируете» Я представляю вам миллионы ПРЕДУПРЕЖДЕНИЙ компилятора, которые будет выплевывать стандартный компилятор, в то же время выполняя идеально исполняемые задачи.
deworde
1

ИМО, надежность - это одна из сторон компромисса между проектами, а не принцип «предпочтения». Как уже отмечали многие, ничто не воняет, как четыре часа, пытаясь выяснить, где ваш JS пошёл не так, только чтобы обнаружить реальную проблему - только один браузер правильно сделал с XHTML Strict. Она позволяла странице разбиваться на части, когда какая-то часть обслуживаемого HTML была полной катастрофой.

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

Или вы можете внести гибкость в процесс, передав список литералов объектов / словарь / ключ-значение и обрабатывая существование каждого аргумента по мере его поступления. Для очень незначительного перфокарта, это пирог и есть его тоже сценарий.

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

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

Попытка предоставить функциональность 2010 в браузере 1999 года, когда вы могли просто предоставить более низкую техническую страницу, является еще одним примером безрассудного компромисса дизайна. Потраченные возможности и деньги, которые я видел, были потрачены впустую на время разработчиков, потраченное на обходные пути, связанные с ошибками, просто чтобы получить закругленные углы на элементе, парящем, например, над градиентным фоном! @ # $, Полностью потряс меня. И для чего? Предоставлять высокотехнологичные страницы, которые плохо работают с проверенными технофобами, ограничивая при этом выбор в браузерах более высокого уровня

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

Эрик Реппен
источник
4
«для метода, который принимает 20 аргументов»> нет необходимости искать дальше, после 5/6 метод неправильный . Спасибо за ответ, хотя :)
Матье М.
1

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

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

  1. Ваша библиотека должна быть спроектирована немного по-другому (переименовать некоторую функцию или разделить ее на две части), чтобы пользователь мог ожидать того, что вы фактически предоставляете.
  2. Если вы считаете, что ваша библиотека спроектирована правильно, что означает четкое / простое именование, вы можете попытаться сделать вывод, что задумал пользователь.

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

Когда имеешь дело с конечным пользователем, попытка исправить его ввод / предположение очень приветствуется. Он ожидается ввести неверную информацию; этот случай совершенно исключительный. Другой разработчик, однако, не простой не технический пользователь. У него есть опыт, чтобы понять ошибку, и ошибка может иметь значение / быть полезной для него. Таким образом, я согласен с вами в разработке строгих API, хотя, конечно же, строгость сопровождается ясностью и простотой.

Я бы порекомендовал вам прочитать этот вопрос моего аналогичного случая.

К. Гкинис
источник