HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

F# cache manager

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
managercachestackoverflow

Problem

This is a port of a C# cache manager we use to F#. This is my first F# code, and I've tried to make it as idiomatic as possible. I would appreciate input on style, performance considerations,correctness, anything at all. The goal is to learn more about F# and functional programming. The purpose of the code is to abstract away the IIS cache, and make it possible to use multiple levels of cache, such as using Redis as a second level cache.

```
namespace FSharpTools
open System.Web
open System.Web.Caching
open System.Collections
open System.Web.Configuration
open Microsoft.FSharp.Reflection

module TheOneCache =

type private CacheType = Web | Redis

//The ICache interface, which can be implemented for IIS cache, Redis, etc
type private ICache =
abstract member Add: string -> 'T -> unit
abstract member AddForTime: string -> 'T -> System.TimeSpan -> unit
abstract member Get: string -> 'T option
abstract member Exists: string -> bool
abstract member Remove: string -> unit
abstract member FlushAll: unit
abstract member FlushKeysThatStartWith: string -> unit
abstract member GetCountStartsWith: string -> int
abstract member GetCacheType: CacheType

//Implement the ICache interface as an IIS cache using an object expression
let private WebCache =
let GetHttpCacheEnum =
HttpRuntime.Cache
|> Seq.cast

let FilterKeys keyPrefix =
GetHttpCacheEnum
|> Seq.filter(fun e -> e.Key.ToString().StartsWith(keyPrefix))

{ new ICache with

member __.Add key value =
HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null)

member __.AddForTime key value duration =
HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, duration, CacheItemPriority.NotRemovable

Solution

My suggestion here is to just make a class for the multiple cache backed version that you are exposing. It can Implement ICache, and add the other ethods you require. This will mean there are less function names to reason about, slightly less code, and will avoid module functions backed by stateful objects, which seem unidiomatic (subjective). The module functions as public APIs will also prevent you from adding optional parameters, passing a common parameter to all the functions if needed, and having overloaded functions, many of which tend to happen in a public API as needs change.

Eirik recently tweeted about this:

https://twitter.com/eiriktsarpalis/status/964067904164651008

If I hadn't suggested converting to a class, I'd also point out that normally, people try to do lowercase for module functions. You may think you have seen some counterexamples in FSharp.Core, but you are usually looking at Static class functions in that case, which tend to be upper case.

Context

StackExchange Code Review Q#118643, answer score: 2

Revisions (0)

No revisions yet.