あなたが受け入れることについてリベラルであるかどうか…?


45

[免責事項:この質問は主観的ですが、事実や反射によって裏付けられた回答を得ることを希望します]

誰もがロバストネスの原則について知っていると思いますが、通常はポステルの法則によって要約されます:

送信する内容には慎重になります。あなたが受け入れるものに寛大であること。

普及している通信プロトコルの設計では、これは理にかなっているかもしれません(簡単に拡張できるようにすることを目標としています)が、HTML / CSSへのアプリケーションは完全に失敗し、各ブラウザが独自のサイレント調整を実装していると常に考えていました検出/動作。複数のブラウザで一貫したレンダリングを取得することはほぼ不可能です。

ただし、TCPプロトコルのRFCでは、特に明記されていない限り、「サイレント障害」を許容できると考えています。これは、控えめに言っても興味深い動作です。

ソフトウェアトレード全体でこの原則が適用されている他の例があります。開発者に噛み付いたために、頭の一番上から定期的に表示されます。

  • Javascriptセミコロン挿入
  • C(サイレント)組み込み変換(切り捨てられなかった場合はそれほど悪くないでしょう...)

「スマート」動作の実装を支援するツールがあります。

しかし、このアプローチは、技術に詳しくないユーザーを扱う場合やエラー回復のプロセスでユーザーを支援する場合には役立つかもしれませんが、ライブラリ/クラスインターフェースの設計に適用するといくつかの欠点があることがわかります。

  • アルゴリズムが「正しい」と推測するかどうかはやや主観的であるため、最小驚きの原則に反する可能性があります。
  • 実装がより難しくなり、バグを導入する機会が増えます(YAGNIの違反?)
  • 「推測」ルーチンを変更すると古いプログラムが破損する可能性があり、リファクタリングの可能性をほぼ最初から除外するため、動作が変更されやすくなります。

そして、これが私を次の質問へと導いたものです。

インターフェイス(ライブラリ、クラス、メッセージ)を設計するとき、堅牢性の原則に傾いていますか?

私自身は非常に厳しい傾向があり、インターフェイスで広範な入力検証を使用しています。


HTMLと一般データの違いは何ですか?堅牢性の原則は、通信に関するものです。1つの書き込み-1つの読み取り。ネットワーク通信がビジュアルまたはAPIと異なるのはなぜですか?私が受け入れるものに寛大であるという原則がプログラマーであるユーザーの生活を簡素化し、コードサイズを減らし、したがってパフォーマンスを改善し、バグを排除するAPIの例を持っています。ルックstackoverflow.com/questions/18576849
ヴァル

@Val:実際には、あなたの例は一致しません。「あなたが受け入れるものに寛容であること」は、単にベース/派生の問題ではなく、それを超えて、わずかに誤った入力を受け入れます(そして解釈します)。
マチューM.

いくつかのケースを表示しても、そのケースは表示されませんか?
ヴァル

回答:


34

あいまいさが生じない場合、堅牢性と言います

例:コンマ区切りリストを解析する場合、コンマの前後にスペースがあるかどうかは意味的な意味を変更しません。

文字列GUIDを解析する場合、任意の数の一般的な形式(ダッシュの有無にかかわらず、中括弧の有無にかかわらず)を受け入れる必要があります。

ほとんどのプログラミング言語は、ホワイトスペースを使用して堅牢です。特に、コードの意味に影響を与えないすべての場所。空白が関係するPythonでさえ、リストや辞書の宣言の中にいれば柔軟です。

何かを複数の方法で解釈できる場合、または何を意味するのかが100%明確でない場合、堅牢性が大きすぎると痛みになりますが、曖昧にならずに堅牢性を確保する余地が十分にあることは間違いありません。


1
コストがかからないときの堅牢性は価値があると思います。
マシューM.

2
コンマ区切りのリストでさえ問題を引き起こします。たとえば、chromeとfirefoxのjavascriptエンジンは{"key": "value",}有効であるように見えますが、IEはそうではありません。JSlintでビルドプロセスを改善するまで、私はこの特定の問題にしばしば出くわしました。
ケプラ

2
@kepplaは、設計ではなく実装の問題です。それがjavascript仕様で合法でIEが従わないのか、それがFFとChromeが追加した「素敵な機能」なのかはわかりませんが、Pythonでは有効であり、そのように実装されるように指定されています。有効と指定されていて、機能しない場合は、実装に問題があります。それが指定されていない場合、それは本当に(実用性の問題として、それは主要なブラウザでの作業をしない場合がユーザーをコントロールしていない場合、それは同様の仕様ではないと考えられるかもしれない)に依存すべきではありません
デービー8

