Log in or use it?

This is best (I know that there is no silver bullet, but there may be some advantage, using one over the other) - to enter the calling function or the function that calls it?

Examples:

Approach 1


module MongoDb =
   let tryGetServer connectionString =
      try
         let server = new MongoClient(connectionString).GetServer()
         server.Ping()
         Some server
      with _ -> None

Using:

match MongoDb.tryGetServer Config.connectionString with
| None ->
    logger.Information "Unable to connect to the database server."
    // ... code ...
| Some srv ->
    logger.Information "Successfully connected to the database server."
    // ... code ...

Approach 2


module MongoDb =
    let tryGetServer connectionString =
        try
            let server = new MongoClient(connectionString).GetServer()
            server.Ping()
            Some server
        with _ -> None

    let tryGetServerLogable connectionString logger =
        match tryGetServer connectionString with
        | None -> 
            logger.Information "Unable to connect to the database server."
            None
        | Some srv -> 
            logger.Information "Successfully connected to the database server."
            Some srv

Using:

match MongoDb.tryGetServerLogable Config.connectionString logger with
| None ->
    // ... code ...
| Some srv ->
    // ... code ...
+4
source share
2 answers

2 . , - , . ; OOD, Decorators Interceptors. FP OOD, .

, 2 , - :

module MongoDb =
    let tryGetServer connectionString =
        try
            let server = MongoClient(connectionString).GetServer()
            server.Ping()
            Some server
        with _ -> None

, MongoDb . , .

tryGetServer :

string -> MongoServer option

, MongoDb:

module XyzLog =
    type Logger() =
        member this.Information message = ()

    let tryGetServer f (logger : Logger) connectionString  =
        match f connectionString with
        | None ->
            logger.Information "Unable to connect to the database server."
            None
        | Some srv ->
            logger.Information "Successfully connected to the database server."
            Some srv

, XyzLog , Serilog, Log4Net, NLog, ...

f - 'a -> 'b option, MongoDb.tryGetServer .

, :

let tgs = XyzLog.tryGetServer MongoDb.tryGetServer (XyzLog.Logger())

tgs

string -> MongoServer option

, , , MongoDb.tryGetServer tgs , .

MongoDb.tryGetServer, .

+5

, . , , - async (, ASP.NET MVC ActionFilters), . , tryGetServer string -> MongoServer option. , :

type Service<'a, 'b> = 'a -> 'b option

, :

type Filter<'a, 'b> = 'a -> Service<'a, 'b> -> 'b option

- , 'a a Service<'a, 'b>, , Service<'a, 'b>. - , 'a, , , . , .

let loggingFilter (connStr:string) (tryGetServer:string -> MongoServer option) : Filter<string, MongoServer option> =
  let server = tryGetServer connStr 
  match tryGetServer connStr with
  | Some _ ->
    logger.Information "Successfully connected to the database server."
    server
  | None -> 
    logger.Information "Unable to connect to the database server."
    server

, :

type Continuation<'a,'r> = ('a  -> 'r) -> 'r

module Continuation =     

    let bind (m:Continuation<'a, 'r>) k c = m (fun a -> k a c)

module Filter =

    /// Composes two filters into one which calls the first one, then the second one.
    let andThen (f2:Filter<_,,_>) (f1:Filter<_,_>) : Filter<_,_> = fun input -> Continuation.bind (f1 input) f2

    /// Applies a filter to a service returning a filtered service.
    let apply (service:Service<_,_>) (filter:Filter<_,_>) : Service<_,_> = fun input -> filter input service

    /// The identity filter which passes the input directly to the service and propagates the output.
    let identity : Filter<_,_> = fun (input:'Input) (service:Service<_,_>) -> service input

, :

let tryGetServerLogable = Filter.apply tryGetServer loggingFilter

? , . , , , , Filter.andThen. , , - .

- . - , .

+4

Source: https://habr.com/ru/post/1548463/


All Articles