Fish don't exist—they're a category humans invented. Files don't exist —they're abstractions over magnetic patterns. Your OrderService doesn't exist either —it's just a name you gave to clustered functions.
If systems are just collections of definitions, why do we scatter those definitions across code, diagrams, wikis, Slack threads, and tribal knowledge?
This article explores compound identities —using sets of semantic keywords instead of flat strings to define system entities. The key insight: `#{:semantic-namespace/error :domain.payment/timeout}` reads like plain English ("an error in the payment domain, specifically a timeout"), and becomes queryable:
```clojure
;; What can go wrong with payments?
(find-docs #{:domain.payment})
;; What are all critical errors?
(find-docs #{:severity/critical})
```
A mid-sized project has 500-1000 such definitions (errors, events, endpoints, metrics, permissions, etc.). Right now they're scattered. What if they were unified, typed, and queryable in one registry?
The system becomes self-describing. Everything else (API docs, monitoring dashboards, tests) can be generated from the definitions.
Built in Clojure but the concept applies broadly. Would love feedback on the approach.
Last week I presented "De-complecting clojure.spec" at Clojure South 2025, exploring how to evolve clojure.spec from a validation tool into a foundation for self-discoverable semantic services.
The key insight: by changing spec's registry from a 1-to-1 mapping (namespaced-keyword → spec) to a 1-to-N mapping (namespaced-keyword → {namespaced-keyword → value|spec}), we can create RDF-compliant semantic systems while solving Rich Hickey's "Maybe Not" problem of context-dependent requirements.
If systems are just collections of definitions, why do we scatter those definitions across code, diagrams, wikis, Slack threads, and tribal knowledge?
This article explores compound identities —using sets of semantic keywords instead of flat strings to define system entities. The key insight: `#{:semantic-namespace/error :domain.payment/timeout}` reads like plain English ("an error in the payment domain, specifically a timeout"), and becomes queryable:
```clojure ;; What can go wrong with payments? (find-docs #{:domain.payment})
;; What are all critical errors? (find-docs #{:severity/critical}) ```
A mid-sized project has 500-1000 such definitions (errors, events, endpoints, metrics, permissions, etc.). Right now they're scattered. What if they were unified, typed, and queryable in one registry?
The system becomes self-describing. Everything else (API docs, monitoring dashboards, tests) can be generated from the definitions.
Built in Clojure but the concept applies broadly. Would love feedback on the approach.