1. 概要

assertとrequireは、契約設計(DbC)アプローチを使用してプログラムを作成するために使用されるScalaの前提条件です。 このチュートリアルでは、assertおよびrequireの機能について学習します。 次に、セマンティクスと例外動作の違いを確認し、プログラムでどちらを使用するかを確認します。

assertとrequireの両方がPredef.scalaパッケージで定義されています。 したがって、それらはすべてのScalaプログラムに自動的にインポートされます。

2. アサート

assertは、ブール式をtrueまたはfalseとして評価するScalaの前提条件です。 通常、実行時にプログラムの実行を検証するために使用されます assert は、プログラムの機能をテストする際に一般的に使用されていることがわかります。

式がfalseと評価された場合、assertはAssertionErrorをスローし、は実行中のプログラムの障害を示します。

数値の2乗を計算する関数を見てみましょう。

private def squareNumCalculation(n: Int):Int = n * n
def getSquareOfNumber(n: Int):Int = {
  assert(squareNumCalculation(2) == 4)
  val squaredNum = squareNumCalculation(n)
  return squaredNum
}

ご覧のとおり、関数squareNumCalculationは整数の2乗を計算します。 パブリック関数では、 getSquareOfNumberassert を使用して、呼び出し元のプログラムに結果を返す前に、計算が正しいことを確認します。

3. 必須

requireは、プログラムのさらなる実行に進む前に、特定の前提条件を適用するために使用される前提条件です。 これは通常、関数への入力パラメーターを検証するために使用されるため、呼び出し側に前提条件を適用します。

assert と同様に、 require も式を取り込んで、結果をtrueまたはfalseとして評価します。require true、の場合は前提条件を渡し、結果がfalseの場合はIllegalArgumentExceptionをスローします。

18歳以上の申請者に運転免許証を発行する機能を見てみましょう。

def issueDrivingLicense(name: String, age: Int): Unit = {
  require(age >= 18)
  println("Issued Driving License to %s ".format(name))
}
issueDrivingLicense("Darwin", 38) // prints "Issued Driving License to Darwin"

try {
  issueDrivingLicense("Jr. Darwin", 5) // prints "Failed in require precondition" 
} catch {
  case e: IllegalArgumentException =>
    println("Failed in require precondition")
}

このサンプル関数では、 require 前提条件により、ageパラメーターが18以上になることが保証されます。 それ以外の場合は、例外をスローします。

4. 機能の違い

assertrequireは表面的なレベルでは似ていますが、それらの間にはいくつかの機能上の違いがあります。

assert は通常、コード/プログラムが期待どおりに機能していることを検証するために使用されます。 一方、 require は、プログラムの入力パラメーターが有効であることを確認するために使用されます。 この違いは、スローされた例外の動作でも明らかです。 assertはエラー(AssertionError)をスローし、requireは例外(IllegalArgumentException)をスローします。

エラーと例外の一般的な違いは、ここでも当てはまります。 エラーは異常状態が発生したことを示し、プログラムの実行を停止する必要があります。ただし、例外は異なります。

アプリケーションで例外をキャッチして適切に処理できるため、プログラムの実行を続行できます。

5. 技術的な違い

これまで、assertrequireの機能の違いを見てきました。 それでは、技術的な違いを見てみましょう。 Predef.scalaassert関数のソースコードを見ると、assert関数の定義に@elidableという注釈が付けられていることがわかります。 (アサーション)。

この機能を使用すると、コンパイラフラグ-Xelide-belowASSERTIONまたは-Xdisable-assertionsを設定することにより、コンパイル時にアサーションを無効にできます。 したがって、コンパイラはコンパイルされたバイトコードにアサーションを含めないため、はるかに軽量で高速な実行可能ファイルが得られます。

一般的なパッケージパターンには、すべてのアサーションを実行し、コードが完全に機能していることを確認するテストビルド内のすべてのアサーションが含まれます。 その後、すべてのアサーションを除外して本番ビルドを実行します。 したがって、より高速でパフォーマンスの高いプログラムを取得できます。

scalac -Xelide-below ASSERTION

また

scalac -Xdisable-assertions

requireは省略可能な関数ではありません require は、関数の呼び出し元に前提条件を適用することを強調しているため、関数を削除不可にする方が理にかなっています。

6. 結論

この短いチュートリアルでは、Scalaのassertrequireの機能を学びました。 次に、簡単な例を使用して、それらのセマンティクスと例外の動作を学習しました。 入力パラメーターに前提条件を適用する必要がある場合はrequireを使用し、プログラムの実行を検証する必要がある場所ではassertを使用します

いつものように、完全なソースコードはGitHubにあります。