20

How does Clojure approach Separation of Concerns ? Since code is data, functions can be passed as parameters and used as returns...

And, since there is that principle "Better 1000 functions that work on 1 data structure, than 100 functions on 100 data structures" (or something like that).

I mean, pack everything a map, give it a keyword as key, and that's it ? functions, scalars, collections, everything...

The idea of Separation of Concerns is implemented, in Java, by means of Aspects (aspect oriented programming) and annotations. This is my view of the concept and might be somewhat limited, so don't take it for granted.

What is the right way (idiomatic way) to go about in Clojure, to avoid the WTFs of fellow programmers _

Cœur
  • 37,241
  • 25
  • 195
  • 267
Belun
  • 4,151
  • 7
  • 34
  • 51
  • 3
    Could you be a bit more specific on what you are asking. Separation of concerns is a term used to mean a 100 different things. – Sami Dec 14 '10 at 17:54
  • 1
    Aspects are a way to modify the behavior of existing code without access to its source. Clojure and other Lisps provide something similar through dynamic variables, which are essentially globals with their own stacks. Top-level functions (those created with defn) are dynamic variables and can be bound with `binding`. The syntax of `binding` looks just like `let`, but the binding is used within calls inside the binding form. – Zak Feb 06 '11 at 18:01

1 Answers1

61

In a functional language, the best way to handle separation of concerns is to convert any programming problem into a set of transformations on a data structure. For instance, if you write a web app, the overall goal is to take a request and transform it into a response, which can be thought of as simply transforming the request data into response data. (In a non-trivial web app, the starting data would probably include not only the request, but also session and database information) Most programming tasks can be thought of in this way.

Each "concern" would be a function in a "pipeline" that helps make the transform possible. In this way, each function is completely decoupled from the other steps.

Note that this means that your data, as it undergoes these transformations, needs to be rich in its structure. Essentially, we want to put all the "intelligence" of our program into the data, not in the code. In a complicated functional program, the data at the different levels may be complex enough that in needs to look like a programming language in its own right- This is where the idea of "domain-specific languages" comes into play.

Clojure has excellent support for manipulating complex heterogenous data structures, which makes this less cumbersome than it may sound (i.e. it's not cumbersome at all if done right)

In addition, Clojure's support for lazy data structures allows these intermediate data structures to actually be (conceptually) infinite in size, which makes this decoupling possible in most scenarios. See the following paper for info on why having infinite data structures is so valuable in this situation: http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf

This "pipeline" approach can handle 90% of your needs for separating concerns. For the remaining 10% you can use Clojure macros, which, at a high level, can be thought of as a very powerful tool for aspect-oriented programming.

That's how I believe you can best decouple concerns in Clojure- Note that "objects" or "aspects" are not really necessary concepts in this approach.

drcode
  • 3,287
  • 2
  • 25
  • 29
  • Well said! As additional note, if most of your functions are pure, you can easily test them independently. – Goran Jovic Dec 14 '10 at 19:37
  • so, instead of Objects (in OO languages), you get structures (in functional languages). This is the corresponded "concept" for Encapsulation (to achieve high cohension, low coupling, black-boxes, modularity) ? Does it have a name ? – Belun Dec 15 '10 at 14:58
  • a good read that talks about a similar pipeline approach (albeit in Python): http://www.dabeaz.com/generators/Generators.pdf – szx Feb 01 '11 at 20:00