3

Scala で例外を処理するために、私は基本的なtry/catchを避け、Scalaz の関数型の考え方(場合によっては型にValidation似ています) の恩恵を受けることを好みます。Either

私のアプリケーションはいくつかのサービスを公開しています。私のサービスレイヤーでこの方法を想像してみてください(意味はありませんが、概念には適しています)。Buyer(購入者) を新しいものに関連付け、すべてのルールが成功した場合、この関連付けを含むCarを返します。Car

def create(carDTO: CarDTO, buyerDTO: BuyerDTO): Validation[Either[TechnicalFailure, List[CarCreationFailure]], CarDTO]

説明: を作成するCarと、両方の例外タイプのいずれかが発生する可能性があります:

  • 技術的な障害(たとえば、データベースがクラッシュしたとき) のラッピングThrowable例外。
  • ビジネスの失敗(たとえば、Car違法なステータスを持つなど、矛盾を防止するカスタム アプリケーションのルール)。もちろん、より多くの失敗CarCreationFailureによって拡張される可能性があります。precised

私の質問は、特にクライアント側に焦点を当てており、具体的には複数の可能性を扱っていますBusiness Failure

戻り値の型Validation[Either[TechnicalFailure, List[CarCreationFailure]], CarDTO]を扱いにくいものに置き換える必要があります。ValidationNel[Throwable, CarDTO]

ここに注意してくださいValidationNel(エラー/例外を に蓄積しますNonEmptyList)。

欠点は、新しい読者が一見しただけでは、このメソッドがTechnicalFailureor CarCreationFailure( BusinessFailureso のサブクラス) を返すと推測できないことです。あまりにも恐ろしいThrowable

Throwable彼は、誰かを忘れないようにするために、私のアプリケーションに含まれるすべての型にパターン マッチングを適用することを余儀なくされるでしょう... => 面倒。

これらのソリューションの中で最もクリーンな方法は何ですか、それとも...他の方法ですか?

4

2 に答える 2

1

Rex Kerr が使用するものに似た (より単純で洗練されていない) ものを使用します。

すべてのビジネス例外/エラーはカスタムBusinessExceptionにラップされ、他のすべてのエラーはさまざまな種類の例外をスローしています。

基本を使用しTry、サーブレットのコードは次のようになります (大幅に簡略化されています)

    ( req getParameter "action" match {

        case null          ⇒ Failure( new BusinessException( "Missing required parameter 'action'" ) )
        case "doThis"  ⇒ doThis()
        case "doThat"  ⇒ doThat( req )
        case x         ⇒ Failure( new BusinessException( "Uknown Action '" + x + "'" ) )
    } ) match {

        case Success( someResponse ) ⇒ //send 200 with some response
        case Failure(t) if t.isInstanceOf[BusinessException] => //send 400 with exception message 
        case Failure( t )        ⇒ //send 500 with exception message
    }

次のようなメソッドdoThisには、型の署名があります

def doThis(): Try[ Option[ String ] ] = Try {
    //do stuff
}

この単純なメカニズムの利点は、例外をスローする既存の Java コードを簡単にラップできることです。これが私たちのユース ケースです。

于 2013-04-24T17:07:21.460 に答える