[ANN] Morphe: an aspect-oriented tool

303 views
Skip to first unread message

Timothy Dean

unread,
Jun 24, 2019, 1:03:06 PM6/24/19
to Clojure
An aspect-oriented library for Clojure

Most aspect-oriented patterns I have seen in Clojure work one of two ways: first, via rebinding var roots dynamically; or second, via functional composition. While both of these patterns are perfectly adequate for many use cases, they are not (IMO) perfect solutions for all. If I wish to avoid dynamic rebinding or if I do not wish to eschew built-in language/tooling features (fn arglist metadata, docstrings, etc.), then typical patterns won't work. 

The following library provides an extension to Clojure's built-in `defn` form that allows you to tag your function definitions with compile-time macro transformations. It also provides very simple macro constructors for the most common use cases. It's not intended to replace dynamic decorations or functional composition, but to provide another useful tool in the box. The library's motivation is explained with a simple example here, and a more detailed comparison with other Clojure idioms is found here.


I've quite enjoyed building and using this library over the last few years, and I hope others can find it useful as well! I recently updated it to work with Clojurescript (but not self-hosted Clojurescript). This was an adventure, and it's quite possible there are some issues with the CLJS implementation that I have not yet discovered.

~Timothy Dean

Juraj Martinka

unread,
Jun 25, 2019, 3:35:00 AM6/25/19
to Clojure
Looks cool - thanks for sharing this.
What kind of aspects do you find to be used most often? Is it mostly logging/tracing/timing or also something else?
Roughly how much did you use these aspects in the codebase you worked on and in which parts of the application? (mostly edges?)

Jesús Gómez

unread,
Jun 25, 2019, 11:31:12 AM6/25/19
to clo...@googlegroups.com
After seeing the final product in your REDME, i.e:

(m/defn ^{::m/aspects [timed logged traced]} do-a-thing [x stuff] (.doThatThing x stuff))

My question would be: Is it possible that the final product would had use `defn` instead, given that the namespaced tag has all the needed information? e.g

(defn ^{::m/aspects [timed logged traced]} do-a-thing [x stuff] (.doThatThing x stuff))


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/74bda940-4f12-4bcb-b1d7-d21380a62b14%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Timothy Dean

unread,
Jun 26, 2019, 3:03:27 PM6/26/19
to Clojure
 
My question would be: Is it possible that the final product would had use `defn` instead, given that the namespaced tag has all the needed information? e.g

(defn ^{::m/aspects [timed logged traced]} do-a-thing [x stuff] (.doThatThing x stuff))

The var would be tagged, but `clojure.core/defn` won't apply the aspects. The only difference `morphe.core/defn` makes is that it applies the tags in between parsing the `defn` body and writing out the fn.


What kind of aspects do you find to be used most often? Is it mostly logging/tracing/timing or also something else?
 
I would say mostly telemetry, but exceptions to that rule included enforcing patterns around error-handling, resource management, or asynchrony, 

Roughly how much did you use these aspects in the codebase you worked on and in which parts of the application? (mostly edges?)

I don't have hard numbers, but by far the largest project that used this can be seen here (at least the parts that were open sourced). At one point in time I estimated that without this library that project would have been 15-25% larger (again, my memory is fuzzy) in LOC, but it's not something I tracked, and I don't know what the numbers look like now. Many uses were on the edges, but there were some (e.g., tracing) that sometimes weaved through the internals of a component.

~Timothy Dean
Reply all
Reply to author
Forward
0 new messages