Real World ClojurePractical information for improving your skill at building Clojure and ClojureScript applications.http://realworldclojure.com/
Thu, 20 Apr 2017 09:35:34 -0400Thu, 20 Apr 2017 09:35:34 -0400Jekyll v3.2.1On the Judicious Use of core.async<p>I remember when core.async was released. It was heralded as an example of the power of Lisp, because being a library it added an asynchronous programming model to a language, something that would usually be done by extending the compiler with syntax. This is certainly true.</p>
<p>It was also celebrated for bringing CSP to Clojure. There are probably many interesting remarks, both positive and negative, that could be made about the flavor of CSP that core.async implements, but I would like to cover a few practicalities that I have learned using core.async. First the bad:</p>
<p><strong>core.async tends towards imperative style.</strong> A <code class="highlighter-rouge">go</code> block is like a function in that it can capture local values in a closure, but it is not a function. A <code class="highlighter-rouge">go</code> block is not referentially transparent. It can have zero or more mutable input channels and zero or more mutable output channels. A <code class="highlighter-rouge">go</code> block encourages the use of <code class="highlighter-rouge">loop</code> (the most imperative construct in Clojure).</p>
<p><strong>core.async is infectious.</strong> This is especially true in ClojureScript where there is no blocking take. Any function that spawns a core.async process will generally return a value on a channel, and to read the channel you have to be in a <code class="highlighter-rouge">go</code> block, so they will propagate across your code base.</p>
<p><strong>core.async does no error handling for you.</strong> I understand why this is<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>, but it still feels kind of crappy when you discover that your application is deadlocked because a process is stuck waiting on a channel that will never have any data put to it, because another process died silently of an exception.</p>
<p><strong>core.async scrambles stack traces.</strong> Because of the way the <code class="highlighter-rouge">go</code> macro re-compiles your code into lightweight processes this is probably unavoidable, but again, it hits you right in the feels.</p>
<p><strong>core.async tends toward large, hairy go blocks.</strong> The <code class="highlighter-rouge">go</code> macro has to be able to see (lexically speaking) any use of <code class="highlighter-rouge">&lt;!</code> or <code class="highlighter-rouge">&gt;!</code>, so you will be gently encouraged to make incomprehensibly big <code class="highlighter-rouge">go</code> blocks.</p>
<p>Of course like anything, there is another side. The good:</p>
<p><strong>Similar in both clojure and clojurescript.</strong> It is pretty cool to be able to write similar code in both Clojure and ClojureScript. You can even write cross platform code in cljc files.</p>
<p><strong>Transducers on channels.</strong> Transducers are very cool, and the fact that you can define a transformation process and apply it to a channel is very nice.</p>
<p><strong>Lightweight processes.</strong> It is useful to have the option to start 10k processes without consuming as many resources as threads.</p>
<p>I think the drawbacks of core.async can be summarized thusly: it is too low-level. You end up specifying how and where instead of just specifying what.</p>
<p>Whatever the drawbacks, core.async is very much worth using, so here are some ideas for how to use it judiciously:</p>
<ol>
<li>
<p><strong>Use it sparingly.</strong> core.async processes are lightweight, but like any threading model, there is overhead. Break up the work your application does into chunks that are neither too large nor too small.</p>
</li>
<li>
<p><strong>Do not use it in libraries.</strong> There may be exceptions, but most libraries should not use core.async. Once you do, you are forcing a particular concurrency model on users of your library (and one that is infectious).</p>
</li>
<li>
<p><strong>Build abstractions that use core.async.</strong> Think about what your application is doing, and write code that tells the computer what to do (not how). Is your application a processing pipeline? Model it as stages that are sewn together. Model using data structures or even records and protocols that are implemented with core.async hidden behind your abstraction.</p>
</li>
<li>
<p><strong>Be very, <em>very</em> conscientious about exceptions.</strong> This is another reason to build abstractions instead of using core.async directly. If you are not eternally vigilant about exceptions, you will deadlock your application, and the stack trace you get will be useless for debugging.</p>
</li>
</ol>
<p>I think of core.async like manual memory management or writing multi-threaded programs with locks: too low-level to be used directly except in exceptional circumstances.</p>
<p>Interestingly, at Clojure/West 2017 Tim Baldridge also had some practical tips about using core.async usage. You might checkout his <a href="https://www.youtube.com/watch?v=096pIlA3GDo">talk</a>.</p>
<div class="footnote-sep"></div>
<p>Footnotes:</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>Why? Imagine there’s a core.async process that is attempting to put on a channel, but it gets an exception. First of all, it is not immediately obvious that some special value should be put on the channel. What if the process eventually would attempt to put on multiple channels? Should all of them get some special error value? Now imagine that more than one process is waiting on one of these channels. Should that error value be sent to each process? If the channel is a broadcast channel that would make sense, otherwise one process would get lucky and pull the error value and the rest would still deadlock, but how does core.async know if a channel is a broadcast channel? etc. etc. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Wed, 19 Apr 2017 06:57:00 -0400http://realworldclojure.com/on-the-judicious-use-of-core.async/
http://realworldclojure.com/on-the-judicious-use-of-core.async/One Weird Trick To Become a Clojure Expert<blockquote>
<p>The Clojurists hate me!</p>
</blockquote>
<p>It is sometimes difficult to remember the path you took to reach proficiency. This makes it difficult to help others reach proficiency. I have this problem with Clojure. I’ve been using it for so long that I forget what I did to get better at it, other than just writing lots of code. (This is actually not a bad idea. Reading and writing lots of Clojure code is probably the best way to get better at writing Clojure code. Play golf with yourself. Solve the same problem over and over trying to use the fewest lines of code. Find an open source library and rewrite it from scratch on your own. Reading and writing lots of Clojure code a great way to get better at writing Clojure code, but that’s not my one weird trick.)</p>
<p>However, I do remember one decision I made that had a very positive impact on my Clojure skill. It only takes about an hour or two, and at the end you will accumulate an amazing amount of knowledge about how Clojure works and how you can use it effectively. It is a weird trick, and you have to be brave enough to do the unconventional. Here it is. Are you ready?</p>
<p><strong>READ THE DOCS!</strong></p>
<p>I’m not even joking! Go to this URL <a href="http://clojure.github.io/clojure/clojure.core-api.html">http://clojure.github.io/clojure/clojure.core-api.html</a> and start reading from top to bottom. If you did not read through that page, you may not know about <code class="highlighter-rouge">amap</code>. If you stopped reading before you get to ‘f’ you wouldn’t know about <code class="highlighter-rouge">frequencies</code>. However, if you read all the way through, you will be rewarded with knowledge about <code class="highlighter-rouge">vary-meta</code>.</p>
<p>Imagine you had a sequence of data, and you wanted to count the number of occurrences of each unique value. You could spend a lot of time writing code, or you could just use <code class="highlighter-rouge">frequencies</code>.</p>
<p>Now I recognize that it may not be immediately clear what a function does by reading its docstring. Here are three ways to fix that:</p>
<ol>
<li>While you’re reading the docs maintain an open REPL session and try any function that is not clear to you. Call it with a few different arguments. Poke it and try to figure out how it works.</li>
<li>Hop over to <a href="http://clojuredocs.org/">ClojureDocs</a> and look up the function. At ClojureDocs you’ll find examples that can provide illumination.</li>
<li>Read the source for the function. If you click the “Source” link under a function it will send you to the GitHub repo and you can see how the function is implemented.</li>
</ol>
<p>Pick one, or try all three. You can do this while you’re reading through the <code class="highlighter-rouge">clojure.core</code> documentation, or you can just make note of functions that are not clear to you, then for 15 minutes every day take a function from your list an conquer it. Eventually that list will be empty! :)</p>
<p>Take the time to invest in yourself. Reading through the docs will give you a great overview of the possibilities of <code class="highlighter-rouge">clojure.core</code>, and practicing with those function in the REPL will solidify that knowledge. The next time you are writing Clojure code, you will have easy access to the perfect function, right when you need it.</p>
Mon, 05 Dec 2016 06:11:00 -0500http://realworldclojure.com/one-weird-trick/
http://realworldclojure.com/one-weird-trick/The System Paradigm<p>One of my favorite talks is <a href="http://www.infoq.com/presentations/Mixin-based-Inheritance">“Engineering(,) A Path to Science”</a> by Richard Gabriel.<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup> He relates an experience he had with incommensurability and a paradigm shift from systems to languages. Gabriel had been involved in engineering Lisp systems, publishing papers, organizing and speaking at conferences, then he went back to school to earn a Master of Fine Arts, upon returning to engineering the landscape had changed.</p>
<p>At first Gabriel thought that while he was gone there had been a shift from an engineering paradigm to a scientific paradigm, but eventually he saw it more focused. It was a microparadigm shift from a system paradigm to a language paradigm.</p>
<p>In the system paradigm, people build systems of interacting components forming a whole; real things doing real stuff. One could observe and experiment with a running system as if it were a living being. With the language paradigm, people define languages with symbols and grammars that convey meaning. Compilers make mathematical transformations that preserve the meaning of the symbols.</p>
<p>Good design for the system paradigm is the result of an experienced technician putting skills, knowledge, and best practices to use. The system can help with good design, but good design springs from the art and skill of the programmer. Good design in the language paradigm is the result of a language designer carefully crafting the rules of grammar to make bad design ungrammatical; the compiler enforces good design by enshrining good techniques into the rules of the language.</p>
<p>There is much more to enjoy from Gabriel’s talk, and I highly recommend it. But the first time I heard it this idea of system vs. language was an important concept to me. I have a Masters degree in computer science, and I like to read academic papers. I used to call myself an “armchair computer scientist,” but I realized that I liked to think in the system paradigm. I liked to tinker with running programs. I started to self identify as an engineer. <em>I am an engineer</em>.</p>
<p>I also had a better understanding of why I liked to work in Clojure.</p>
<h2 id="organisms">Organisms</h2>
<blockquote>
<p>“Pascal is for building pyramids—imposing, breathtaking, static structures built by armies pushing heavy blocks into place. Lisp is for building organisms—imposing, breathtaking, dynamic structures built by squads fitting fluctuating myriads of simpler organisms into place.”</p>
<p>—Alan Perlis</p>
</blockquote>
<p>Another watershed moment for me was reading Structure and Interpretation of Computer Programs. I had been programming for a number of years and had even worked in Clojure for a while. SICP demonstrated to me the beauty of abstraction. It was also the first time I finally understood the power of Lisp macros and “metacircular interpretation.”</p>
<p>After Gabriel’s talk, when I looked at SICP again it was there all along—right there in the foreword by Alan Perlis—<em>“Lisp is for building organisms…”</em> Lisp is for building dynamic systems of organisms. Systems. Living things. Real things doing real stuff.</p>
<p>I have used a REPL connected to a production system to change code. Yes, I have changed code in a running production system. Does that terrify you? Honestly, it kind of terrifies me a little, too! Regardless, sometimes the best way—the only way—to diagnose a particularly nasty bug is to poke a living organism and observe the result. I am more like a doctor diagnosing a patient and less like a detective trying to piece together a sequence of events from the clues left behind.</p>
<p>A stack trace and heap dump are dead. It is far better to poke at a living thing than dissect a lifeless one.</p>
<h2 id="repl-the-ultimate">REPL the Ultimate</h2>
<p>One common complaint I have heard about Clojure is that you are forced to order the code in your source files. You must define or declare something before you can use it. In the early days of Clojure, Steve Yegge <a href="https://groups.google.com/d/msg/seajure/GLqhj_2915A/KgeKKXGO83UJ">famously complained about this</a>. A firestorm ensued, or at least what seemed like a firestorm to the small, young Clojure community.</p>
<p>Rich responded to Steve in <a href="https://news.ycombinator.com/item?id=2467809">a comment on Hacker News</a>:</p>
<blockquote>
<p>“Should Clojure start requiring files and defining semantics for them? (it does not now)”</p>
</blockquote>
<p><em>Wait, what‽</em> Clojure does have files. You do require them. Has Rich lost his mind?</p>
<p>In this comment Rich explains The Lisp Way. A file of Lisp code is like a transcript of a REPL session. You can literally open a REPL, enter the top-level forms one-by-one, and produce the same effect in that REPL session as you would by requiring the file. The compilation unit of Clojure is not the file, it is the top-level form. The REPL is not this nice debugger bolted on to the side of Clojure, <em>it is Clojure</em>.</p>
<p>Furthermore, the REPL is a tool of the system paradigm, not the language paradigm. Each form you evaluate in the REPL adds another little organism to the larger system of organisms. You can see it in the way that Steve and Rich frame their arguments. Steve mentions C++ as a bad example of a language, and presumably has some good example in mind. He is talking about files and compilation; about the compiler having a broader view of your application than just a form at a REPL.</p>
<p>Rich has in mind a system. Since Common Lisp does what people want (allows a reference to an as yet undefined symbol) it seems possible to do something similar in Clojure. But Rich has thought about it and rejected it, and his argument for not doing it comes from the system paradigm. He does not like how it would affect the REPL experience and the way the system components interact with each other.</p>
<p>One of the hallmarks of incommensurability is using the same terms but meaning different things. Gabriel found this to be true in his experience with incommensurability between the system paradigm and the language paradigm.</p>
<p>In the language paradigm, a class is a static thing. It lives in a file and to change the class you change the file. In a system paradigm, a class is an organism in a running system. The Common Lisp Object System has rules for resolving an instance identity after its class has been modified. Such a thing is simply impossible in the language paradigm.</p>
<p>A Lisp programmer does not define semantics and then say, “hmm… how can I make this work at the REPL?” The REPL is the beginning and the end. REPL the Ultimate. Clojure has what I like to call “REPL semantics.”</p>
<p>When I interview developers for Clojure positions, I pay attention to their view of the REPL. I think someone who reaches for the REPL “gets it” whether consciously or not. They understand that programs are meant to be built incrementally, top-level-form-by-top-level-form. They understand the value of probing a running system.</p>
<h2 id="system-boundaries">System Boundaries</h2>
<p>Perlis’ organisms are nicely fractal. Pascal is used to construct pyramids which are made up of heavy blocks<sup id="fnref:2"><a href="#fn:2" class="footnote">2</a></sup>, not smaller pyramids. Lisp is used to make organisms out of organisms. It’s organisms all the way down. And all the way up.</p>
<p>If immutable data and controlled, explicit state work well for components in memory, would they not work well for a REST endopoint? If referential transparency simplifies reasoning about a call tree of functions, shouldn’t it do the same for reasoning about a constellation of microservices?</p>
<p>If REPL semantics are useful for a single Lisp process, would they also be useful for a distributed system?</p>
<p>I believe that we are building increasingly complex systems, and we will need to simplify, decouple, abstract, and isolate system components as much as possible, but that is not enough.</p>
<p>As we come up against SLAs for 99.99% uptime and zero downtime deploys, we will need to think about how we can gracefully build systems incrementally. What does component A do if component B is down? How does component B communicate to A that it is now using a new data format? How does component A ask B for the old format (because B should continue to support both otherwise the system grinds to a halt)?</p>
<p>Networks go down. Fixes are deployed. New features are rolled out. This is the real world with real things doing real stuff. Thinking of your application as a system—as a living thing—is especially useful when you’re working in a language like Clojure that lends itself to the system paradigm.</p>
<div class="footnote-sep"></div>
<p>Thanks to Vincent Storme, Phil Hagelberg, Rusty Bently, Devin Walters, and Jake McCrary for giving feedback on an earlier draft.</p>
<p>Footnotes:</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>It turns out that many of my favorite talks and papers are from Richard Gabriel. I’ve never met him, but I feel he and I are kindred spirits! :) <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
<li id="fn:2">
<p>A (not so) subtle jab at the Algol family of languages. <a href="#fnref:2" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Mon, 19 Sep 2016 08:00:00 -0400http://realworldclojure.com/the-system-paradigm/
http://realworldclojure.com/the-system-paradigm/Application Configuration<p>I have been involved in three large Clojure projects, and configuration is always a problem eventually to be solved. It may or may not surprise you to know that <em>each of these applications has handled configuration differently</em>. I have mixed emotions about that, because I wish we could have built on someone else’s work, but I also know that one size does not necessarily fit all. Two of those projects ended up open sourcing their configuration libraries, so perhaps we’re a little better off.</p>
<p>Why does one size not necessarily fit all? Configuration has several dimensions and each config library lies at a different intersection of the space. Configuration values can be compiled into your code, or they can be pulled at run-time from some external source. That external source can be the environment, a file on the file system, a resource on the classpath, JVM system properties, or even some external configuration service. Most applications will read config once at start up assuming it does not change, but some may want config that can change dynamically over the life of the process.</p>
<p>Keep these dimensions in mind as we examine five methods for defining config, three that work only for Clojure, one that works only for ClojureScript, and one that works for both. The Clojure only methods are <a href="https://github.com/weavejester/environ"><code class="highlighter-rouge">weavejester/environ</code></a>, <a href="https://github.com/sonian/carica"><code class="highlighter-rouge">sonian/carica</code></a>, and <a href="https://github.com/outpace/config"><code class="highlighter-rouge">outpace/config</code></a>. The ClojureScript method is the built in <code class="highlighter-rouge">goog-define</code> macro. The Clojure/ClojureScript option is <a href="https://github.com/adzerk-oss/env"><code class="highlighter-rouge">adzerk-oss/env</code></a>.</p>
<h1 id="weavejesterenviron">weavejester/environ</h1>
<p><code class="highlighter-rouge">environ</code> uses environment variables for configuration as has been made popular by <a href="https://12factor.net/">The Twelve-Factor App</a>, and it has advantages:</p>
<ol>
<li>Environment variables can be changed independently from code.</li>
<li>Since they are independent from code sensitive config is unlikely to be accidentally checked in.</li>
<li>They are programming language and operating system agnostic.</li>
</ol>
<p>However, there are other considerations that may or may not be disadvantages depending on your use case:</p>
<ol>
<li>All environment values are strings.</li>
<li>Environment values cannot be tweaked to change configuration for a running application.</li>
<li>Environment variables form a flat, un-namespaced map.</li>
<li>If there were a required config value, application code would have to ensure it is available as <code class="highlighter-rouge">environ</code> does not.</li>
<li><code class="highlighter-rouge">environ</code> does not have a feature for providing a default value.</li>
<li>Assuming a value is available, it also falls to application code to validate it, because <code class="highlighter-rouge">environ</code> will not.</li>
</ol>
<p>The last three considerations result from using a pull model, instead of a push model. environ is not so much “configuring” your application as it is providing a map of values from which your application can configure itself. I think this approach is problematic for a few different reasons that I will talk about when I get to <code class="highlighter-rouge">outpace/config</code>, but note that this is a problem with the pull model, not with using environment for configuration.</p>
<p>If you like the trade-offs, using environment as a source for configuration can be very useful, and environ is a great way to do that. You should consider <code class="highlighter-rouge">adzerk-oss/env</code> as it also takes configuration from the environment, but it uses a push model.</p>
<h1 id="soniancarica">sonian/carica</h1>
<p><em>Full disclosure: While at Sonian I was involved in writing the code that eventually became <code class="highlighter-rouge">carica</code>.</em></p>
<p>The environment is not the only source for configuration values, files on the filesystem and resources on the classpath can also be sources of configuration. <code class="highlighter-rouge">carica</code> will pull configuration values from JSON, EDN, or Clojure files and resources. It will also merge multiple files on the classpath, which can be useful, but is also finicky as you will need to closely control the order of JARs and directories on the classpath. <code class="highlighter-rouge">carica</code> has some other features like middleware, but I think those are more nice-to-haves, and I want to focus more on the fundamentals.</p>
<p>Let’s revisit the advantages of environment variables, but with config files on the mind. Config files can also be changed independently from code. In some cases <code class="highlighter-rouge">carica</code> expects you to check in your config files and build them into your JAR to make them available as resources. This can be great for some config, and dangerous for sensitive config. You can always have <code class="highlighter-rouge">carica</code> use a filesystem file or a resource on the classpath that is only available in production, but you might have to be more careful about what you put in config files. Finally, if you use JSON your config files can be somewhat programming language and operating system agnostic.</p>
<p>I don’t think we lose much with <code class="highlighter-rouge">carica</code> versus environment variables. We gain some advantages. Config files can have a richer set of values, and that is better than having only strings as values. <code class="highlighter-rouge">carica</code> also would allow us to change config values for a running application. By default <code class="highlighter-rouge">carica</code> uses a caching middleware which will not read changed values, but you can override that so that it will re-read the config files every time you ask for a config. There is a performance penalty to this approach, but you could probably use <code class="highlighter-rouge">carica</code> for two different sets of configs: those that do not change after loading the application and those that do. I’ll talk more about changing config for a running application when I wrap up this whole discussion.</p>
<p>However, we still have these considerations:</p>
<ol>
<li>Config files form a flat, un-namespaced map.</li>
<li>If there were a required config value, application code would have to ensure it is available as <code class="highlighter-rouge">carica</code> does not.</li>
<li><code class="highlighter-rouge">carica</code> does not have a feature for providing a default value. Presumably you would provide a default by baking a config file into your JAR, which you would override in production with a deployed config file on the filesystem or earlier on the classpath.</li>
<li>Assuming a value is available, it also falls to application code to validate it, because <code class="highlighter-rouge">carica</code> will not.</li>
</ol>
<p>Again, these considerations stem from the pull model of configuration.</p>
<h1 id="outpaceconfig">outpace/config</h1>
<p><em>Full disclosure: While at Outpace I was involved in maintaining the <code class="highlighter-rouge">config</code> project.</em></p>
<p>This is my favorite configuration library for Clojure, so I will try not to gush too much, and you will have to take what I say with a grain of salt.</p>
<p>While I was at Outpace, Alex Taggart wrote the <code class="highlighter-rouge">config</code> library, and the moment I saw it I instantly thought it brilliant. While most other configuration libraries are a pull model, <code class="highlighter-rouge">config</code> is a push model. It pushes root values to vars that are marked as configuration values using the <code class="highlighter-rouge">defconfig</code> macro:</p>
<div class="language-clojure highlighter-rouge"><pre class="highlight"><code><span class="p">(</span><span class="nf">defconfig</span><span class="w"> </span><span class="n">database-url</span><span class="p">)</span><span class="w">
</span></code></pre>
</div>
<p>You can define a required config var:</p>
<div class="language-clojure highlighter-rouge"><pre class="highlight"><code><span class="p">(</span><span class="nf">defconfig!</span><span class="w"> </span><span class="n">database-url</span><span class="p">)</span><span class="w">
</span></code></pre>
</div>
<p>You can provide a default value:</p>
<div class="language-clojure highlighter-rouge"><pre class="highlight"><code><span class="p">(</span><span class="nf">defconfig</span><span class="w"> </span><span class="n">database-url</span><span class="w"> </span><span class="s">"jdbc:postgresql://localhost/my_db"</span><span class="p">)</span><span class="w">
</span></code></pre>
</div>
<p>You can also provide validators:</p>
<div class="language-clojure highlighter-rouge"><pre class="highlight"><code><span class="p">(</span><span class="nf">defconfig</span><span class="w">
</span><span class="o">^</span><span class="p">{</span><span class="no">:validate</span><span class="w"> </span><span class="p">[</span><span class="nb">string?</span><span class="w"> </span><span class="s">"Must be a string."</span><span class="w">
</span><span class="n">super-cool?</span><span class="w"> </span><span class="s">"Must be super cool!"</span><span class="p">]}</span><span class="w">
</span><span class="n">database-url</span><span class="w">
</span><span class="s">"jdbc:postgresql://localhost/my_db"</span><span class="p">)</span><span class="w">
</span></code></pre>
</div>
<p>Since these are just vars, they can be marked <code class="highlighter-rouge">:dynamic</code> and/or <code class="highlighter-rouge">:private</code>, given type hints, bound, redefined, and anything else a var can do, and the Clojure compiler will helpfully point out if you are trying to reference a configuration var that does not exist. The only thing that is special about them is they receive a root value at load-time. <code class="highlighter-rouge">config</code> pulls in all the configuration values that it needs at load-time, so it is not possible to define config values that can change at run-time. Since they receive their value at load-time, not compile-time, AOT compiling will not trigger any I/O.</p>
<p>But wait there’s more! <code class="highlighter-rouge">config</code> will use a file on the filesystem to define the root values of your configuration vars. Using reader tags in the EDN file, <code class="highlighter-rouge">config</code> can pull values from the environment, a system property, a file on the filesystem, a resource on the classpath, or any other place for which you configure a reader tag. The configuration file is not really a configuration file, it is a layer of abstraction that binds a source for a configuration value with a destination for it.</p>
<p>One interesting consequence of this is it is safe to use <code class="highlighter-rouge">config</code> in a library, because using <code class="highlighter-rouge">defconfig</code> you only mark a var as a configuration value you do not make any assumptions about where it is coming from. And since each config var is namespaced there is no risk of collision over configuration names used by different libraries.</p>
<p>Finally, I think the most useful thing about <code class="highlighter-rouge">config</code> is its tool to generate a <code class="highlighter-rouge">config.edn</code> file. Using this tool you can generate a <code class="highlighter-rouge">config.edn</code> file that lists all of the configuration vars in your application (and the libraries it uses) and their default values if any. If a configuration var is required, it will also appear in the file waiting for you to give it a value. You can also run this tool with an existing <code class="highlighter-rouge">config.edn</code> file in place, and it will tell you if you are trying to configure vars that do not exist. The biggest drawback of the pull model for configuration is that you have no traceability between the config values that exist and the places in your code that use configuration, and my experience is config becomes a mess of vestigial values that no one dares remove. <code class="highlighter-rouge">config</code>’s generate tool will give you accurate information about your application and its complicated relationship with its config.</p>
<p><code class="highlighter-rouge">config</code> addresses all of the considerations of the previous libraries<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup> except that it does not allow values to be tweaked for running applications. The tradeoff is that we no longer have programming language or operating system agnosticism.</p>
<h1 id="goog-define">goog-define</h1>
<p>As of ClojureScript 1.7.107 there is a <code class="highlighter-rouge">goog-define</code> macro that can be used to define a value at compile-time. I think Martin Klepsch does a great job of <a href="https://www.martinklepsch.org/posts/parameterizing-clojurescript-builds.html">describing how to use <code class="highlighter-rouge">goog-define</code></a>. To that I will add these considerations:</p>
<ol>
<li>The config values are pulled from compiler options, not the environment. This is very much not programming language agnostic.</li>
<li>Each value must be a string, a number, or a boolean.</li>
<li>Config values are baked into the application. In advanced optimization mode they are propagated as constants.</li>
<li>You must specify a default value.</li>
<li>Assuming a value is available, it falls to application code to validate it, because—aside from basic type validation–<code class="highlighter-rouge">goog-define</code> will not.</li>
</ol>
<h1 id="adzerk-ossenv">adzerk-oss/env</h1>
<p>This is another 12factor style library. However, there are some differences from <code class="highlighter-rouge">environ</code>:</p>
<ol>
<li><code class="highlighter-rouge">env</code> will let you declare that a config is required, and an exception will be thrown if it is not provided.</li>
<li>You can specify a default value to be used if an environment variable is not available.</li>
<li><code class="highlighter-rouge">env</code> is also a push model, so there is more traceability about which config values are used where.</li>
<li><code class="highlighter-rouge">env</code> will pull from system properties in addition to the environment.</li>
<li>If you set the root value of a config var, that new value will get pushed into a JVM system property and subsequent attempts to read the environment will see the new value.</li>
</ol>
<p>We still have the following considerations:</p>
<ol>
<li>All environment values are strings.</li>
<li>Assuming a value is available, it falls to application code to validate it, because <code class="highlighter-rouge">env</code> will not.</li>
</ol>
<p>Additionally, remember that <code class="highlighter-rouge">env</code> works for both Clojure and ClojureScript, so that is a huge advantage.</p>
<h1 id="conclusion">Conclusion</h1>
<p>We have taken a look at <code class="highlighter-rouge">weavejester/environ</code>, <code class="highlighter-rouge">sonian/carica</code>, and <code class="highlighter-rouge">outpace/config</code>, <code class="highlighter-rouge">goog-define</code>, and <code class="highlighter-rouge">adzerk-oss/env</code>. We have considered each along several dimensions: compile-time vs. run-time, configuration source (the environment, a file on the file system, a resource on the classpath, JVM system properties), push model vs. pull model, config loaded once vs. config that can change.</p>
<p>I believe the push model to be far superior to the pull model, because you have better traceability over which configs are used and where they are used. With a push model you can also enforce required configs, default values, and validation. Additionally, a push model can allow safe use of configuration in libraries (as we saw with <code class="highlighter-rouge">outpace/config</code>).</p>
<p>We did see a couple of libraries that allow you to change config values at run-time. If you are building a 99.9999% available service, then you will need change the configuration of a running application. However, be reasonable. If you’re not paying 100 full-time engineers to work on your service, then don’t try to be Google. I would strongly caution you to be explicit about which configs are set once and which can change. In your code you must carefully handle configs whose value may change out from under you, otherwise you will open yourself up to weird concurrency related bugs. Specifically, if you are going to read a config value more than once during the course of a single task, you should read it once at the beginning of the task and use that value instead of re-reading the config. Or you could just take the 5 minutes of downtime. :)</p>
<p>In the end which configuration library you choose will depend on your use case and philosophy. You may choose a library that I didn’t even talk about, or you may chose to use more than one library for different classes of configs, and that’s all right, because there is no one-size-fits-all config library.</p>
<div class="footnote-sep"></div>
<p>Footnotes:</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>ahahahaha! <code class="highlighter-rouge">outpace/config</code> defines the standards to which the other libraries must adhere! Classic Marketing Maneuver™ <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Tue, 06 Sep 2016 19:29:00 -0400http://realworldclojure.com/application-configuration/
http://realworldclojure.com/application-configuration/Conj 2016 Opportunity Grant Campaign<blockquote>
<p>This campaign has ended, and we collected $160 for the Opportunity Grant program. Thanks for participating!</p>
</blockquote>
<p>I sold the 100th copy of <em>Clojure Polymorphism</em> on Leanpub! In the grand scheme of things that is pretty small potatoes, but for me this is all new and exciting! :)</p>
<p>I have been involved for a long time in this amazing Clojure community, and in celebration of such an insignificant and arbitrary milestone I’d like to do something to give back.</p>
<p><strong>September 6 through September 16, 2016, I will donate 100% of my proceeds for Amazon sales of <em>Clojure Polymorphism</em> to the Clojure Conj 2016 Opportunity Grant program.</strong> You can read about the Opportunity Grant program at the <a href="http://2016.clojure-conj.org/opportunity-grants/">Clojure Conj 2016 website</a>.</p>
<p>I would like to get more exposure for my book on Amazon, and that is what I hope will happen with this campaign. While I could get exposure some other way, I’d rather do something that will help the community at the same time.</p>
<p>If you would simply like to support the Opportunity Grant program, you can do so when you register for the Conj. If you have an interest in <em>Clojure Polymorphism</em>, you can support the Opportunity Grant program and buy it at the same time!</p>
<p>The campaign will run September 6-16, because the deadline for opportunity grant applications is September 16, and I would like to give people as much time as possible to both help with the campaign and make applications for a grant.</p>
<h1 id="are-you-with-me">Are you with me?</h1>
<p>If you would like to buy my book and support the 2016 Clojure Conj Opportunity Grant program at the same time, you can purchase the book through this link: <a href="https://www.amazon.com/gp/product/B01LB7NU34/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=realworldcloj-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=B01LB7NU34&amp;linkId=f9fe7b3bc2a6fda14d41b0d07089973b"><em>Clojure Polymorphism</em></a><sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>. Thanks, and please help spread the word!</p>
<div class="footnote-sep"></div>
<p>Footnotes:</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>This is an affiliate link. I did not link to my <a href="/affiliate-policy/">Affiliate Policy</a>, because I’m not trying to sell someone else’s product. The affiliate proceeds will also be used to support the Opportunity Grant program. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Tue, 06 Sep 2016 08:00:00 -0400http://realworldclojure.com/conj-2016-opportunity-grant-campaign/
http://realworldclojure.com/conj-2016-opportunity-grant-campaign/Applying Clojure<blockquote>
<p>This post contains one or more affiliate links. See my <a href="/affiliate-policy/">Affiliate Policy</a>.</p>
</blockquote>
<p>I would broadly and inaccurately categorize materials about learning Clojure as: beginner, cookbook, deep-dive, and applied. Beginner materials will teach you syntax, how to create a project, how to setup an IDE, and take you through some example programs. Good examples of this kind of material would be <em><a href="https://www.amazon.com/Living-Clojure-Carin-Meier/dp/1491909048/">Living Clojure</a></em> and <em><a href="https://www.amazon.com/Clojure-Brave-True-Ultimate-Programmer/dp/1593275919/">Clojure for the Brave and True</a></em>.</p>
<p>Cookbook materials give you solutions to specific problems. It could be a general cookbook where you look up a problem and get a snippet of code. Some examples of the general cookbook style are <em><a href="https://www.amazon.com/Clojure-Cookbook-Recipes-Functional-Programming/dp/1449366171/">Clojure Cookbook</a></em> and <em><a href="https://www.amazon.com/Clojure-Recipes-Developers-Library-Julian/dp/0321927737/">Clojure Recipes</a></em>. In the cookbook category I would also include books that show you how to work in a particular domain, like <em><a href="https://www.amazon.com/Web-Development-Clojure-Build-Bulletproof/dp/1680500821/">Web Development with Clojure</a></em> and <em><a href="https://www.amazon.com/Clojure-Data-Science-Henry-Garner/dp/1784397180/">Clojure for Data Science</a></em>.</p>
<p>Deep-dive materials take one or more features of Clojure and explore them in-depth. This in-depth exploration might include looking at the various functions and parameters, talking about the philosophical underpinnings, discussing the implementation, or even looking at source code. These kind of materials include <a href="https://www.youtube.com/watch?v=R3PZMIwXN_g">Core Async Go Macro Internals Part 1</a> and <a href="https://www.youtube.com/watch?v=SI7qtuuahhU">Part 2</a>, and <em><a href="https://www.amazon.com/gp/product/1617291412/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=realworldcloj-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=1617291412&amp;linkId=bbb5b259866bfe95f2009b655105117b">Joy of Clojure</a></em> <span class="non-aff"><a href="https://www.amazon.com/Joy-Clojure-Michael-Fogus/dp/1617291412/">(non-aff)</a></span>.</p>
<p>Finally, applied materials help you understand trade-offs. They usually are based on lessons learned from using Clojure in the field. My ideal applied material would not just solve a problem, but would solve it several different ways, providing guidance about principles that can be extracted. I don’t see many materials with this learning-through-comparison approach. The idea is to learn from experience, and experience is best acquired by doing things over and over in different ways.</p>
<p>Materials in the first two categories tell you <em>what</em> to do. You are meant to emulate them directly. This is appropriate when you are getting started with something new. Deep-dive materials tell you <em>how</em> something works, and I think a richer understanding of a topic is always useful, though it may not help you develop your sense of design. As I imagine them, applied materials help you develop a refined taste for good Clojure design.</p>
<p>I think there is a process to learning. At first you are mostly imitating others, then as you become more familiar with the “vocabulary” and “grammar” of a topic you can begin to form your own “sentences” according to the rules. Eventually, you are able to see past the rules, decide when to apply them, and when to ignore them. First you walk, then crawl, then run and jump. First you follow recipes, then improvise, then write your own recipes. To put one more analogy to it, the beginner and cookbook materials are like giving someone fish, the deep-dive materials are like studying biology and ecology, the applied materials are like learning the art of fishing.</p>
<p>Is there a dearth of materials in the applied category? I think so. I am seeking to provide some applied materials like <em><a href="http://leanpub.com/clojurepolymorphism/">Clojure Polymorphism</a></em>, with others forthcoming. However, though there may not be many, there are some applied resources available. In fact, there’s one that has “applied” in its title: <em><a href="https://www.amazon.com/gp/product/1680500740/ref=as_li_tl?ie=UTF8&amp;tag=realworldcloj-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=1680500740&amp;linkId=44823a1fe9829ce0c33228a6b92e8f61">Clojure Applied: From Practice to Practitioner</a></em> <span class="non-aff"><a href="https://www.amazon.com/Clojure-Applied-Practitioner-Ben-Vandgrift/dp/1680500740/">(non-aff)</a></span>.</p>
<p>I bought this book when I was surveying for applied material to validate my intuition that there could be more, and maybe I could publish some. I found <em>Clojure Applied</em> to be fantastic, and well written. Here’s an except from Chapter 1, “Model Your Domain”:</p>
<blockquote>
<p>Maps and records both use the standard map collection functions for access and modification, but most of the time records are a better choice for domain entities. Records leverage features of the host platform—the Java Virtual Machine (JVM)—to provide better performance in several ways. Records define their type by creating a Java class with a field for each attribute. A record can thus take primitive type hints in its field definition and will create primitive fields in the underlying Java class, which priovides a more efficient representation and faster arithmetic for numbers. The underlying Java class also provides a place to implement Java interfaces and Clojure protocols, placing behavior directly on the record and providing the fastest possible dispatch for those cases.</p>
<p>Given that records give you well-known fields, a type, factory functions, and better performance, they should be your first choice for domain entities. Why might we use maps instead?</p>
<p>One specific case for which you should strongly consider maps is in public-facing APIs, whether they’re expected to be consumed by Java or by Clojure. In an API, it’s important to minimize the constraints on our callers. Requiring them to create instances of our record classes causes some of the details of those classes to be effectively public as well. In this case, maps with a well-known set of keys commit to less and are a simpler and better choice.</p>
</blockquote>
<p>This kind of practical, contextual wisdom obviously has its root in using Clojure for many different projects. When people would ask me what is a good book for learning Clojure, I would tell them to pick up one of the beginner books<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>, and then get <em>Joy of Clojure</em> as a second deeper dive. I believe now that a well supplied Clojure library should have a trilogy of books that includes <em>Clojure Applied</em>.</p>
<p>You may not agree with my categories or with the particular books I’ve put in each category. I’ll be the first to admit that no book falls purely into any one category. However, I hope that this is a useful framework for you to use when thinking about where you are and which materials can help you on your journey to Clojure mastery.</p>
<div class="footnote-sep"></div>
<p>Footnotes:</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>Many years ago the beginning book I recommended was <em><a href="https://www.amazon.com/Programming-Clojure-Stuart-Halloway/dp/1934356867/">Programming Clojure</a></em>. I was a technical reviewer for the first edition, but have not read the second edition, though I’m sure it is still excellent. There are so many great introductory books on Clojure, and I’m so far removed from that beginning phase that I hesitate to recommend anything specific. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Fri, 02 Sep 2016 00:00:00 -0400http://realworldclojure.com/applying-clojure/
http://realworldclojure.com/applying-clojure/Closeable Services<p>In my book <a href="https://www.leanpub.com/clojurepolymorphism/">“Clojure Polymorphism”</a> I use a service as an example for creating a polymorphic abstraction. The service is imagined to be a key-value blob store, like S3, Cloudfiles, or Azure.</p>
<p>I try as much as possible to focus the book on features that are compatible with both Clojure and ClojureScript, but here is a tip that is only useful in Clojure.</p>
<p>The main function in my example changes slightly for each implementation approach, but the core of it remains the same: we let the initialized service then enter a <code class="highlighter-rouge">try</code> block which closes the service in a <code class="highlighter-rouge">finally</code> block. Using a <code class="highlighter-rouge">finally</code> block means that the service will get closed whether the <code class="highlighter-rouge">try</code> block exits normally or via exception, and this is the safest way to ensure resources are cleaned up.</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">-main</span><span class="w">
</span><span class="p">[</span><span class="o">&amp;</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w">
</span><span class="c1">;; ... initialize some things ...
</span><span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">access-key</span><span class="w"> </span><span class="p">(</span><span class="nf">System/getenv</span><span class="w"> </span><span class="s">"AWS_ACCESS_KEY_ID"</span><span class="p">)</span><span class="w">
</span><span class="n">secret-key</span><span class="w"> </span><span class="p">(</span><span class="nf">System/getenv</span><span class="w"> </span><span class="s">"AWS_SECRET_ACCESS_KEY"</span><span class="p">)</span><span class="w">
</span><span class="n">storage-conn</span><span class="w"> </span><span class="p">(</span><span class="nf">storage/connect</span><span class="w"> </span><span class="n">access-key</span><span class="w"> </span><span class="n">secret-key</span><span class="p">)]</span><span class="w">
</span><span class="p">(</span><span class="nf">try</span><span class="w">
</span><span class="c1">;; ... initialize some more things, or maybe just do stuff ...
</span><span class="w"> </span><span class="p">(</span><span class="nf">finally</span><span class="w">
</span><span class="p">(</span><span class="nf">storage/close</span><span class="w"> </span><span class="n">storage-conn</span><span class="p">)))))</span></code></pre></figure>
<p>For this pattern Clojure has a built-in macro called <code class="highlighter-rouge">with-open</code>. However, you can only use <code class="highlighter-rouge">with-open</code> with an object that implements the <code class="highlighter-rouge">java.io.Closeable</code> interface. An advantage with defining your abstraction using a protocol (as opposed to plain functions or multimethods) is you can also implement <code class="highlighter-rouge">java.io.Closeable</code> for your service object:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">defrecord</span><span class="w"> </span><span class="n">S3Storage</span><span class="w">
</span><span class="p">[</span><span class="n">access-key</span><span class="w"> </span><span class="n">secret-key</span><span class="p">]</span><span class="w">
</span><span class="n">proto/IStorage</span><span class="w">
</span><span class="p">(</span><span class="nb">get</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">s3/get-object</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">put</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="w"> </span><span class="n">value</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">s3/put-object</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="w"> </span><span class="n">value</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">delete</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">s3/delete-object</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">))</span><span class="w">
</span><span class="n">java.io.Closeable</span><span class="w">
</span><span class="p">(</span><span class="nf">close</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">proto/close</span><span class="w"> </span><span class="n">this</span><span class="p">)))</span></code></pre></figure>
<p>Then the main function can be rewritten to:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">-main</span><span class="w">
</span><span class="p">[</span><span class="o">&amp;</span><span class="w"> </span><span class="n">args</span><span class="p">]</span><span class="w">
</span><span class="c1">;; ... initialize some things ...
</span><span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">access-key</span><span class="w"> </span><span class="p">(</span><span class="nf">System/getenv</span><span class="w"> </span><span class="s">"AWS_ACCESS_KEY_ID"</span><span class="p">)</span><span class="w">
</span><span class="n">secret-key</span><span class="w"> </span><span class="p">(</span><span class="nf">System/getenv</span><span class="w"> </span><span class="s">"AWS_SECRET_ACCESS_KEY"</span><span class="p">)]</span><span class="w">
</span><span class="p">(</span><span class="nb">with-open</span><span class="w"> </span><span class="p">[</span><span class="n">storage-conn</span><span class="w"> </span><span class="p">(</span><span class="nf">storage/connect</span><span class="w"> </span><span class="n">access-key</span><span class="w"> </span><span class="n">secret-key</span><span class="p">)]</span><span class="w">
</span><span class="c1">;; ... initialize some more things, or maybe just do stuff ...
</span><span class="w"> </span><span class="p">)))</span></code></pre></figure>
<p>The downside is there is no way to enforce this in the abstraction. Each implementation of the abstraction must individually implement <code class="highlighter-rouge">java.io.Closeable</code>. It would be possible if you were using the “Protocol + Client Namespace + Multimethod” approach to wrap the object as it gets returned from connect in a <code class="highlighter-rouge">Closeable</code> object, but that is the closest you could get:</p>
<figure class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">connect</span><span class="w">
</span><span class="p">[</span><span class="n">options</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">[</span><span class="n">obj</span><span class="w"> </span><span class="p">(</span><span class="nf">proto/connect</span><span class="w"> </span><span class="n">options</span><span class="p">)]</span><span class="w">
</span><span class="p">(</span><span class="nf">reify</span><span class="w">
</span><span class="n">proto/IStorage</span><span class="w">
</span><span class="p">(</span><span class="nb">get</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">proto/get</span><span class="w"> </span><span class="n">obj</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">put</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="w"> </span><span class="n">value</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">proto/put</span><span class="w"> </span><span class="n">obj</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="w"> </span><span class="n">value</span><span class="p">))</span><span class="w">
</span><span class="p">(</span><span class="nf">delete</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">proto/delete</span><span class="w"> </span><span class="n">obj</span><span class="w"> </span><span class="n">bucket</span><span class="w"> </span><span class="nb">key</span><span class="p">))</span><span class="w">
</span><span class="n">java.io.Closeable</span><span class="w">
</span><span class="p">(</span><span class="nf">close</span><span class="w"> </span><span class="p">[</span><span class="n">this</span><span class="p">]</span><span class="w">
</span><span class="p">(</span><span class="nf">proto/close</span><span class="w"> </span><span class="n">obj</span><span class="p">)))))</span></code></pre></figure>
<p>I find this ugly, because not implementing <code class="highlighter-rouge">java.io.Closeable</code> is a programmer mistake. If you were to use <code class="highlighter-rouge">with-open</code> with an object that does not implement <code class="highlighter-rouge">java.io.Closeable</code>, you would get an exception, you would go add that interface to the appropriate service implementation, you would double check all the other service implementations, and from that point on forevermore you would not get the exception anymore. Over the lifetime of your application maybe you would write 5-10 implementations of this service abstraction? Do you need to add a bunch of lines of code and an extra layer of run-time construct just because a programmer accidentally wrote the wrong code? The tradeoff doesn’t make sense to me.</p>
<p>What does make sense to me is taking advantage of platform interfaces and conventions to save myself time and lines of code. So if you’re implementing a service abstraction on the JVM throw a <code class="highlighter-rouge">java.io.Closeable</code> in there.</p>
Thu, 01 Sep 2016 03:41:30 -0400http://realworldclojure.com/2016/09/01/closeable-services/
http://realworldclojure.com/2016/09/01/closeable-services/"Clojure Polymorphism" Released!<p>I have released a short e-book (30 pages) titled <a href="https://www.leanpub.com/clojurepolymorphism/">“Clojure Polymorphism”</a>.</p>
<p>What is this book about?</p>
<blockquote>
<p>When it comes to Clojure there are many tutorials, websites, and books about how to get started (language syntax, set up a project, configure your IDE, etc.). There are also many tutorials, websites, and books about how language features work (protocols, transducers, core.async). There are precious few tutorials, websites, and books about when and how to use Clojure’s features.</p>
<p>This is a comparative architecture class. I assume you are familiar with Clojure and even a bit proficient at it. I will pick a theme and talk about the tools Clojure provides in that theme. I will use some example problems, solve them with different tools, and then pick them apart for what is good and what is bad. There will not be one right answer. There will be principles that apply in certain contexts.</p>
<p>In this installment, I will pick up the theme of “Polymorphism” looking at the tools of polymorphism that Clojure provides. Then I take a couple of problems and solve them several ways. At the end of it all, we look back at the implementations and extract principles. The end goal is for you to develop an understanding of tradeoffs and a taste for good Clojure design.</p>
</blockquote>
<p>I have some ideas for other e-books. Perhaps a concurrency tour of Clojure taking a look at futures, STM, reducers, core.async, etc. Or maybe talk about identity by looking at <code class="highlighter-rouge">atom</code>, <code class="highlighter-rouge">agent</code>, <code class="highlighter-rouge">ref</code>, <code class="highlighter-rouge">volatile!</code>, etc. Or maybe look at code quality tools. Or how to organize namespaces. Or adding a new data structure with <code class="highlighter-rouge">deftype</code>?</p>
<p>What would you like to see? <a href="/contact/">Contact</a> me. :)</p>
Tue, 30 Aug 2016 06:41:30 -0400http://realworldclojure.com/2016/08/30/clojure-polymorphism-released/
http://realworldclojure.com/2016/08/30/clojure-polymorphism-released/