7
@ Davy8:末尾のコンマは違法のようです(stackoverflow.com/questions/5139205/…)。私はこれに頼りたくない、私のポイントは、十分な人々が入力を受け入れると、それが事実上の標準になり(エラーであることに気付かないため)、それがHTMLで遭遇した何かにつながる:エラーあまりにありふれたものになるので、それらを不正な入力として無視することはできなくなります。
ケプラ

1
@keppla、それはmozとChromeで失敗するはずです。主にJS開発者として、そうではないことに腹を立てます(少なくともMozでは慣れていました)。デバッグが難しくなりますが、簡単ではありません。IEは本来の動作をしています。不良コードで失敗します。HTMLは一つのことです。スクリプト言語ではこのがらくたは必要ありません。これは、ブラウザベンダーが得意とする堅牢な原則のひどい適用例です。
エリックReppen

15

絶対にありません。防御的プログラミングなどの技術はバグをあいまいにし、その出現をより少なく、よりランダムにし、検出を困難にし、それらを隔離することをより困難にします。

非常に過小評価されているSolid Codeの作成は、バグの導入や隠蔽を困難にする必要性と手法を繰り返し強調するという点で非常に優れていました。「ランダムな動作を排除します。バグを強制的に再現可能にする」などの原則を適用します。そして、「インターフェースの欠陥を常に探し、排除します。」開発者は、大量のバグの原因となる曖昧さや制御不能な副作用を排除することにより、ソフトウェアの品質を大幅に改善します。


9

ロバストネスの過剰な適用は、ユーザーが何を望んでいたかを推測することにつながります。また、顧客があなたの信頼を乱用せず、たまたま動作するランダムなちらつきを作成しないが、バージョン2ではサポートできないという完全に見当違いの信仰が必要です。

正当性を過剰に適用すると、顧客が軽微なエラーを犯す権利を拒否することになります。これは、競合他社の製品で自分のものがうまく機能することを不平を言うまで問題はなく、5,000ページの標準でできることを教えて「ドラフト」はまだクレヨンの表紙に走り書きされており、少なくとも3人の専門家が根本的に欠陥があると主張しており、200人以上の正直な専門家は完全に理解していないと述べています。

私の個人的な解決策は常に非推奨です。あなたは彼らを支持しますが、彼らが間違っていること、そして(可能であれば)正確さへの最も簡単な道を彼らに伝えてください。そうすれば、バグ機能を10年後に無効にすると、少なくとも「これが起こるかもしれないと警告しました」と書かれた紙の証跡があります。


廃止予定の +1 は確かに重要な概念であり、今まで見過ごされていたことに驚きました。
マチューM.

9

残念ながら、いわゆる「堅牢性の原則」は堅牢性につながりません。例としてHTMLを取り上げます。ブラウザーが不正なコンテンツの意味を推測しようとする代わりに、最初からHTMLを厳密に解析していれば、多くのトラブル、涙、時間とエネルギーの浪費を回避できました。

ブラウザは、裏で修正しようとするのではなく、単にエラーメッセージを表示する必要がありました。それはすべてのバングラーに彼らの混乱を修正することを余儀なくされたでしょう。


(古くなっている必要があります)自分自身を引用:「しかし、私は常にHTML / CSSへの応用は完全な失敗だったと思っている」
マシューM.

3
確かに、同じフォールトトレランスもWebの人気を高めました。
MAR

ブラウザベンダーはその1つで失敗しました。Doctypeを使用すると、この点に関して独自の選択を行うことができましたが、それらの日の終わりには、Doctypeが宣言されている限り、すべてがほぼ同じように動作しました。今、彼らは失敗に対処する方法に関して従うべき厳格なルールの超複雑なセットが解決策だと思いますか?彼らは問題を特定することに失敗していると思います。
エリックReppen

「ロバスト」の反対であるフェイルファストがより効率的であると言っています。
ヴァル

@MaR:そうですか?非常に議論の余地のある、はるかに多くの機能が重要でした。
デデュプリケーター

6

インターフェイスをいくつかのグループに分けます(必要に応じて追加します)。

  1. あなたの管理下にあるものは厳密でなければなりません(通常はクラス)
  2. ライブラリAPIも厳密な側面にあるべきですが、追加の検証が推奨されます
  3. 入ってくるあらゆる種類の不正行為(通常はプロトコル、ユーザー入力など)を処理する必要があるパブリックインターフェイス。ここでは、入力に対する堅牢性が実を結びますが、誰もが自分の問題を修正することは期待できません。そして、ユーザーにとって、アプリケーションが機能しないのはあなたのせいであることを忘れないでください。

出力は常に厳密でなければなりません。


5

