リターンコードと例外:鐘楼からの眺め

ポストリターンコードと例外およびコメントを見て、1つのスレッドが議論に欠けていることに気付きました。その簡潔な理論は次のとおりです。一部の言語では、この問題は価値がありません。 そのような言語での質問「選択するもの、戻りコード、または除外」は低レベルです。 たとえば、「foreach」コンストラクトを実装する方法に疑問はありません。 なぜなら 同じ「foreach」を使用するプログラマにとって、作成者がこの演算子の実装でwhileを使用したか、言語または他の何かを使用したかは問題になりません。 主なものはパターンです。これはまさにこの演算子です。

foreachについて話すのをやめます。 例として、互いに非常によく似た2つの演算子を直接示します。1つは実装として「例外」を使用し、もう1つは「戻りコード」を使用します。

プロセス例外 [ マッピング本体 ]
ここで、 マッピングは{例外1 <->処理方法1、例外2 <->処理方法2、...}、body-例外が発生する可能性のある演算子の形式のマップです。

および2番目の演算子:
process-retcode-answer [ マッピングボディ ]
ここで、 マッピングは{戻りコード1 <->処理方法1、戻りコード2 <->処理方法2、...}の形式のマップです。 本文 -サブプログラムの応答で終わるステートメントの本文または必要な呼び出し先システム戻りコードに基づいたプロセス。

彼らが働くのを見てみましょう。

プロセス再コード回答



リターンコード0、-1、-2、および残りのコードを処理するロジックを処理する関数があるとします。

defn ok-processor [結果]
println str " ok。result :" result ))

defn error-processor [結果]
println str " error。result :" result ))

defn another-error-processor [結果]
println str "another error。result :" result

defn unknown-error-processor [結果]
println str "unknown error。result :" result


それらを処理する関数の名前のマップ戻りコードを定義します。

def result-mapping { 0 'ok-processor
-1 'エラープロセッサ
-2 '別のエラープロセッサ
その他の 'unknown-error-processor }


次に、さまざまな戻りコードと対応する結果を返すテストルーチンを作成します。

defn test-call-ok [ ]
[ 0 "テスト結果" ]

defn test-call- error [ ]
[ -1 "テスト結果" ]

defn test-call-another- error [ ]
[ -2 "テスト結果" ]

defn test-call-unknown- error [ ]
[ -1000 "テスト結果" ]


この場合のオペレーターの作業は次のようになります。

process-retcode-answer結果マッピング test-call-ok
わかった 結果 テスト結果

process-retcode-answer result-mapping test-call- error
エラー 結果 テスト結果

process-retcode-answer result-mapping test-call-another- error
別のエラー 結果 テスト結果

process-retcode-answer結果マッピング test-call-unknown- error
不明なエラー 結果 テスト結果


ここでは、各ボディは1つのメソッドのみで構成されています。 実際には、代わりに任意の関数シーケンスを挿入できます。

この演算子の利点は、ハンドラーを実装し、マッピングを適切に変更することにより、新しいコードの処理または既存のハンドラーの変更が透過的に実行されることです。

ifsはありません。 このアプローチは、リターンコードを処理するためのかなり柔軟なパターンを実装します。

プロセス例外



前の例との類推によって。 いくつかの例外を処理するための関数があります。

defn算術例外プロセッサ[ e ]
println str "算術例外。"

defn nullpointer-exception-processor [ e ]
println str "Nullpointer exception。"

defn another-exception-processor [ e ]
println str "その他の例外。"


それらを処理する関数の名前の例外をマップします。

def exception-mapping { java。lang。ArithmeticException 'arithmetic-exception-processor
java lang NullPointerException 'nullpointer-exception-processor
java lang 例外 'another-exception-processor }


さまざまな例外を生成するテストルーチンを作成します。

defn test-call-ok [ ]
「テスト結果」

defn test-throw-arithmetic-exception [ ]
throw new java。lang。ArithmeticException
「テスト結果」

defn test-throw-nullpointer-exception [ ]
throw 新しいjava。lang。NullPointerException
「テスト結果」

defn test-throw-other-exception [ ]
throw 新しいjava。lang。ClassNotFoundException
「テスト結果」


オペレーターの仕事:

プロセス例外の例外マッピング
test-call-ok ))
「テスト結果」

プロセス例外の例外マッピング
test-throw-arithmetic-exception
算術例外

プロセス例外の例外マッピング
test-throw-nullpointer-exception
ヌルポインター例外

プロセス例外の例外マッピング
test-throw-other-exception
その他の例外


前のステートメントの説明の最後にある注意がここに適用されます。

結論



これらの演算子は非常に似ており、原則として、同じ応答処理パターンを実装しますが、実装は異なります。 ここでは、 process-retcode-answerを優先します 。 他の言語では、例外を使用するバリアントと比較して、リターンコードを持つバリアントが常に有利であるとは限りません(もちろん、問題の条件と言語自体に依存します-これについては既に説明しました)。

上記の演算子の実装オプションは次のとおりです。

defmacroプロセス例外[マッピング本体]
let [ catch-items map fn [ m ]
` catch〜 first m e#
eval second m e#
eval mapping ]
` try〜@ body
〜@ catch-items


defmacro process-retcode-answer [ mapping body ]
` let [ answer# do〜@ body
retcode# 最初の回答#
結果# 2番目の回答#
プロセッサー# get〜マッピングretcode#
プロセッサ# if nil ?processor# other〜mapping プロセッサ# ]
eval processor# result#


このかなり誇張された例は、新しいコンストラクトで言語を拡張し、同じ高次関数、ラムダ、クロージャーを持つ機能のように、言語の基本要素はあまり重要ではないことを示しています。 このような言語により、プログラマーはアーティストになれます。 彼は何度も何度もパターンを書きません。 彼は、自分の仕事の解決策を最も自然に、グラフィカルに、簡潔に定式化できる言語を単に「作成」します。 職業は工芸ではなく芸術になります。

Source: https://habr.com/ru/post/J131129/


All Articles