Reputation: 34071
I am pretty new in f# world. I wrote a very small application that query data from sap and show the result as output. When the application try to connect sap, it could throw some exceptions, in case something goes wrong.
Look at following code:
type Customer() =
let mutable _lastName = String.Empty
member self.LastName with get () = _lastName
member self.QueryData () =
//Some CODES here
let bapi = SapBapi()
let bapiFunc = bapi.GetBapiFunc(dest, "BAPI_CUSTOMER_GETDETAIL1")
match bapiFunc with
| Success bp ->
//Some CODES here
let addressData = bp.GetStructure("PE_PERSONALDATA")
_lastName <- addressData.GetString("LASTNAME")
None
| RfcCommunication ex ->
Some(ex :> Exception)
| RfcLogon ex ->
Some(ex :> Exception)
| RfcAbapRuntime ex ->
Some(ex :> Exception)
As you can see, I handle the error with option type and downcast the throwed exception to base exception type.
In the main function
open CustomerBapi
open System
[<EntryPoint>]
let main argv =
let customer = CustomerBapi.Customer()
let ex = customer.QueryData()
match ex with
| Some ex ->
printfn "%s" ex.Message
| None ->
printfn "%s" customer.LastName
Console.ReadLine() |> ignore
0 // return an integer exit code
This code works but do I handle exception in the right way?
I read an article in internet, that handling exception in f# should return an error code, it's more easy then the exception style.
Upvotes: 1
Views: 123
Reputation: 13577
A typical way of handling errors within the type system is to employ an Either
type.
type Either<'a,'b> =
| Left of 'a
| Right of 'b
Conventionally Right value carries the success result and Left carries an error or exception (either as a string
or an exc
type). A simple way to think about it is to treat it like an option
where Right
corresponds to the Some
case and instead of a None
you have error information.
So your code could become:
// QueryData no longer needs to depend on side effects to work,
//so you can make it a regular function instead of a method
let result = queryData()
match result with
| Left ex ->
// handle exception
printfn "%s" ex.Message
| Right result ->
// either set the property, or make customer a record
// and set the name field here
customer.LastName <- result
printfn "%s" customer.LastName
The bit about error codes sounds very wrong, would like to know where you found it.
Upvotes: 2
Reputation: 7411
In general I think that your solution is okay, but can be improved.
You mix a bit the functional and OO style in your code. It feels a bit strange to me that you are working with the exception as the only optional value. Usually the customer should be the value which has the optionality included and the match should be if the customer has a value or not.
Upvotes: 0