Thursday, November 17, 2011

Dependency Injection vs Functional

At work, we use dependency injection to build up small, decoupled classes each with a single responsibility. DI lets us assemble these in multiple different ways, so we can use the same class for similar processes. This strategy of combining small pieces of functionality in different ways is also a goal of functional programming. Let's contrast the two methods.

There's a chunk of code whose job it is to string together the contents of a list of segments. The contents can be in one of two different fields in the segments. The segments might have connectors, which might need to go between the contents. We might need to skip the first and last segment if they're not interesting.

To avoid duplication of any part of this, our current Spring-y solution at work uses dependency injection to construct different SegmentContentsConcatenators with different components. The result is 9 Java classes and 6 Interfaces.

  • Builder
    • has a SegmentRemover (or a not-remover)
    • has a Concatenator
      • has a ConnectorRetriever (or a not-retriever)
      • has a first-or-lastness determiner
      • has a ContentExtractor (two implementations, one for each possible field)

The Spring configuration defines 3 beans that are useful, but in order to hydrate these in all possible combinations, 17 bean definitions are required. Fortunately for us we care about three of the eight possible behaviour combinations, so we only need 12 bean definitions. Only!

That's a at least 120 lines of Java in 15 files, plus about 30 lines of XML. Not counting tests.

Just for fun, I implemented the same functionality in F# using The result is 12 little function (including two that are generic and could be placed in a list-processing library). It took 30 lines of F# code. The functions build on each other, and the three desired functionality combinations are pieced together from other small functions. Best of all, there's no XML at all!

Both methods have the same goal: take small, testable pieces of functionality and piece them together in multiple ways. This is what functional languages DO. Trying to achieve the same goal in Java with Spring was not so pretty.

For reference, here's the F# code:

// defining the types
type Contents = string

type ConnectorMethod =
| Easy
| Complicated of Contents

type Segment = { ExpectedContents : Contents; ObservedContents : Contents; Connector : ConnectorMethod; IsExtraneous : bool;}

// Functions that build up all the pieces
let findConnector c : Contents =
match c with
| Easy -> ""
| Complicated x -> x

let expected s = s.ExpectedContents
let observed s = s.ObservedContents

let expectedInternalJunction s = expected s + findConnector s.Connector

let rec concatSegmentsInternal f fIJ acc list =
match list with
| [] -> acc
| [x] -> acc + f x
| head :: tail -> concatSegmentsInternal f fIJ ( acc + fIJ head ) tail

let concatSegments f fIJ l : Contents =
match l with
| [] -> ""
| x -> concatSegmentsInternal f fIJ "" l

let isExtraneous s = s.IsExtraneous

// these last two are generic, could apply to any predicate and list
let rec removeLastIf s l : 'a list =
match l with
| [] -> []
| [x] when s x -> []
| [x] -> [x]
| head :: tail -> head :: (removeLastIf s tail)

let removeEndsIf s l =
match l with
| [] -> []
| head :: tail when s head -> removeLastIf s tail
| head :: tail -> head :: removeLastIf s tail

// Publically useful methods - these put the pieces together.
let concatExpectedSegments : Segment list -> Contents = concatSegments expected expectedInternalJunction
let concatObservedSegments : Segment list -> Contents = concatSegments observed observed
let concatInterestingObservedSegments ss : Contents = concatSegments observed observed (removeEndsIf isExtraneous ss)

// Tests
let s1 = {ExpectedContents = "ABC"; ObservedContents = "ABCD"; Connector = Complicated "-"; IsExtraneous = true;}
let s2 = {ExpectedContents = "EFG"; ObservedContents = "EFGH"; Connector = Complicated "a"; IsExtraneous = false }
let s3 = {s1 with IsExtraneous = false}

let ss = [s1;s2;s3]

assert (concatExpectedSegments ss == "ABC-EFGaABC")
assert (concatObservedSegments ss == "ABCDEFGHABCD" )
assert (concatInterestingObservedSegments ss == "EFGHABCD")


  1. Are you acquainted besides cogent time, the Swiss watches are absolutely beautiful accessories to louis vuitton replica appearance your amusing cachet and appearance taste? As everybody knows, if you firstly accommodated somebody, his/her clothing, shoes and added accessories are some affair that comes into your mind. Apparently, we are activated to anticipation someone's personality by accessories they wear. Swiss watches with absolute above and adroitness are just ones men and women can advertise the comfortable lifestyle.Owning a baroque aboriginal Swiss watch is usually in anniversary and every agog fashionista's ambition list. While, they never appear out with low amount prices back appropriate and accomplished adroitness has been paid into, authoritative absolute that they've above top quality, attention engineering, and absurd function. Besides, they betoken the amount and acclaim of the top brands. Based on the diffuse history of their appearance houses, every Swiss alarm is a authentic section of art, forth with a adored treasure. Therefore, it seems that they are alone bound to the wealthy. For archetypal folks, they're not accommodating to pay their hard-earned money on such comfortable items. After all, for them, affluence items are no necessity, instead, they are extravagance. While, does it beggarly that they accept to carelessness the able of get amusement from affluence beauty? Absolutely not! Here we accept a abundant another to go for: Swiss replica watches. They are authentic duplicates of the aboriginal timepieces with finest materials, avant-garde movements, above alive dials, etc. Manufacturers of them put admirable affliction and adherence to replica watches aftermath every piece. What's added significant, they're absolutely cost-effective. Back they amount you alone a little atom of the banknote that you've got to pay for an aboriginal timepiece, they're basically the actual advantage for those who wish to aforementioned funds and accept a aftertaste of affluence as the identical time. There is a advanced ambit of Swiss replica watches offered in present market. They are frequently priced from $100 to $300 depending on assorted sizes and styles. You may consistently ascertain the acceptable 1 to bout your circadian outfit. Purchasing 1 isn't a arduous factor. It is accessible to breitling replica go about your bounded food or artlessly accomplish your adjustment on the internet in foreground of a claimed computer. No amount area you access from, you should consistently do accumulate in apperception to analysis the believability and acceptability of there retailers to break abroad from from getting cheated. In a word, it is absolutely not abstract to say that affairs Swiss replica watches are ideal and benign investment.