HTMLとWorld Wide Webは、ロバストネスの原理の広範囲な実世界テストを提供し、それが大規模な失敗であることを示したと思います。それは、Web開発者(およびそのユーザー)の生活を悲惨にし、新しいInternet Explorerのリリースごとに悪化する、ほぼ標準の競合するHTMLの混乱の混乱に直接責任があります。

1950年代から、コードを適切に検証する方法を知っています。厳密なパーサーで実行し、構文が正しくない場合は、エラーをスローして中止します。合格しないでください、200ドルを集めないでください、そして、バイナリであるすべての愛のために、彼が間違えたならば、いくつかのコンピュータープログラムがコーダーの心を読もうとしないでください!

HTMLとJavaScriptは、これらの原則が無視されたときに何が起こるかを正確に示しています。最善の行動は、彼らの間違いから学び、繰り返さないことです。


4
@ChaosPandion:問題はInternet Explorer自体にあるのではなく、以前のバージョンで受け入れられたすべての非標準のWebページであり、誰もが一緒に暮らす必要があります...
マチューM.

5
実際、IEチームはすべてのブラウザ開発者にとって最悪の立場にいると思います。ジョエルは私の考えをかなりうまくまとめています。
ディーンハーディング

3
それは開発者やデザイナーにとって人生を悲惨なものにしたかもしれませんが、非常にゆっくりと進化し、静的な標準に固執するでしょう-私はそれが今与えられているようなウェブになるとは思いません。本当の勝者はウェブを閲覧している人々であり、結局のところ、彼らは重要な人々です。
FinnNk

4
また、ロバストネスの原則はWeb開発者の生活を困難にする可能性がありますが、World Wide Web(現在、地球上のほとんどすべての主要機関の不可欠な部分)を大失敗と呼ぶことは困難です。
deworde

3
「1950年代以来、コードを適切に検証する方法を知っています。厳密なパーサーを介して実行し、構文が正しくない場合はエラーをスローして中止します。」これを現実世界のシナリオに適用するには:ページの右端でカットのすぐ下に1つのアイコンをねじ込んだ場合、ページ全体をあきらめることは、他の人を他の人に見せるのに本当に良い方法です。彼らは気づいてさえいなかった問題。はい、あなたは私が間違いを犯すべきではなかったと主張することができます。しかし、それはむしろ、私があなたのより強力な競争相手にまだ行っておらず、もはやあなたの電話を受けていないことを前提としています。
deworde

3

メイソンの例の対比として、セッション開始プロトコルでの私の経験は、異なるスタックは関連するRFCを異なるように解釈するが(これはこれまでに書かれたすべての標準で起こると思う)、あなたが受け入れることで(適度に)寛大であること実際に2つのデバイス間で電話をかけることができます。これらのデバイスは、デスクトップ上のソフトウェアとは対照的に、通常の物理的なものであるため、受け入れるものに寛大でなければなりません。さもないと、特定のメーカーの別の電話を呼び出すことができません。それはあなたの携帯電話の見栄えを良くしません!

ただし、ライブラリを作成している場合、複数の関係者が共通の標準を相互に互換性のない方法で解釈するという問題はおそらくないでしょう。その場合、あいまいさを排除するので、あなたが受け入れるものを厳しくする必要があります。

Jargon Fileには、ユーザーの意図を「推測」するという恐ろしい話もあります。


非常に面白い話:)私は、既存のシステムと対話しようとすると、それが動作しない場合ので、あなたは、より多くの余裕を必要とするかもしれないことを認識し、あなたが「非難するでしょう。
マチューM.

実際、お使いの携帯電話が他のほとんどの携帯電話で動作しない場合、お使いの携帯電話は不良です。
-SamB

1
@SamB:badbrokenに置き換えます。
deworde

3

ルールはプロトコルではなくプログラミングに適用されます。プログラミング中にタイプミスをすると、コンパイル(または、これらの動的型の場合は実行)するとすぐにエラーが発生します。コンピューターに推測させることによって得られるものは何もありません。一般の人々とは異なり、私たちはエンジニアであり、私の言うことを正確に言うことができます。;)

したがって、APIを設計するときは、ロバストネスの原則に従わないと言うでしょう。開発者が間違いを犯した場合、彼らはすぐにそれについて知る必要があります。もちろん、APIがファイルのような外部ソースからのデータを使用する場合、寛大でなければなりません。ライブラリのユーザーは自分の間違いについて知る必要がありますが、他の人の間違いについて知るべきではありません。

余談ですが、TCPプロトコルでは「サイレント障害」が許可されていると思います。そうしないと、不正な形式のパケットが投げられた場合、エラーメッセージが殺到するからです。これは単純なDoS保護です。


1
「プログラミング中にタイプミスをすると、コンパイルするとすぐにエラーが発生します」私はあなたに何百万ものコンパイラ警告を提示します。
deworde

1

IMO、堅牢性はデザインのトレードオフの1つの側面であり、「優先」の原則ではありません。多くの人が指摘しているように、XHTML Strictで1つのブラウザーだけが適切な処理を行っていた場合に、実際の問題を発見するためだけに4時間かけてJSがどこを間違えたのかを突き止めるような悪臭はありません。提供されたHTMLの一部が完全な災害であったときに、ページをバラバラにさせました。

一方、20個の引数を取るメソッドのドキュメントを検索し、スキップしたいものの空またはnullの値プレースホルダーとまったく同じ順序であると主張したい人はいますか?その方法に対処する同様に恐ろしい堅牢な方法は、すべての引数をチェックし、相対的な位置と型に基づいてどの引数が何であるかを推測し、無言で失敗するか、意味のない引数で「やらせ」ようとすることです。

または、オブジェクトのリテラル/辞書/キーと値のペアのリストを渡すことでプロセスに柔軟性を持たせ、各引数の存在を処理します。非常に小さなパフォーマンスのトレードオフについては、それはケーキであり、あまりにもそれを食べるシナリオです。

インテリジェントでインターフェイス一貫性のある方法で引数をオーバーロードすることは、物事に対して堅牢になるためのスマートな方法です。したがって、冗長性をシステムに組み込むことで、さまざまな潜在的な送信手段を備えた新興技術分野のすべての人が所有し、実行する非常に複雑なネットワークでパケット配信が定期的に配信されないと想定されます。

ただし、特に管理しているシステム内での絶対的な失敗を許容することは、決して良いトレードオフではありません。たとえば、ページの上部または下部にJSを配置することに関する別の質問で、ヒッピーな発言をすることを避けるために、一息つく必要がありました。一部の人々は、ページを完全にロードできなかった場合でも、いくつかの機能がある可能性があるため、JSを一番上に置く方がよいと主張しました。ハーフワーキングページは、完全なバストよりも劣ります。せいぜい、あなたはそれを知る前にあなたが無能であると正しくあなたのサイトへのより多くの訪問者をもたらすでしょう。それについて何かできる人。

低めの技術ページを提供するだけで1999年のブラウザで2010の機能を提供しようとすることは、無謀なデザインのトレードオフのもう1つの例です。たとえば、!@#$ ingグラデーションの背景の上に浮かぶ要素の角を丸くするために、バグの多い回避策に費やされた開発者の時間に費やされた機会とお金は、完全に吹き飛ばされました。そして何のために?パフォーマンスの低いハイテクページを実績のあるテクノフォブに配信し、ハイエンドブラウザでの選択肢を制限する。

正しい選択であるためには、入力をロバストな方法で処理することを選択すると、短期および長期のIMOで、問題の両側での生活が常に楽になります。


4
「20個の引数をとるメソッドの場合」>さらに調べる必要はありません。5/ 6の後、メソッドは間違っています。答えてくれてありがとう:)
マチューM.

1

黙って失敗することはありません。それとは別に、API /ライブラリのユーザーが何を望んでいるかを推測しようとしても、悪い考えのようには聞こえません。しかし、私はそれに従いません。厳格な要件があると、呼び出しコードのバグやAPI /ライブラリに関する誤解を露呈する可能性があります。

さらに、すでに指摘したように、ユーザーが何を期待したかを実際に推測することがどれだけ難しいかにかかっています。非常に簡単な場合、次の2つのケースがあります。

  1. ライブラリは、ユーザーが実際に提供するものを期待できるように、少し異なるように設計する必要があります(関数の名前を変更するか、2つに分割する)。
  2. ライブラリが適切に設計されている、つまり明確でわかりやすい名前付けをしていると思われる場合は、ユーザーの意図を推測することができます。

100%明白で決定論的ではない場合、1つの入力を別の入力に変換する必要がある場合、既に述べたいくつかの理由(リファクタリングでの互換性の破れ、ユーザーの最低の驚き)のために、変換を行わないでください。

エンドユーザーに対処する場合、入力/推測を修正しようとすることは大歓迎です。彼は無効な情報を入力することが期待されています。このケースはまったく例外ではありません。ただし、別の開発者は、単純な非技術ユーザーではありません。彼にはエラーを理解する専門知識があり、エラーは重要である/有益である可能性があります。したがって、厳密なAPIの設計についてはもちろん同意しますが、もちろん厳密さには明確さと単純さが伴います。

私の似たようなケースのこの質問を読むことをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.