エラー処理が間違っています!

Susan Sarandon
Susan Sarandonオリジナル
2024-12-06 11:05:12968ブラウズ

You’re Doing Error-Handling Wrong!

エラー処理が間違っている: 予測可能で標準化された応答のケース

はじめに: 独自のスタンス

JavaScript でのエラー処理は、強い意見を呼び起こすトピックです。ここで私の意見を共有します。従来の try-catch アプローチは、使いにくく、不便で、時代遅れです。 Garmingo では、稼働時間とインフラストラクチャ監視のための SaaS ソリューションである Garmingo Status を構築しましたが、try-catch ブロックから移行しました。代わりに、非同期操作に対して予測可能な標準化された応答を提供する TypeScript ベースのアプローチを採用しました。

この記事では、このパラダイムが開発者の生産性を大きく変えると私たちが考える理由と、それがコードベースの簡素化にどのように役立ったかについて説明します。これは独断的な見解ではありますが、ご自身のプロジェクトでエラーを処理する方法を再考するきっかけになれば幸いです。

トライキャッチの問題

正直に言うと、JavaScript でのエラー処理は面倒になることがあります。従来の try-catch ブロックには多くの課題が伴います:

  1. 冗長性: すべての非同期関数呼び出しを try-catch でラップすると、不要な定型文が追加されます。コードが乱雑になり、読みやすさが損なわれます。
  2. 一貫性のないエラー オブジェクト: JavaScript エラー オブジェクトは、構造と内容が大きく異なる場合があります。標準化がなければ、これらのエラーを処理することは、推測ゲームをしているような気分になることがよくあります。
  3. ネストされたロジック地獄: 失敗する可能性のある複数の操作を処理する場合、ネストされた try-catch ブロックにより、コードが読み取り不能な混乱に変わります。

これらの問題を強調する簡単な例を次に示します:

try {
  const user = await fetchUser();
  try {
    const account = await fetchAccount(user.id);
    console.log(account);
  } catch (accountError) {
    console.error('Error fetching account:', accountError);
  }
} catch (userError) {
  console.error('Error fetching user:', userError);
}

結果は?コードの読み取り、デバッグ、保守が難しくなります。

TypeScript の型付き応答パラダイムに入る

Garmingo Status では、try-catch を廃止し、すべての非同期操作に対する標準化された応答構造を採用しました。仕組みは次のとおりです:

構造

すべての非同期関数は、事前定義された共用体タイプの Promise を返します。

Promise<
  | { success: false; error: string }
  | { success: true; result: T }
>;

このアプローチにより、次のことが保証されます。

  • 操作が失敗した場合、結果は常に { success: false、error: string } になります。
  • 成功した場合は、{ success: true, result: T } になります。
  • 成功が true の場合、結果オブジェクトは存在しますが、エラー オブジェクトは存在しません。またその逆も同様です。失敗した応答に対して結果を使用することもできません。

これは、上記と同じ例をこのパターンで書き直したものです:

const userResponse = await fetchUser();

if (!userResponse.success) {
  console.error('Error fetching user:', userResponse.error);
  return;
}

const accountResponse = await fetchAccount(userResponse.result.id);

if (!accountResponse.success) {
  console.error('Error fetching account:', accountResponse.error);
  return;
}

console.log(accountResponse.result);

ご覧のとおり、アプリのメイン ロジックにネストは導入されません。エラー処理のためにこれらの小さなチェックが追加されるだけですが、メイン フローは中断されず、最初からエラー処理の必要がなかったかのように続行できます。

予測可能かつ標準化されたエラー処理の利点

1. 予測可能性

最大の利点は、何が起こるかを正確に知ることができることです。操作が成功しても失敗しても、構造は一貫しています。これにより、エラー オブジェクトによく見られるあいまいさがなくなります。

2. 使いやすさ

深くネストされた try-catch ブロックの時代は終わりました。型付きアプローチを使用すると、コードのフローを中断することなくエラーをインラインで処理できます。

3. 読みやすさの向上

構造化されたアプローチにより、コードがクリーンになり、理解しやすくなります。各操作は、成功シナリオと失敗シナリオで何が起こるかを明確に定義します。

4. タイプセーフティの強化

TypeScript の静的分析により、エラーの処理を忘れることはありません。成功のチェックを誤って省略すると、TypeScript コンパイラによってフラグが立てられます。

バランスのとれた視点

欠点のないアプローチはありません。型付き応答パラダイムでは、成功する確信がある場合でも、すべての操作の成功ステータスを明示的にチェックする必要があります。これにより、(自己責任ではありますが) 単純にエラー処理を完全に回避できる従来のアプローチと比較して、わずかなオーバーヘッドが追加されます。

ただし、この「欠点」は長所の 1 つでもあります。潜在的な障害について批判的に考える必要があり、その結果、コードがより堅牢になります

Garmingo Status での使用方法

Garmingo では、このアプローチにより、非同期ユーティリティとライブラリの構築方法が変わりました。すべての API 呼び出しとデータベース クエリは、この標準化された応答構造に準拠し、コードベース全体の一貫性を確保します。
実際、プロジェクト全体で再利用され、失敗する可能性がある すべて の単一の非同期関数がこのアプローチを使用します。
結果?よりスムーズな (そしてはるかに高速な) 開発エクスペリエンスと、深夜のデバッグ セッションの減少。

たとえば、フェッチ関数は次のようになります:

try {
  const user = await fetchUser();
  try {
    const account = await fetchAccount(user.id);
    console.log(account);
  } catch (accountError) {
    console.error('Error fetching account:', accountError);
  }
} catch (userError) {
  console.error('Error fetching user:', userError);
}

この予測可能性は私たちのチームにとって大きな変革となり、エラー処理ロジックを解くのではなく機能の構築に集中できるようになりました。

結論

従来の try-catch ブロックにはそれなりの役割がありますが、最新の JavaScript 開発、特に TypeScript を多用したコードベースでは、価値がある以上に問題となることがよくあります。型付き応答パラダイムを採用することで、予測可能性、可読性、そして安心感が得られます。

Garmingo では、このアプローチがどのように開発を簡素化し、Garmingo Status のような洗練された製品を提供する能力を強化するかを直接見てきました。すべての人に適しているわけではないかもしれませんが、より多くの開発者が検討すべきアプローチだと私は強く信じています。

それで、エラー処理を再考する準備はできていますか?あなたの意見をお聞かせください!

以上がエラー処理が間違っています!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。