Last active
December 30, 2015 01:19
-
-
Save aamedina/7755360 to your computer and use it in GitHub Desktop.
new multimethod template conventions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (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