I have found that my code tends to end up structured like so:
- Functions that take maps tend to be larger and have side effects.
- Functions that take arguments tend to be smaller and are pure.
I didn't set out to create this distinction but that is often how it ends up in my code. I don't think using one style necessarily negates the other.
The pure functions are easy to unit test. The larger ones with maps get more into the "integration" test area since they tend to involve more moving parts.
In javascript, one thing that helps a lot is using something like Meteor's Match library to perform parameter validation. It makes it very clear what the function expects and can handle maps quite cleanly.
For example,
function foo (post) { check(post, { text: String, timestamp: Date, // Optional, but if present must be an array of strings tags: Match.Optional([String]) }); // do stuff } See http://docs.meteor.com/#match for more.
:: UPDATE ::
Stuart Sierra's video recording of Clojure/West's "Clojure in the Large" also touches on this subject. Like the OP, he controls side effects as part of the map so testing becomes much easier. He also has a blog post outlining his current Clojure workflow which seems relevant.