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

Clojure function greater than 10 SLOC

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

Problem

It has been mentioned in the Clojure Style guide to avoid functions longer than 10 SLOC but mine has more than 10 (47 to be exact).

The code is an web api implementation and follows like this:

```
(defn classify
"Sends a text to a classifier and returns a classification"
[keys texts classifier & user-name]
{:pre [(check-keys? keys)]}
(let [textbase64-tag (map #(make-xml-node :textBase64
{:id (str "Text" (str (index-of % texts)))}
(String. (encode (.getBytes %)) )) texts)
texts-tag (make-xml-node :texts {} textbase64-tag)
user-attribute (if (> (count user-name) 0)
{ :username (first user-name) })
classify-tag (if (= (count user-name) 0)
(map #(make-xml-node :classify
{:id (str "Classify" %)
:classifierName classifier
:textId (str "Text" %)
})
(range (count texts)))
(map #(make-xml-node :classify
{:id (str "Classify" %)
:classifierName classifier
:textId (str "Text" %)
:username (first user-name)})
(range (count texts))))
read-calls (make-xml-node :readCalls
{:readApiKey (keys :read-key)}
classify-tag)
uclassify-response (raw-post-request
(xml/emit-str
(xml-append-elements uclassify
(list texts-tag read-calls))))]
(if (check-response
(get-response uclassify-response))

Solution

There's value in factoring the logic out into one or more new functions, even if those functions are only used in a single place, because it can make the code easier to understand and modify.

In a situation like that (when the logic won't be used elsewhere) I often use letfn. The letfn could be either internal or external to the function itself but I see that as a purely stylistic decision.

Here's the ClojureDocs page on letfn. See Pedestal's dataflow logic for a few examples of letfn in use.

On the other hand, there's really no problem with having a top level function that's only used in one place. I like that letfn implicitly communicates the function's scope of relevance, but I don't think either way is objectively superior to the other.

Context

StackExchange Code Review Q#30106, answer score: 3

Revisions (0)

No revisions yet.