Skip to content

Instantly share code, notes, and snippets.

Last active Aug 16, 2021
What would you like to do?
Some Clojure anti-patterns
;; Anti patterns
;; Implicit data manipulation anti-pattern
;; Having nested calls manipulating data, instead of explicitly stating
;; what changes are performed to the data
(def h
;; ...
(def g [y]
;; ...
(h (->z y)))
(def f [x]
;; ...
(g (->y x)))
;; VS
(-> x
;; The benifits are two-fold: we can explicitly read what the sequence
;; of data manipulations are, and we can insert log statements easily to
;; track the data. Also, the definition order of f, g and h is
;; not important. They are made reusable, and decoupled from each other.
;; Another point, we can only test f->g->h, g->h and h in the first
;; strategy, we can test each of the functions in the other
;; Example
;; logs -> logs with error 500 -> logs grouped by date -> entry with
;; most elements -> key for that entry
;; First strategy:
(defn filtered-logs
(filter #(= 500 (:error %)) logs))
(defn filtered-and-grouped-by-date-logs
(group-by :date (filtered-logs logs)))
(defn day-with-most-500-errors
(key (max-key (comp count second) (filtered-and-grouped-by-date-logs logs))))
;; Second strategy
(defn filtered-logs
(filter #(= 500 (:error %)) logs))
(defn filtered-and-grouped-by-date-logs
(group-by :date logs)) ;; now does less
(def day-with-most-500-errors
(->> logs
(max-key (comp count second))
;; Related, but more difficult to illustrate:
;; Data reconstructive surgery vs. data massage anti-pattern
;; Information is transformed through different representations aiding
;; in a calculation, where each representation is different, introducing
;; a new view of the world in each function invocation, thereby making
;; it hard to mentally context switch from function to function. It also
;; makes it more cumbersome to generate test data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment