これは、機能的な観点からこれにアプローチする方法の例と、潜在的な落とし穴を回避するのにどのように役立つかを示しています。私はHaskellで働いていますが、あなたが知らないと想定しているので、詳しく説明しながら説明します。
data Application = Applied ApplicationDetails |
InReview ApplicationDetails |
Approved ApplicationDetails |
Declined ApplicationDetails
これは、アプリケーションの状態に対応する4つの状態のいずれかになるデータ型を定義します。 ApplicationDetails
詳細情報を含む既存のタイプであると想定されます。
newtype UpdatableApplication = UpdatableApplication Application
との間の明示的な変換が必要なタイプエイリアスApplication
。つまり、次の関数を定義し、それを受け入れてアンラップし、UpdatableApplication
それを使用して何か便利なことを行うと、
updateApplication :: UpdatableApplication -> ApplicationDetails -> Application
updateApplication (UpdatableApplication app) details = ...
次に、アプリケーションを使用する前に、明示的にアプリケーションをUpdatableApplicationに変換する必要があります。これは、次の関数を使用して行われます。
findUpdatableApplication :: Application -> Maybe UpdatableApplication
findUpdatableApplication app@(Applied _) = Just (UpdatableApplication app)
findUpdatableApplication _ = Nothing
ここでは、3つの興味深いことを行います。
- アプリケーションの状態をチェックします(この種のコードに非常に便利なパターンマッチングを使用)。
- 更新できる場合は、それをラップします
UpdatableApplication
(これには、追加される型の変更のコンパイル型のメモのみが含まれます。Haskellには、このような型レベルのトリッカーキーを実行する特定の機能があるため、実行時に何もかかりません) 、および
- 「Maybe」で結果を返します(
Option
C#またはOptional
Java と同様です。欠落している可能性のある結果をラップするオブジェクトです)。
これを実際に組み合わせるには、この関数を呼び出し、結果が成功した場合は、更新関数に渡す必要があります...
case findUpdatableApplication application of
Just updatableApplication -> do
storeApplicationInDatabase (updateApplication updatableApplication)
showConfirmationPage
Nothing -> do
showErrorPage
updateApplication
関数にはラップされたオブジェクトが必要なため、前提条件を確認することを忘れないでください。また、前提条件チェック関数はオブジェクト内のラップされたMaybe
オブジェクトを返すため、結果をチェックし、失敗した場合もそれに応じて応答することを忘れることはできません。
これで、オブジェクト指向言語でこれを行うことができます。しかし、それほど便利ではありません。
- 私が試したオブジェクト指向言語には、タイプセーフなラッパー型を作成するための単純な構文がないため、これは定型です。
- また、少なくともほとんどの言語では、ラッパータイプを削除することができないため、効率が低下します。これは、ラッパータイプが存在し、実行時に検出可能である必要があるためです(Haskellにはランタイムタイプチェックがありません。すべてのタイプチェックはコンパイル時に実行されます)。
- 一部のオブジェクト指向言語には同等のタイプ
Maybe
がありますが、通常、データを抽出して同時に取得するパスを選択する便利な方法がありません。ここでもパターンマッチングは非常に役立ちます。