Skip to content

Instantly share code, notes, and snippets.

@aamedina
Last active December 30, 2015 01:19
Show Gist options
  • Select an option

  • Save aamedina/7755360 to your computer and use it in GitHub Desktop.

Select an option

Save aamedina/7755360 to your computer and use it in GitHub Desktop.
new multimethod template conventions
(def account-columns
"Columns for the account model. Will be used to specify
the content of the generated table header cells."
[{:name :select-all
:content "Select All"}]
(defmulti th
"Multimethod template function. Dispatches on the value specified.
If the value is a keyword and the first argument to the function when called is a map,
it looks up the value in the map for itself. E.g. given {:name :select-all}, calling
(:name {:name :select-all}) returns :select-all, which is the value the multimethod is
dispatched on."
:name)
(defmethod th
"Template for the select all cell. node is a function which returns
a DOM Element for the given markup."
:select-all
[column]
(node [:th {:id (:name column)} (:content column)]))
(defmethod th
"Default method implementation for table header cells."
:default
[column]
(node [:th (:content column)]))
(deftemplate thead
"Write your parent template code once. If you know that the children
of this template may have many differnt templates, implement it as a multimethod!
That way every new cell you have to design can simply be defined as above, without
having to redefine or even touch this function again. Extensibility made simple."
[columns]
[:thead
[:tr
(for [column columns]
(th column)))
(comment
(thead account-columns) =>
<thead>
<tr>
<th id=":select-all">"Select All"</th>
</tr>
</thead>
"So why multimethods? Because the alternative is writing code like this: "
(deftemplate th
[column]
(if (= (:name column) :select-all)
(node [:th {:id (:name column)} (:content column)])
...
(if...
(if...
(if...))
"Which means this function will scale linearly with the number of different cell designs you want to make!
But the real problem is that in order to make a change, update this function, or add a new template
you have to understand the entirety of this function. This is a trivial example, but in production I'm sure you've seen
large, convoluted if/elses, switch statements, and their related irk that are confusing. With multimethods you can just
write a new function and you're done!"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment