2009-07-13 6 views
8

私はJavaコードベースをCocoa/Objective-Cに移植してデスクトップMac OS X上で動作させようとしています。Javaコードにはロットロットのメソッドがあり、以下のようなチェック例外があります:JavaコードをObjCに移植する際に、チェック例外をどのように表現するのが最適でしょうか?

double asNumber() throws FooException { 
    ... 
} 

Objective-Cでこれらを表現する最良の方法は?例外またはエラーアウトパラメータ?

- (CGFloat)asNumber { 
    ... // possibly [FooException raise:format:]; 
} 

または

- (CGFloat)asNumberError:(NSError **)outError { 
    ... 
} 

私はOut-Errorが一般的にObjective-Cの方が優れているという感覚を持っていますが、あなたが見ることができるように...上記のような多くの方法非常に扱いにくいです。また、ロットがあります。

もちろん、これらはJavaで 例外がチェックされているので、 @tryブロックまたは if (*outError) {...}チェックをどこにでも追加する必要があります( ロットの場所)。

Objective-Cでは@tryブロックに入るのは一度高価でしたが、64ビットやSLや他の新しいenv(正確には思い出さない)では安いと聞きました。私は下位互換性について全く心配していないので、私はです。

+1

私は自宅で一緒に続く人のために、私はアウトエラーに行くとクインのNSScannerのアドバイスに従うことにしました。この特定のメソッドは、次のようなものになります。 ' - (BOOL)getNumber:(CGFloat *)outNumエラー:(NSError **)outErr;' –

+0

@olliejは、@tryブロックが現代ランタイムで「ゼロコスト」であることを正しく指摘します(64ビット版とiPhone版)がありますが、実際に例外を投げると例外が発生します。また、必要に応じて、 'CGFloat'の代わりに' double'を使用することもできます。自分がいる環境と統合するコードのベストプラクティスを実行してください。 –

答えて

16

は、文字列から数値を解析する場合など、例外の例外を絶対に避けてください。 Objective-Cでは、例外はプログラマーのエラーを表し、ユーザーの入力エラーではなく、使用できないファイルでもあります。 (理由の一部は、例外処理はより多くの "従来の"エラー処理よりもコストがかかり、複雑であるということです。entering @try blocks is "zero cost" in 64-bitという事実にかかわらず、例外が実際に発生したときは遅いです)。もちろん、あなたが好きなように例外はありますが、これはCocoaのやり方ではありません。あなたは他のObjective-Cコードとは違うかもしれません。あなたのコードを使用する人々は、エラーに終わるはずのケースで例外をスローすると信じられないほど迷惑になります。 Apple's own docsから

:内蔵のCocoaクラスは、このようなエラーを処理する方法で

"In many environments, use of exceptions is fairly commonplace. For example, you might throw an exception to signal that a routine could not execute normally—such as when a file is missing or data could not be parsed correctly. Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors. Instead you should use the return value of a method or function to indicate that an error has occurred, and provide information about the problem in an error object."

ルック。たとえば、NSStringには-floatValueのような失敗した場合は0を返すメソッドがあります。あなたの特定の状況のた​​めのよりよい解決策は、-scanFloat:のようにNSScannerが実行する方法です。結果が格納されるフィールドへのポインタを受け取り、解析が成功したかどうかに基づいてYESまたはNOを返します。

Obejctive-Cの慣例とベストプラクティスとは別に、NSErrorはNSExceptionよりはるかに堅牢で柔軟性があり、発信者が問題を効果的に無視できるようにします。私はError Handling Programming Guide For Cocoaを通して読むことをお勧めします。 注:NSError**パラメータを受け入れる場合は、エラー情報を受け取らないようにクライアントがNULLを渡すように設計することを強くお勧めします。私が知っているすべてのCocoaクラスは、NSStringを含むエラーに対してこれを行います。

移植されたコードはJavaコードと全く違って見えるかもしれませんが、Javaコードと同じクライアントではなくObjective-Cコードで使用されることを認識してください。間違いなく、言語のイディオムにマッチします。ポートはJavaコードの鏡像ではありませんが、その結果として(Objective-Cでは)より正確になります。

+0

あなたのフィードバックのために、Qux –

+1

私は特にNSScanner'アドバイスが好きです。これらのメソッド名を少しきれいにしてObjCでより自然にするのに役立ちます。 –

-1

64ビットObj-C ABI(ランタイム)はゼロコスト例外を使用するため、例外がおそらく最善の方法です。したがって、実際のコストでよりクリーンなコードを取得できます。もちろん、32ビットの古いsetjmp/longjmp例外はまだ使用されており、C++とやりとりしないので、それが目標であれば問題があります。

+0

偉大なフィードバックoliverのためのthx。記録のために、いいえ。私はこのコードベースをC++と何らかの形で混ぜ合わせません。 –

+0

-1申し訳ありませんが、これはObjective-CのTERRIBLEアドバイスです。すべての例外が「ゼロコスト」であるわけではなく、実際には決して発生しないものだけです(並行処理を使用してプログラミングする場合の非競合ロックによく似ています)。あなたが例外( "スロー")を起こした瞬間に、あなたは価格を支払う。ライブラリコードでは例外が発生する可能性がありますが、すべての単一のクライアントは@tryと@catchを使用して例外を処理する必要があるため、 "cleaner code"という結果をもたらすと主張しています。 「ココアのやり方」は、このような状況にエラーと戻りコードを使用することです。ポートが良いObjective-Cコードになるようにするには、EXCEPTIONSを使用しないでください。 –

+1

@Quinn:「ゼロコスト」の例外は、例外がスローされない場合は特にゼロコストを意味するよく理解されている用語です。32ビットObj-C ABIはsetjmpとlongjmpを使用して例外を実装しています。つまり、@ try/@ catchは例外がスローされるかどうかにかかわらず大きなコストがかかります。 – olliej

3

「アウトエラーは一般にObjCにとってより良い解決策です」ごくまれに、例外をスローするAPIをCocoaで見つけることができます(APIの前提条件を満たしていない場合を除き、その場合の動作はデフォルトでは未定義です)。

このコードが他のCocoa開発者にも採用されることを期待している場合は、エラーを使用することをおすすめします。私はCocoaに慣れていない人が作成し、例外を自由に使ったコードで作業します。これは回避するための王様の痛みです。

7

ココアでは、例外は実際には「プログラミングエラー」のためだけに使用されることになっています。アプリはそれらをキャッチして、ユーザーに自分が行っていることを保存するオプションを与え、終了させるという哲学があります。 1つは、すべてのフレームワークやコードパスが100%例外セーフであるとは限らないため、これが唯一の安全な方法です。予期され、回復できるエラーについては、NSErrorを使用する必要があります。通常、outパラメータを使用します。

+1

Objective-Cの例外はJavaでエラーが定義されているのと似ています。あなたはそれらを処理するとは予想されませんが、正常にシャットダウンします。 –

2

私は、Objective-Cが使用するアウトエラーアプローチの大ファンです。例外を処理する必要がありますが、必要に応じてエラーを無視することもできます。 「プログラマは自分が何をしているかを知っている」というObjective-Cの姿勢にすべて合致しています。また、Objective-Cは非常にきれいな言語になっています。これは、コードがtry-catchブロックで煩雑にならないためです。

あなたは次のことを考えてみることができます:例外が無視されるシナリオはありますか?あなたが本当に投げる例外はです。?変数をクリーンアップして継続する単純なキャッチブロックを作成していますか?私はシンタックスが好きで、Objective-Cが最も重大なエラーだけのために例外を予約するので、エラーに向かって傾いています。

+0

hrm、Javaソースでは、これらは*チェックされた*例外なので、現在のデザインでは、絶対に処理する必要があります。彼らは本当に批判的ですが、私は厳しい質問であると思います。 本当に重要ではないかもしれません。元の作者は元の言語(Java)の優れた機能を利用していただけかもしれません。 私は言うでしょう....私は元の著者のために最高の尊敬を持っています。彼は間違いなく彼のものを知っている(少なくともJavaでは)。 –

+0

+1元の著者には敬意を表します。私がJavaで書くとき、私は規則(言語と私のチームの両方)に従い、同様の場合にチェック例外を投げます。これは、文脈を考慮したものであり、与えられた文脈に最も適したものです。また、NumberFormatException、NullPointerExceptionなどに対して常に防御するのではなく、エラーを処理することが本当に重要なときにクライアントが判断できるようにするのも良いことです –

2

これらの検査された例外の外観は、より完全にエラーにマップされます。例外は引き続き使用できますが、例外的な状況のために予約する必要があります。

関連する問題