4

I have been inspired buy this book: Building Evolutionary Architectures and clean architecture.

One of the concept is to be able to test your architecture in the code. In particular I would like to be able to check dependencies between namespaces, layers and assert that a namespace doesn't call a namespace for another layer.

All my namespaces are inside the circles:

my architecture

The idea is that a namespace inside 'controllers' can not import a namespace inside 'entities' but only import namespaces below him (use-cases). And I would like to detect this in my unit tests.

So this should fail in my unit tests:

(ns com.controller.core
  (:require [com.entities.core :as entities]
            [com.use-cases.core :as use-cases]))

(defn do-something [args]
      (let [use-cases-results (use-cases/do-something args)]
           (entities/do-some-other-thing use-cases-results)))

In java you can write those sort of unit tests using archunit.

private final JavaClasses classes = new ClassFileImporter().importPackagesOf(Controller/core.class);

noClasses().that().resideInAPackage("..controller..").should().accessClassesThat().resideInAPackage("..use-cases..").check(classes);

Are you using something similar for clojure or do you have some suggestions how to tackle this problem?

Michel Uncini
  • 321
  • 1
  • 14
  • 2
    This is a perfectly valid and interesting question but some of the nitpickers would like to see more concrete detail. Could you add a brief example- a little sample code with 2 or 3 namespaces, and some references between them, and an example of the kind of test shape you would like to see fail given the example? – Jonah Benton May 23 '18 at 16:34
  • 2
    BTW, here's a good fairly recent list of code quality tools: https://blog.jeaye.com/2017/08/31/clojure-code-quality/. There also is a legendary old project from Rich Hickey, the author of Clojure, called codeq: https://github.com/Datomic/codeq which loads a git repo into a Datomic database, allowing for various kinds of code shape queries. Rumors are that Cognitect will be giving codeq some love in the near future. – Jonah Benton May 23 '18 at 16:36
  • 2
    One more reference- there is an interesting project written in Clojure that focuses on code quality and deeper tech and architectural debt issues, see here: https://clojure.org/stories/empear. The founder is author of a great code analysis book "Code as a Crime Scene", see http://adamtornhill.com/ for more – Jonah Benton May 23 '18 at 16:47
  • codeq is really cool! but for may case I would like to have something like archunit :) – Michel Uncini May 24 '18 at 09:19
  • I am looking for exactly the same. I think Clojure core provides the tools to achieve this, and there are libraries in this space too focusing on static analysis. It's a shame that a wonderful language, used in cautiously, can still yield a mess when everything is globally referenceable. Enforcing structures is a good way of stopping this happening. – Anthony Leonard Dec 11 '20 at 09:35

1 Answers1

0

How about using ns-refers something like:

(deftest controllers-should-not-refer-to-entities
  (is (->> (all-ns)
           (filter #(clojure.string/includes? % "controller"))
           (map ns-refers)
           (map vals)
           flatten
           (not-any? #(clojure.string/includes? % "entities")))))