Skip to content

Commit 8ce2352

Browse files
committed
Add examples and rationale to Exceptions, Naming, and Annotations
Fill in bare rules across three sections: add good/bad examples to reuse-existing-exception-types, prefer-with-open-over-finally, naming-protocols-records-structs-and-types, naming-unsafe-functions, and all five annotation keywords (TODO, FIXME, OPTIMIZE, HACK, REVIEW).
1 parent 0a72ead commit 8ce2352

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

README.adoc

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,19 @@ acronyms like HTTP, RFC, XML uppercase.)
960960
NOTE: `CapitalCase` is also known as `UpperCamelCase`, `CapitalWords`
961961
and `PascalCase`.
962962

963+
[source,clojure]
964+
----
965+
;; good
966+
(defprotocol Serializable ...)
967+
(defrecord HttpRequest ...)
968+
(deftype XMLParser ...)
969+
970+
;; bad
971+
(defprotocol serializable ...)
972+
(defrecord http-request ...)
973+
(deftype xml_parser ...)
974+
----
975+
963976
=== Predicate Methods [[naming-predicates]]
964977

965978
The names of predicate methods (methods that return a boolean value)
@@ -979,7 +992,20 @@ should end in a question mark
979992
=== Unsafe Functions [[naming-unsafe-functions]]
980993

981994
The names of functions/macros that are not safe in STM transactions
982-
should end with an exclamation mark (e.g. `reset!`).
995+
should end with an exclamation mark (e.g. `reset!`). The `!` signals
996+
to callers that the function has side-effects and should not be called
997+
inside a `dosync` block.
998+
999+
[source,clojure]
1000+
----
1001+
;; good
1002+
(defn save-user! [user]
1003+
(db/insert! user))
1004+
1005+
;; bad - side-effecting function without the ! warning
1006+
(defn save-user [user]
1007+
(db/insert! user))
1008+
----
9831009

9841010
=== Conversion Functions [[naming-conversion-functions]]
9851011

@@ -2236,9 +2262,38 @@ throw an exception -- throws an exception of a standard type
22362262
`java.lang.UnsupportedOperationException`,
22372263
`java.lang.IllegalStateException`, `java.io.IOException`).
22382264

2265+
[source,clojure]
2266+
----
2267+
;; good - use ex-info for data-carrying exceptions
2268+
(throw (ex-info "Invalid input" {:value x :reason :negative}))
2269+
2270+
;; good - use standard Java exception types
2271+
(throw (IllegalArgumentException. "x must be positive"))
2272+
2273+
;; bad - defining a custom exception type for no reason
2274+
(deftype MyCustomException [msg]
2275+
...)
2276+
----
2277+
22392278
=== Prefer `with-open` Over `finally` [[prefer-with-open-over-finally]]
22402279

2241-
Favor `with-open` over `finally`.
2280+
Favor `with-open` over `finally`. `with-open` guarantees that the
2281+
resource is closed even if an exception is thrown, with less
2282+
boilerplate and no risk of forgetting the cleanup step.
2283+
2284+
[source,clojure]
2285+
----
2286+
;; good
2287+
(with-open [rdr (clojure.java.io/reader "file.txt")]
2288+
(slurp rdr))
2289+
2290+
;; bad - verbose and easy to get wrong
2291+
(let [rdr (clojure.java.io/reader "file.txt")]
2292+
(try
2293+
(slurp rdr)
2294+
(finally
2295+
(.close rdr))))
2296+
----
22422297

22432298
=== Catching Throwables [[catching-throwables]]
22442299

@@ -2753,26 +2808,64 @@ with no note. This usage should be the exception and not the rule.
27532808
Use `TODO` to note missing features or functionality that should be
27542809
added at a later date.
27552810

2811+
[source,clojure]
2812+
----
2813+
(defn process-order [order]
2814+
;; TODO: Add support for discount codes.
2815+
(calculate-total order))
2816+
----
2817+
27562818
==== `FIXME` [[fixme]]
27572819

27582820
Use `FIXME` to note broken code that needs to be fixed.
27592821

2822+
[source,clojure]
2823+
----
2824+
(defn calculate-total [order]
2825+
;; FIXME: This doesn't account for tax in all regions.
2826+
(reduce + (map :price (:items order))))
2827+
----
2828+
27602829
==== `OPTIMIZE` [[optimize]]
27612830

27622831
Use `OPTIMIZE` to note slow or inefficient code that may cause
27632832
performance problems.
27642833

2834+
[source,clojure]
2835+
----
2836+
(defn find-duplicates [coll]
2837+
;; OPTIMIZE: O(n^2) — consider using a set for large collections.
2838+
(for [x coll y coll :when (and (not (identical? x y)) (= x y))]
2839+
x))
2840+
----
2841+
27652842
==== `HACK` [[hack]]
27662843

27672844
Use `HACK` to note "code smells" where questionable coding practices
27682845
were used and should be refactored away.
27692846

2847+
[source,clojure]
2848+
----
2849+
(defn user-name [request]
2850+
;; HACK: Parsing the token manually until we add proper auth middleware.
2851+
(-> request :headers (get "authorization") (subs 7) decode-token :name))
2852+
----
2853+
27702854
==== `REVIEW` [[review]]
27712855

27722856
Use `REVIEW` to note anything that should be looked at to confirm it
27732857
is working as intended. For example: `REVIEW: Are we sure this is how the
27742858
client does X currently?`
27752859

2860+
[source,clojure]
2861+
----
2862+
(defn retry [f n]
2863+
;; REVIEW: Should we add exponential backoff here?
2864+
(loop [i n]
2865+
(or (try (f) (catch Exception _ nil))
2866+
(when (pos? i) (recur (dec i))))))
2867+
----
2868+
27762869
==== Document Custom Annotations [[document-annotations]]
27772870

27782871
Use other custom annotation keywords if it feels appropriate, but be

0 commit comments

Comments
 (0)