vendredi 29 juillet 2016

How to make this function testable?

I have a function responsible for collecting a bunch of configurations and making a bigger configuration out of all these parts. So it's basically:

let applyUpdate updateData currentState =
    if not (someConditionAbout updateData) then
        log (SomeError)

    let this = getThis updateData currentState.Thingy
    let that = getThat updateData currentState.Thingy
    let andThat = createThatThing that this updateData

    // blablablablablabla

    { currentState with
        This = this
        That = that
        AndThat = andThat
        // etc. }

I currently have unit tests for getThis, getThat, createThatThing, but not for applyUpdate. In an object-oriented style, these would be passed via an interface through dependency injection. In a functional style I'm unsure as to how to proceed:

// This is the function called by tests
let applyUpdateTestable getThisFn getThatFn createThatThingfn etc updateData currentState =
    if not (someConditionAbout updateData) then
        log (SomeError)

    let this = getThisFn updateData currentState.Thingy
    // etc

    { currentState with
        This = this
        // etc. }

// This is the function that is actually called by client code
let applyUpdate = applyUpdateTestable getThis getThat etc

This seems the functional equivalent of Bastard Injection, but beyond that I'm mainly concerned with:

  • now my code is harder to follow because you can't just F12 (Go to Definition) into functions; this problem also exists with dependency injection but is mitigated by tooling (i.e. Resharper Go To Implementation).
  • The function I'm testing isn't technically the one called by production code (there could be errors in the mapping)
  • I don't even see a good name for that "Testable" version of the function
  • I'm polluting the module with duplicate definitions of everything

How do deal with these problems in functional programming?

Aucun commentaire:

Enregistrer un commentaire