<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.brandonbloom.name/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.brandonbloom.name/" rel="alternate" type="text/html" /><updated>2025-01-02T07:01:16+00:00</updated><id>https://www.brandonbloom.name/feed.xml</id><title type="html">You work for me, Computer.</title><subtitle></subtitle><entry><title type="html">Unix and Microservice Platforms</title><link href="https://www.brandonbloom.name/blog/2021/08/02/unix-and-microservice-platforms/" rel="alternate" type="text/html" title="Unix and Microservice Platforms" /><published>2021-08-02T00:00:00+00:00</published><updated>2021-08-02T00:00:00+00:00</updated><id>https://www.brandonbloom.name/blog/2021/08/02/unix-and-microservice-platforms</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2021/08/02/unix-and-microservice-platforms/"><![CDATA[<p>“Code the Perimeter” is the key insight of <a href="https://archive.ph/o/uboBU/https://www.youtube.com/watch?v=3Ea3pkTCYx4">Kevin Greer’s fabulous 2016
analysis of why Unix beat Multics and what it means for Google’s mission to
organize the world’s information</a>. If you haven’t seen it, it’s well worth 7
minutes of your time.</p>

<p>In the 1960s, implementing a new operating system was considered a herculean
effort, akin to the moon landing. Greer explains how just two engineers –
Dennis Richie and Ken Thompson – accomplished such a feat while building Unix.
Somehow, they managed to outpace the development of a large team of their
contemporaries building Multics.</p>

<p>Greer’s argument is summarized by the following image. It shows a simulation
of Ritchie and Thompson implementing Unix – represented by the two red dots on
the right – as compared to the many blue dots on the left implementing
Multics. The rows represent types of data and the columns represent features.
The cells represent implementation progress. Unix’s approach to filesystems
and pipes meant that they were able to “code the perimeter.” Richie and
Thompson were therefore able to fill the area in O(N+M) effort instead of
O(N*M).</p>

<p><img src="/images/code-the-perimeter.png" alt="Unix's code the perimeter approach allows a much smaller team to fill the implementation matrix much more efficiently." /></p>

<p><a href="https://archive.ph/o/uboBU/https://en.wikipedia.org/wiki/Unix_philosophy">Unix Philosophy</a> is best summarized by Doug McIlroy:</p>

<blockquote>
  <p>Write programs that do one thing and do it well. Write programs to work
together. Write programs to handle text streams, because that is a universal
interface.</p>
</blockquote>

<p>Often, this philosophy is further shortened to just the first sentence. The
importance of the second and third sentences is oft-ignored. This shortening
is no longer a valid summary! It’s not enough to write programs that do one
thing well. You must also write programs that work together, utilizing
universal interfaces.</p>

<p>“Programs should do one thing” is often invoked to justify favoring
micro-services over monoliths. However, in the absence of collaboration over
universal interfaces, you’re likely to find yourself coding the area instead
of the perimeter. You wanted linear complexity, but all you got was
rectangular complexity with an extra helping of distributed systems
complexity.</p>

<p>Cloud computing is still at the Multics stage of evolution. We can do better.
To do so, let’s analyze microservice development using Greer’s framework.
Consider all the functionality expected of a modern, production-caliber web
service. The list is massive, but to name a few: authentication,
authorization, metrics, monitoring, alerting, provisioning, deployment,
testing, logging, and tracing! And these requirements are fractal. If you zoom
in, you’ll find each area is rich enough to have more than a couple of
venture-funded startups attempting to address just that one area. Even if you
use this functionality-as-a-service from one of these vendors, you still need
to do the integration work.</p>

<p>If you’re building a monolith, your implementation matrix looks like this:</p>

<p><img src="/images/monolith-table.png" alt="A modern web service requires the implementation of many features, including Authn, Authz, Metrics, Monitoring, Alerting and Deployment." /></p>

<p>Here, functionality is rows and services are columns. Once you add additional
services, the matrix looks like this:</p>

<p><img src="/images/microservice-table.png" alt="Multiple services requires re-implementation of the same features for each service." /></p>

<p>If you’re lucky enough to have a platform team at your company, they’ve got
their work cut out for them! Hopefully, they are not running around the area
of the matrix like the many blue dots working on Multics, individually
configuring functionality for each service. If you’re not so lucky to have an
army of blue dots, you’re doomed unless you either (A) keep the number of
services small or (B) code the perimeter!</p>

<p>This is where the second sentence of the Unix philosophy comes in: write
programs to work together. For example, instead of configuring metrics once
for each service, you might write a single reusable library (Unix philosophy
point #1) that can be embedded into each service to act as the glue between
that service and the common metrics service (point #2). Designing and
implementing these glue libraries is not easy, but it is generally
straightforward, and it’s linear work, not square.</p>

<p>OK, so let’s say you follow this approach. Twitter did precisely this with
their <a href="https://archive.ph/o/uboBU/https://twitter.github.io/finagle/">Finagle RPC
system</a>.
Functionality like request metrics, traffic splitting, retries, and more was
coded once and then shared across every service at Twitter. Well, that is,
every service at Twitter that <em>runs on the JVM</em>.</p>

<p>See, the brilliance of Unix didn’t stop at functional orthogonality, they also
used C: A high-level programming language, as compared to machine-specific
assembly code. Once Unix started getting ported to new hardware architectures,
the two-dimensional implementation matrix becomes three-dimensional.</p>

<p><img src="/images/perimeter-3d.png" alt="Unix's high-level, code the perimeter approach allows it to adapt to new hardware, while Multics falls behind." /></p>

<p>Now point number three of the Unix Philosophy comes into play: Use universal
interfaces. The C abstract machine was close enough to a universal interface
that the developers of Unix were still coding the perimeter, instead of the
volume!</p>

<p>Turning our attention back to microservices, let’s further examine the Finagle
RPC framework example. As Twitter’s data science and machine learning efforts
grew, so too has their usage of Python. Polyglot programming is inevitable.
However, Finagle is a JVM solution. It’s insufficiently universal to be
applied to Python programs. If you want to get this functionality, you’re now
coding the area of a 2D slice in the 3D space of services, functionality, and
programming languages.</p>

<p>Cloud computing can escape the Multics stage of evolution. Sticking with the
Finagle and the RPC example, we are beginning to see the adoption of service
meshes. While still nascent, service meshes hold promise. They do one thing
well: enhance network traffic with important operational functionality.
Service meshes work together with other programs: by running as sidecars,
embeddable with each service. And they utilize universal interfaces: TCP,
HTTP, etc. As a result, a service mesh is coded once and immediately
applicable to every service in every language.</p>

<p>Zooming out of the fractal complexity of RPC, we as a community need to find
Unix-style solutions to a wide range of additional service-oriented
architecture concerns. Our journey towards coding the perimeter is only just
beginning. We can imagine a future in which each service, coded in any
language, created at every company, comes into existence ready-to-go for a
“production-caliber” deployment. This future is possible only by coding the
perimeter, which requires embracing the Unix philosophy fully: all three
sentences of it.</p>

<blockquote>
  <p>This was originally posted to the the blog of my now defunct startup, Deref.
I’ve republished it here for archival and my own future reference.</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[“Code the Perimeter” is the key insight of Kevin Greer’s fabulous 2016 analysis of why Unix beat Multics and what it means for Google’s mission to organize the world’s information. If you haven’t seen it, it’s well worth 7 minutes of your time.]]></summary></entry><entry><title type="html">Structural and Relational Data</title><link href="https://www.brandonbloom.name/blog/2017/07/05/structural-and-relational-data/" rel="alternate" type="text/html" title="Structural and Relational Data" /><published>2017-07-05T09:21:00+00:00</published><updated>2017-07-05T09:21:00+00:00</updated><id>https://www.brandonbloom.name/blog/2017/07/05/structural-and-relational-data</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2017/07/05/structural-and-relational-data/"><![CDATA[<p><em>Before reading this post, see the introductory post for this series:
<a href="http://www.brandonbloom.name/blog/2017/05/24/particles-and-waves/">Particles and Waves</a>.</em></p>

<p>Among our goals is the desire to understand the duality of data and code. This
duo represents one of the most fundamental pairs of particles and waves in
software. However, careful selection of a bounded context can reveal particles
and waves at any level. Combined with the observation that particles and space
are generally easier to recognize and reason about than waves and time, let’s
zoom in on data before tackling code.</p>

<h2 id="data-structures">Data Structures</h2>

<p>Perhaps surprisingly, there is only a small number of foundational abstract
data types. <a href="https://en.wikipedia.org/wiki/Abstract_data_type#Examples_2">Wikipedia lists some common examples</a>: List, Set, Multiset
(Bag), Map, Graph, Stack, Queue, Priority Queue, etc. If you squint just right,
there are really only two fundamental types of data containers: lists and bags.
Every simple data structure can be classified as ordered or unordered. Common
modes of use, such as FILO stacks and FIFO queues, are really just
specializations of more generalized lists. Similar for maps and graphs; these
are specialized bags. More complex data structures can be recognized as a
careful composite of ordered and unordered substructures. Even the ubiquitous
map can be viewed as a bag of lists, where each list is a key/value pair,
constraining keys to be unique.</p>

<p>Individual data structures are the traditional particles we think of when we
think about the data in our code. From a typical vantage point, the context
that bounds these particles is so far away that we generally don’t ever
perceive it. It’s only when we take a step back from a fragment of code and
look at a complete system that we can perceive a common and relevant bounded
context: a “database”.</p>

<h2 id="databases">Databases</h2>

<p>Numbers, such as <code class="language-plaintext highlighter-rouge">5</code>, or strings, such as <code class="language-plaintext highlighter-rouge">"foo"</code>, have sufficient structure to
be recognized in our shared global context made up of decimal numbers and
unicode. However, <code class="language-plaintext highlighter-rouge">5</code> is useless on its own. We need to know how to interpret
it. For that, we need more shared context. Let’s introduce a database with a
fruit table and say that our favorite number is a fruit ID. Now we can lookup
up the fruit ID and find out that we’re talking about bananas. It turns out
that our number particle is just one  of many particles in a banana wave
traveling through our database medium.</p>

<p>By changing our perspective, we can study other bounded contexts, revealing
more waves. When this happens, there tends to be an inversion: ordered becomes
unordered and vice versa. Additional inversions are explored in sections below.
For now, let’s choose the perspective of a programming language runtime
implementer. From this vantage point, the heap is a database. A simple ordered
data structure such as a pair, is actually represented with pointers, no
different than our banana ID. The pair structure arrises from the interplay
between a ordered structure with two pointers and an unordered structure, a
map, encoded as memory itself, that translates addresses to objects. Shift your
perspective again, from application user-space to operating system kernel-space
and the question of whether memory is ordered or unordered depends on your
perspective on virtual memory.</p>

<p>One common form of data warrants a special note: graphs. The easiest
representation of a graph in a traditional programming language is to utilize
memory pointers. However, this representation is impoverished. It forcibly
equates nodes with their graphs that they are part of and sets an implicit
boundary equal to all of memory. As much as possible, graphs and nodes should
be clearly delimited. A graph should rightfully be considered as a database of
nodes.</p>

<h2 id="openness">Openness</h2>

<p>For the sake of concision, I will refer to data built up from other data in the
implicit “global” context as “structural data”, or simply “structures”.
Similarly, data derived from the relationship between structures and an
explicit context will be referred to as “relational data”, or simply
“relations”. These shorthands are not to be confused with the more specific
concepts of C-style “structures” or traditional relational database
“relations”, despite my abuse of the intentional analogies.</p>

<p>A key distinction and advantage of relational data is its inherit openness. One
fruit ID may appear in many tables. Adding a new table to a database extends
the meaning of that fruit ID without impacting any existing relations. We can
also extend the meaning of that one fruit ID by moving the context boundary:
switch databases, connect to a second database, talk to an external fruit
service, etc. By contrast, structural data is closed. Structural data can only
be “extend” by replacing it with a slightly varied structure; appending an
element to a four element list produces a new list of five elements.</p>

<p>Time is the most important dimension of openness. Growth occurs over time as we
add tables to a database, <code class="language-plaintext highlighter-rouge">mmap</code> additional pages in to virtual memory, or
simply add keys to a map. The impact of time on the interpretation of data is a
massive topic, to be discussed at another — *ahem — *time.</p>

<h2 id="cutting-along-the-grain">Cutting Along The Grain</h2>

<p>Much pain in software designs stems from a conflict between the programmer’s
intuition and the nature of the data they are working with. Each kind of data
“wants” to be used in a particular way. Given the ability to recognize
structures and relations, we can choose the most appropriate end of this
duality spectrum; then choose strategies for working with such data according
to its wants.</p>

<p>Here’s a summary of each kind of data’s respective usual wants:</p>

<table>
<tr><th>               </th><th>   Structures         </th><th>  Relations        </th></tr>
<tr><th> Order         </th><td>   Ordered            </td><td>  Unordered        </td></tr>
<tr><th> Substructure  </th><td>   Positional         </td><td>  Associative      </td></tr>
<tr><th> Mutability    </th><td>   Immutable          </td><td>  Mutable          </td></tr>
<tr><th> Hierarchy     </th><td>   Contain Children   </td><td>  Point To Parents </td></tr>
<tr><th> Construction  </th><td>   Bottom-Up          </td><td>  Top-Down         </td></tr>
<tr><th> Cycles        </th><td>   Acyclic            </td><td>  Cyclic           </td></tr>
<tr><th> Limits        </th><td>   Finite             </td><td>  Infinite         </td></tr>
</table>

<p>Each of these wants can be overridden by moving the bounds of your context.
Stuff tuples in to the context of a table to exploit associativity; or scope
the context of a database to a transaction to build relations out of temporary
ids, bottom-up.</p>

<p>Again, time is too vast a topic to discuss in detail here. Suffice to say, time
can be bounded by “stopping” it and/or by choosing a time slice. Stopped time
turns the mutable in to immutable and a time slice can turn the infinite in to
the finite. Conversely, stopped or sliced time can be started and opened again:
stick an immutable structure in a mutable box or connect a live pipe to a
queue.</p>

<h2 id="perspective">Perspective</h2>

<p>This perspective has dramatically hastened and improved how I design software.
Carefully considering bounded contexts strongly guides many design choices. In
situations where I used to find myself flip-flopping on some tradeoff, I now
find myself happily choosing and committing to an appropriate blend of
structural and relational data. Future posts in this series will revisit this
tradeoff through some more concrete examples.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Before reading this post, see the introductory post for this series: Particles and Waves.]]></summary></entry><entry><title type="html">Particles and Waves</title><link href="https://www.brandonbloom.name/blog/2017/05/24/particles-and-waves/" rel="alternate" type="text/html" title="Particles and Waves" /><published>2017-05-24T09:45:00+00:00</published><updated>2017-05-24T09:45:00+00:00</updated><id>https://www.brandonbloom.name/blog/2017/05/24/particles-and-waves</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2017/05/24/particles-and-waves/"><![CDATA[<p>If simpler is better, is fewer better? Is one better than two? When
designing programming constructs, there is a tendency towards
<a href="http://blog.ezyang.com/2012/11/extremist-programming/">extremist programming</a>. There is power and beauty in a grand unified
approach that has just one class of elements. Alluring as singularity may be,
these one-element approaches tend to fail in ways that more complex designs do
not. Hybrid approaches tend to win in the end. Why? And how should this
reality inform our designs? Can we predict and enable hybrid solutions?</p>

<p>During the 17th century, opposing theories of light were being considered:
particles vs waves. A great deal of science was conducted on behalf of either
camp, but no clear victor emerged. It wasn’t until the 20th century that the
dual nature of light was widely accepted. I’m far from the first to notice the
parallels to logic and computing. Similarities are plentiful here. We even use
the same word, “duality,” to informally describe the frequent occurrence of
this two-element, yin-and-yang pattern in computing.</p>

<p>Where do dualities come from? Why are there so many of them? Why aren’t there
more trinities? Quaternities?</p>

<p>Binary classifications arrises when we define a domain of discourse, then
segregate that domain by a predicate. That is, some elements of the domain
possess some property and the other elements do not. When this property is
defined in terms of some bounded context, the binary classifications becomes a
metaphysical, particle/wave-style duality. An element of such a domain may or
may not satisfy such a predicate depending on your frame of reference!</p>

<p>Consider the famous Rubin’s Vase illusion:</p>

<p><img style="box-shadow: none; -webkit-box-shadow: none; " src="/images/vases.png" /></p>

<p>In each image, either a vase or a pair of face profiles can be scene. Consider
which subset of pixels satisfies the foreground predicate, and which satisfies
its negation or dual, the background predicate. While the “meta-image” has a
white background, the left and rightmost sub-images have a black background.
Inverting the colors can switch which object appears in the foreground.
However, adding a border can achieve the same illusion! Despite the center
image being a pixel-perfect, color-matching, sub-rectangle of the rightmost
image, the vase and faces appear to have swapped between the foreground and
background. The border provides the bounded context that governs the
foreground/background duality.</p>

<p>Returning to the duality of light: What property separates particles from
waves? Unlike waves, particles possess a definite position in space. Waves
have indefinite position, existing only with respect to some medium. A
physical medium serves as a bounded context. There’s no splash without a pool
of water; just as there is no background without a border.</p>

<p>Faced with duality, there is natural tendency to seek a preference between the
two sides. For many binary classifications, there is no clear winner. Heads or
tails? White or black? There’s no right answer. However, the equation is not
as balanced when it comes to context-bounded dualities. Our preference is
necessarily situational. On a white canvas, we paint a black vase in the
foreground, but just the opposite on a black canvas. We must consider the
context.</p>

<p>Frequently, the “particle” side of a duality is easier to recognize and reason
about. The particle theory of light was proposed in the 11th century, nearly
600 years prior to the wave theory. What makes waves more difficult to
recognize or reason about? Typically, context is implicit. The choice of
context is often already made for you. When I set out to write this blog post,
the background of my blog was already white. On a small beach, it’s easy to
see the particles of sand, but it’s just as easy to see the waves of the
ocean. Our relative scale influences our perspective, and that grants
dominance to one of the two perspectives on the duality. Luckily, perspective
can be shifted. Placing a handful of sand in to a carefully selected context,
such as the surface of a speaker, will instantly reveal a wave. Thinking in
terms of bounded contexts can put reasoning about waves on a level playing
field with particles.</p>

<p>One last bit of metaphysics is worthy of mention here: spacetime. It is
especially difficult to reason about time as a contextual bound on space.
Notably, many waves only appear when observing a medium over time, or by
projecting the time dimension on to a spatial dimension. Despite being
unbounded at a universal scale, time is scarce for us mortals. We can’t
capture time, holding on to it for study. At best, we can capture information
about the past, or make predictions about the future, effectively transforming
time in to the space such information takes up.</p>

<p>A good design takes things apart with an eye towards putting them back
together again. However, focusing on the pieces to the exclusion of their
contexts will yield a poor design. Even if the parts snap together nicely, a
gestalt may not arise, or the composition may clash with its surroundings. The
particles and waves or spacetime dualities can be found hiding under every
rock in computer science: Data vs interfaces, logic with negation, values and
state, imperative vs declarative, structural vs relational, and many more.
Learning to recognize these dualities will enable you to design better systems
and to produce better compositions within existing systems.</p>

<p>In future posts, I intend to discuss a wide range of programming topics with
an eye for context and gestalt. We’ll use the lense of duality to deepen our
understanding of the design tradeoffs in systems ranging from calculators to
databases and beyond. I’ll then abuse the perspective to argue against the
fetishization of modern programming ideals, such as functional purity, or the
overuse of constructs such as promises and observables.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[If simpler is better, is fewer better? Is one better than two? When designing programming constructs, there is a tendency towards extremist programming. There is power and beauty in a grand unified approach that has just one class of elements. Alluring as singularity may be, these one-element approaches tend to fail in ways that more complex designs do not. Hybrid approaches tend to win in the end. Why? And how should this reality inform our designs? Can we predict and enable hybrid solutions?]]></summary></entry><entry><title type="html">Versioning Better Than SemVer</title><link href="https://www.brandonbloom.name/blog/2017/01/18/versioning-better-than-semver/" rel="alternate" type="text/html" title="Versioning Better Than SemVer" /><published>2017-01-18T01:30:00+00:00</published><updated>2017-01-18T01:30:00+00:00</updated><id>https://www.brandonbloom.name/blog/2017/01/18/versioning-better-than-semver</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2017/01/18/versioning-better-than-semver/"><![CDATA[<p>I’ve written before about <a href="http://www.brandonbloom.name/blog/2013/06/19/semver/">my dislike for SemVer</a>. Recently, Rich Hickey
<a href="https://www.youtube.com/watch?v=oyLBGkS5ICk">spoke about this very same issue, and more</a>. I’m currently working on some
software that I’m hoping people will use, so I decided to make my thoughts on
a better versioning scheme clear. Below you’ll find an exerpt from my new
project’s documentation. Each point below could be elaborated on in a full post
of it’s own, but this summary has value as a checklist of sorts for those
discussions.</p>

<h2 id="contracts">Contracts</h2>

<p>Software should make explicit what it promises to provide, as well as make
explicit the requirements it relies on. Implicit promises or reliance should
be avoided. This is a as much a social contract as it is a technical one.</p>

<h3 id="breakage">Breakage</h3>

<p>If software relies on an explicit promise, it should never break.</p>

<h3 id="instability">Instability</h3>

<p>It is often useful to defer commitments. The default social contract should be
one of instability. In the absence of explicit promises, everything should be
considered unstable, and subject to change.</p>

<h3 id="accretion">Accretion</h3>

<p>It should always be possible to provide more. Making additional promises should
never cause breakage.</p>

<h2 id="migrations">Migrations</h2>

<p>Occasionally, supporting old contracts becomes burdensome. Parties to these
contracts should be provided a path to a new contract without breakage.</p>

<h3 id="retractions">Retractions</h3>

<p>Retracting promises should always be preceded by sufficient warning in order
to avoid breakage. This entails a new contract which specifies deprecated
provisions at the same time as providing new promises to migrate to.</p>

<h3 id="timelines">Timelines</h3>

<p>Contracts are identified by a ordinal version number and an instant in time.
Any contract may accrete new promises or bug fixes by creating an artifact
tagged with a new instant. Successive ordinal versions may retract promises
deprecated by previous ordinals.</p>

<h2 id="coexistence">Coexistence</h2>

<p>Even in the presence of migrations, grandfathered contracts should be honored.</p>

<h3 id="side-by-side">Side-by-Side</h3>

<p>A contract timeline may be forked by accreting a new contract with a new name.</p>

<h3 id="layering">Layering</h3>

<p>Platform systems should facilitate openness such that side-by-side systems may
interoperate. Where this is not immediately possible, lower layers should be
extended to facilitate this before forking higher layers.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I’ve written before about my dislike for SemVer. Recently, Rich Hickey spoke about this very same issue, and more. I’m currently working on some software that I’m hoping people will use, so I decided to make my thoughts on a better versioning scheme clear. Below you’ll find an exerpt from my new project’s documentation. Each point below could be elaborated on in a full post of it’s own, but this summary has value as a checklist of sorts for those discussions.]]></summary></entry><entry><title type="html">Rarely Reversible</title><link href="https://www.brandonbloom.name/blog/2015/04/26/rarely-reversible/" rel="alternate" type="text/html" title="Rarely Reversible" /><published>2015-04-26T15:33:00+00:00</published><updated>2015-04-26T15:33:00+00:00</updated><id>https://www.brandonbloom.name/blog/2015/04/26/rarely-reversible</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2015/04/26/rarely-reversible/"><![CDATA[<p><a href="https://facebook.github.io/react/">React.js</a> and its <a href="http://mollyrocket.com/861">“IMGUI”</a> inspired rendering model is exploding in
popularity.  After <a href="https://www.youtube.com/watch?v=LNtQPSUi1iQ">my talk at Clojure/West</a>, several folks asked me about
two seemingly separate discussion topics: Two-way Bindings and <a href="https://github.com/omcljs/om/wiki/Cursors">Cursors</a>.</p>

<p>Among those asking me about data binding, there are a few campaigning for a
“spreadsheet-like” method of defining user interfaces. On one hand, they’re
right to seek a direct-manipulation experience for building artifacts in a
fundamentally visual and interactive medium. However, the code-level approach
of using spreadsheet-like “equations” is fundamentally flawed.</p>

<p>Meanwhile, folks using <a href="https://github.com/omcljs/om">Om</a> in practice have expressed their frustrations
with cursors. A few suggested using something more principled like Haskell’s
<a href="https://hackage.haskell.org/package/lens">lenses</a>.  While this may be useful in some situations, it’s fundamentally
flawed for the same underlying reasons.</p>

<p>Both designs share a flaw born of a common desire: To automatically map user
input back to data sources. When there’s a 1-to-1 mapping from data sources to
user interfaces, this is appropriate. However, it’s not sufficient for the
general case. In fact, it’s not sufficient for the <em>common</em> case.</p>

<p>Transformations of source data in to views beyond trivial editable fields is
almost never reversible or equational.</p>

<p>To substantiate my position, let me demonstrate just how difficult it is to
write reversible relationships with some examples in the domain of grammars.</p>

<p>Let’s say you have this simple grammar:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A ::= a+
</code></pre></div></div>

<p>The production <code class="language-plaintext highlighter-rouge">A</code> is formed of 1 or more <code class="language-plaintext highlighter-rouge">a</code> characters.</p>

<p>An infinite number of substitutions will satisfy the rule.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a -&gt; A
aaaaaa -&gt; A
</code></pre></div></div>

<p>Here, the direction of the arrow is critically important.</p>

<p>How can you reverse this production rule?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>??? &lt;- A
</code></pre></div></div>

<p>The only <em>universal</em> way to convert directed rules in to reversible relations
is to never discard “information”.</p>

<p>For example, we could parameterize <code class="language-plaintext highlighter-rouge">A</code> by a number.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aaaa &lt;-&gt; A(4)
</code></pre></div></div>

<p>Alternatively, you can specify a general principal for lossy reversal rules,
like “always produce the smallest value that would satisfy the rule”.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>a &lt;- A
</code></pre></div></div>

<p>However, this falls flat on its face if you introduce alternation:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AB ::= a | b

a -&gt; AB
b -&gt; AB

??? &lt;- AB
</code></pre></div></div>

<p>Neither <code class="language-plaintext highlighter-rouge">a</code> nor <code class="language-plaintext highlighter-rouge">b</code> is “smaller”, so you need a new principle to reverse by.
In a traditional context free grammar, <code class="language-plaintext highlighter-rouge">|</code> doesn’t imply order, but in a
<a href="https://en.wikipedia.org/wiki/Parsing_expression_grammar">PEG</a>, for example, you have ordered choice. You could say that you reverse
to the first choice which satisfies the rule. Let’s use <code class="language-plaintext highlighter-rouge">/</code> as the ordered
choice operator.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AB ::= a / b

a -&gt; AB
b -&gt; AB

a &lt;- AB
</code></pre></div></div>

<p>Even in this simplified context, we haven’t even begun to scratch the surface
of potential problems with reversibility. Constructs such as binders or loops
will cause the reversal principles to explode in complexity.</p>

<p>Grammars offer pretty simple and well defined operations. However, practically
every new operation introduces new reversal principles. Once real world
business logic gets involved, things get hairy quickly.</p>

<p>In the context of user interfaces, these problems are magnified to be so large
that they are practically unrecognizable. However, if you zoom in on individual
cases in your own applications, you’ll spot this inherit complexity.</p>

<p>A robust UI solution should not attempt to build upon a foundation of
automatic reversibility.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[React.js and its “IMGUI” inspired rendering model is exploding in popularity. After my talk at Clojure/West, several folks asked me about two seemingly separate discussion topics: Two-way Bindings and Cursors.]]></summary></entry><entry><title type="html">Unsound and Incomplete</title><link href="https://www.brandonbloom.name/blog/2014/01/08/unsound-and-incomplete/" rel="alternate" type="text/html" title="Unsound and Incomplete" /><published>2014-01-08T17:36:00+00:00</published><updated>2014-01-08T17:36:00+00:00</updated><id>https://www.brandonbloom.name/blog/2014/01/08/unsound-and-incomplete</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2014/01/08/unsound-and-incomplete/"><![CDATA[<p>The academic programming language community spends lots of time studying and
building type systems. It’s widely considered that <a href="http://en.wikipedia.org/wiki/Soundness">soundness</a> is the mark
of a well designed type system. A sound type system never permits an
incorrectly typed program to pass type checking. An ideal type system would
also be <a href="http://en.wikipedia.org/wiki/Completeness#Logical_completeness">complete</a>; it would never reject a correctly typed program because
it was unable to prove its correctness. If you’re not familiar with this
terminology, Ben Karel offers <a href="http://eschew.wordpress.com/2009/08/31/sound-and-complete/">an illuminating analogy</a> to help you.</p>

<p>Recently, a flurry of new, statically typed languages have entered the public
stage. Among these are Google’s <a href="http://www.dartlang.org/">Dart</a>, as well as Microsoft’s
<a href="http://www.typescriptlang.org/">TypeScript</a>. One thing that these languages have in common is that they
have unsound type systems. Cue the horrified gasps of the type theorists!</p>

<p>Ignoring the topic of completeness for a moment, since most critics do so
themselves (I think “unsound” just sounds scarier than “incomplete”). Surely
Google and Microsoft employ some smart folks who have followed the latest
research in type systems, so why, in 2014, are we still building languages
that have unsound type systems? Well, I’ll let the <a href="https://www.dartlang.org/articles/why-dart-types/">Googlers</a> and
<a href="https://typescript.codeplex.com/discussions/428572">Microsofties</a> explain themselves. In short, it’s difficult to maintain
soundness in feature-rich languages. Even when possible, it may cause an
<a href="http://i.imgur.com/YAls4tQ.png">astronomical increase in complexity</a>. Achieving soundness requires
a trade off against completeness, complexity, toolability, and more. Never
mind the fact that being fully sound isn’t even that useful to begin with!</p>

<p>Let’s step back and examine why we even bother with type systems at all.
In many cases, static analysis can dramatically reduce programmer errors and
opens up significant optimization opportunities. Programming languages that
are amenable to formal static analysis are <a href="http://www.cse.chalmers.se/~nad/publications/danielsson-et-al-popl2006.html">highly correlated</a> with
programming languages that are amenable to informal static analysis, i.e. by
programmers! Type systems have proven to be a particularly useful category of
static analysis; so much so, that many programmers can’t imagine building
software without a type checker on hand at all times.</p>

<p>Sadly, type systems fundamentally can’t catch all kinds of programming
mistakes, nor will they magically improve the time or space complexity of your
algorithms. You’ll have to write tests and benchmarks either way, to say
nothing of validating your designs with stakeholders! Still, there are other
reasons to have a good type system, like enforcement of <a href="http://en.wikipedia.org/wiki/Type_safety">type safety</a>
(which is a different thing than “type correctness”). However, safety can also
be <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/ClassCastException.html">enforced by dynamic means</a> and dynamic mechanisms such as
<a href="http://erights.org/elib/capability/ode/ode-capabilities.html">capabilities</a> can enforce security far beyond that of static safety
checks. You might even want to <a href="http://msdn.microsoft.com/en-us/library/t2yzs44b.aspx">intentionally forego safety</a> in order to
achieve maximum performance. Furthermore, there’s lots of other kinds of
static analysis, both formal and informal, that can be used to find bugs or
speed your programs up.</p>

<p>Assuming we want a tool that finds as many errors as possible, we should be
willing to forego completeness, instead preferring to have our static analysis
be overly cautious, warning us of programs that <em>might</em> be incorrect. We can
always suppress such warnings after informal analysis (or alternative formal
analysis!). Assuming we’re realistic about the fact that no static analysis
tool will ever catch all errors, we should also be willing to tolerate
unsoundness in order to <a href="http://www.haskell.org/haskellwiki/Hoare_Property">spend our mental complexity budgets more wisely</a>.
Assuming we want a tool that independently improves with time, we should not
create a <a href="http://bracha.org/pluggableTypesPosition.pdf">cyclic dependency between languages and type systems</a>.</p>

<p>There is a class of such tools. They’re called <a href="http://en.wikipedia.org/wiki/Lint_(software)">linters</a>.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[The academic programming language community spends lots of time studying and building type systems. It’s widely considered that soundness is the mark of a well designed type system. A sound type system never permits an incorrectly typed program to pass type checking. An ideal type system would also be complete; it would never reject a correctly typed program because it was unable to prove its correctness. If you’re not familiar with this terminology, Ben Karel offers an illuminating analogy to help you.]]></summary></entry><entry><title type="html">Slurp &amp;amp; Spit</title><link href="https://www.brandonbloom.name/blog/2013/06/26/slurp-and-spit/" rel="alternate" type="text/html" title="Slurp &amp;amp; Spit" /><published>2013-06-26T11:59:00+00:00</published><updated>2013-06-26T11:59:00+00:00</updated><id>https://www.brandonbloom.name/blog/2013/06/26/slurp-and-spit</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2013/06/26/slurp-and-spit/"><![CDATA[<h2 id="does-nobody-teach-fopen-anymore">Does nobody teach fopen anymore?</h2>

<p>Many programmers start with “Hello World”. Shortly after that, it’s “Hello
$NAME”, with a string read off stdin. But soon, budding engineers get tired of
reminding their computer of their name each and every time their code runs.
When I was first learning to program, file IO was an early requirement. We were
taught how to read and write “data files” using little more than fopen,
fscanf, fprintf, and fclose.</p>

<p>Fast forward five to ten years; you find yourself writing your 10 millionth SQL
query, wishing for simpler times. Spend some more time with the NoSQL database
du jour and the humble fopen function will be but a distant memory.  Until that
one fateful day arrives where you’ve got a relatively simple program and
encounter the need for equally simple durability. Five years ago, you’d have
cracked your knuckles and hacked out a pair of “save” and “load” functions.
Today, you add a dependency on your favorite database driver, switch to the
shell, type <code class="language-plaintext highlighter-rouge">createdb myapp</code> and then dutifully begin defining a lovely schema.
Of course, now you need to either rework your models to conform to some horrid
ORM layer, or write save/load-style “hydrate” and “dehydrate” methods anyway.</p>

<p>Now, at ten years and a day, you decide it’s finally time to learn that hip new
programming language that everybody is talking about. You’ve got your book out,
you’ve rocked through all your favorite technical interview puzzles, and you’re
ready to put together a little web service for personal or small group use.  If
this was yesterday, you’d know exactly what dependency to add and how to
proceed, but that was yesterday. Today, you do some Googling or hop into IRC
looking to find out what’s popular.</p>

<p>Why don’t you even consider fopen?</p>

<h2 id="but-files-arent-web-scale">But files aren’t “Web Scale”!</h2>

<p>Is that really true? And do you really care? Should you really care?</p>

<p>The answer to all of these questions is “No”. Files can easily be “web scale”.
As of 2013, Hacker News is still running as a single process, on a single core,
of a single server, backed by a directory structure of simple data files.
Nearly 2 million page views are served daily. See <a href="https://news.ycombinator.com/item?id=5229522">this thread</a> and
<a href="https://news.ycombinator.com/item?id=5253773">this submission</a> for details.</p>

<p>The bottom line on this subject is that 1) You’re going to need significant
cleverness to scale any service regardless of whether you use a database or the
file system directly. And 2) You probably won’t need to scale hugely anytime
soon, anyway. Being crushed by traffic is a Good Problem To Have, so let’s
worry about the Ghost Town problem first. 3) You can always refactor later.</p>

<h2 id="data-literals-print-read-spit-and-slurp">Data Literals: print, read, spit, and slurp</h2>

<p>This article was prompted by a reoccurring discussion started by newcomers to
the Clojure IRC channel. Having learned the basics, folks want to hit the
ground running with stateful and durable services. Coming from a background in
some big framework or some hairy application, these folks ask those suggestive
questions about databases, driver libraries, and the like. Often, upon
interrogation, they only have a couple kilobytes or megabytes of total data to
be stored. In such a situation, the advice is always the same: Put that data
into an atom, then use <code class="language-plaintext highlighter-rouge">spit</code> and <code class="language-plaintext highlighter-rouge">slurp</code> to save and load.</p>

<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">db</span><span class="w"> </span><span class="p">(</span><span class="nf">atom</span><span class="w"> </span><span class="p">{</span><span class="n">...</span><span class="p">}))</span><span class="w">

</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">save-data</span><span class="w"> </span><span class="p">[]</span><span class="w">
  </span><span class="p">(</span><span class="nf">spit</span><span class="w"> </span><span class="s">"somefile"</span><span class="w"> </span><span class="p">(</span><span class="nb">prn-str</span><span class="w"> </span><span class="o">@</span><span class="n">db</span><span class="p">)))</span><span class="w">

</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">load-data</span><span class="w"> </span><span class="p">[]</span><span class="w">
  </span><span class="p">(</span><span class="nf">reset!</span><span class="w"> </span><span class="n">db</span><span class="w"> </span><span class="p">(</span><span class="nf">read-string</span><span class="w"> </span><span class="p">(</span><span class="nb">slurp</span><span class="w"> </span><span class="s">"somefile"</span><span class="p">))))</span><span class="w">
</span></code></pre></div></div>

<p>Because Clojure encourages the use of printable, readable, “pure” data, your
save and load functions are virtually free! If you’re not familiar with
Clojure, then consider working with pure JSON in Node.js:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">db</span> <span class="o">=</span> <span class="p">{...};</span>

<span class="kd">function</span> <span class="nx">saveData</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFileSync</span><span class="p">(</span><span class="dl">"</span><span class="s2">somefile</span><span class="dl">"</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">serialize</span><span class="p">(</span><span class="nx">db</span><span class="p">));</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nx">loadData</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">db</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="dl">"</span><span class="s2">somefile</span><span class="dl">"</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Things aren’t quite as easy in languages lacking data literals, but nearly
every popular language has some kind of automatic serialization library.
However, even if you do need to write your own save and load functions, it’s
a pretty straightforward, if somewhat tedious, process.</p>

<p>Even–or especially–experienced programmers are surprised by just how far
this brain-dead-simple durability scheme will go.</p>

<h2 id="atomicity">Atomicity</h2>

<p>One other objection to files is that it’s difficult to ensure an application
enjoys the same guarantees that a well-tested ACID database affords. Never mind
the fact that the majority of Rails applications suffer from dozens of
consistency bugs because most developers forget to wrap related updates in
transactions; it is true that incorrectly implemented file IO can cause
catastrophic data loss.</p>

<p>If you plan to deploy spit and slurp into production, you’d be advised to write
to a temporary file and utilize an atomic rename. This ensures that a failure
during writing won’t corrupt your database. See <code class="language-plaintext highlighter-rouge">man rename</code> for more.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">saveData</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFileSync</span><span class="p">(</span><span class="dl">"</span><span class="s2">somefile.tmp</span><span class="dl">"</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">serialize</span><span class="p">(</span><span class="nx">db</span><span class="p">));</span>
  <span class="nx">fs</span><span class="p">.</span><span class="nx">renameSync</span><span class="p">(</span><span class="dl">"</span><span class="s2">somefile.tmp</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">somefile</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Just this one little tweak and this bad boy is production ready. Clojure
programmers can use Java’s <code class="language-plaintext highlighter-rouge">File.renameTo</code> method. See below.</p>

<p>Remember to configure your backups!</p>

<h2 id="dont-stop-the-world">Don’t Stop The World</h2>

<p>Experienced Node.js programmers likely cringed at the “Sync” suffix on the
above file operations. These operations will block while data is being read or
written. In addition to yielding clearer example code, synchronous operations
do not require coordination. If your application only needs to serve a handful
of users, you can still write 100 megabytes of data in less than half a
second. Even if you write every change to a file on every request, your ten
users might not even notice your blocking IO. As you scale up, you’ll need to
either split your data files up and/or start writing files asynchronously.</p>

<p>Asynchronous means coordination. Coordination means locking or queues. This
stuff really isn’t as scary as it sounds, but it will have to wait; this post
has already gotten far too long. However, I don’t want to lead you down the
wrong path, so I should mention that, unlike Node.js, synchronous writes on
the JVM will not block other requests. You practically don’t have a choice, but
to be asynchronous.  If two requests both call your save function at the same
time, the resulting race condition can lead to incremental data loss. Luckily,
Clojure’s agents and persistent data structures provide for a super quick fix:</p>

<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">import</span><span class="w"> </span><span class="ss">'java.io.File</span><span class="p">)</span><span class="w">

</span><span class="p">(</span><span class="k">def</span><span class="w"> </span><span class="n">save-agent</span><span class="w"> </span><span class="p">(</span><span class="nb">agent</span><span class="w"> </span><span class="n">nil</span><span class="p">))</span><span class="w">

</span><span class="p">(</span><span class="k">defn</span><span class="w"> </span><span class="n">save-data</span><span class="w"> </span><span class="p">[]</span><span class="w">
  </span><span class="p">(</span><span class="nb">send-off</span><span class="w"> </span><span class="n">save-agent</span><span class="w">
    </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">[</span><span class="n">_</span><span class="p">]</span><span class="w">
      </span><span class="p">(</span><span class="nf">spit</span><span class="w"> </span><span class="s">"somefile.tmp"</span><span class="w"> </span><span class="p">(</span><span class="nb">prn-str</span><span class="w"> </span><span class="o">@</span><span class="n">db</span><span class="p">))</span><span class="w">
      </span><span class="p">(</span><span class="nf">.renameTo</span><span class="w"> </span><span class="p">(</span><span class="nf">File.</span><span class="w"> </span><span class="s">"somefile.tmp"</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">File.</span><span class="w"> </span><span class="s">"somefile"</span><span class="p">)))))</span><span class="w">
</span></code></pre></div></div>

<p>Different web servers across all the different languages have varying
concurrency support and configuration defaults. Whether or not you use file IO,
you should be aware of the concurrency story for your platform and its impact
on your application.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Does nobody teach fopen anymore?]]></summary></entry><entry><title type="html">Code Density</title><link href="https://www.brandonbloom.name/blog/2013/06/24/code-density/" rel="alternate" type="text/html" title="Code Density" /><published>2013-06-24T18:26:00+00:00</published><updated>2013-06-24T18:26:00+00:00</updated><id>https://www.brandonbloom.name/blog/2013/06/24/code-density</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2013/06/24/code-density/"><![CDATA[<p>I’ve heard from many folks who have had difficulty learning functional
programming. In attempting to complete seemingly simple tasks, even the most
experienced imperative and object oriented programmers fall flat on their faces
when first attempting to program in a functional style. Yet, experienced
functional programmers rave about their productivity and their small, beautiful
codebases. Are these functional programmers simply that much smarter? Or is
there some other force at work?</p>

<p>Even in a familiar language, a small, but powerful library might be described
as “write-only code” by those who do not grok the fundamental ideas. Powerful
ideas produce powerful programs, but powerful programs don’t always shed light
on their underlying powerful ideas. Functional programming is a powerful idea.</p>

<p>A lot of businesses just need somebody to bang out some pretty vanilla
solutions to some pretty vanilla problems. If you’re in one of these businesses
(and most of us are), then your team’s resident curmudgeon is right: Clever is
not a good thing. Familiar and understood beats simple and powerful ideas every
time.</p>

<p>However, if you’re looking to up your game; If you want to tackle bigger
problems, you need more powerful tools. If you’ve tried to read some Lisp or ML
or Haskell, but found your head swimming; If you’ve tried to fight your way
through <a href="http://projecteuler.net/">Project Euler</a> with an unfamiliar language, but got stumped by
tasks you aced in freshman year; Don’t panic. There’s a good explanation for
why these things seem harder. Those functional programmers really aren’t
smarter than you.  They’re just a little more persistent.</p>

<p>The key issue is one of code density. Powerful ideas can succinctly express
solutions to tough problems. The problem isn’t necessarily any easier, nor is
expressing the solution necessarily any more difficult. There is simply more
meaning per line of code, so reading and writing each line of code takes
proportionally longer. If you’ve jumped into a 100,000+ lines-of-code Java
project and found your way around like a champ, you shouldn’t feel ashamed by
jumping into a 10,000 line Clojure project and being horribly lost. Those
10,000 lines of code might take you five times as long to read per line.  These
numbers are only backed by anecdotal evidence, but that’s a hypothetical 50%
reduction in total code reading time!</p>

<p>When you start writing some object-oriented code, you spend a bunch of time
creating classes and defining the shape of your domain. There is some delay
between when you begin typing and when you run head first into the problem at
hand. During that delay, you have a lot of time to think about the problem.
While you’re fingers are hard at work, your mind is too. Your brain needs time
for solutions to bake. If you encounter the hard problems as soon as you start
typing, you need to walk away from your desk!</p>

<p>Functional programming is a particularly compelling powerful idea because it
captures the essence of a lot of computational problems. There is a great deal
of complexity that is hidden away in mutable state, implicit context, and
abstract interfaces. If you’re used to the constant drip of progress afforded
by stitching together class hierarchies, you suffer immediate withdrawals when
faced with all of the hidden moving parts laid bare in an individual function’s
signature. Suddenly, you need to solve many more problems at once, but you’ve
become accustom to having those problems spread out across a wider
cross-section of your program.</p>

<p>It takes longer to get started with a powerful idea because you must first
understand and internalize that powerful idea. Take a deep breath, lean back in
your chair, close your eyes, and think through the problem. Untangle the mess
in your head, maybe explore a bit in the REPL, then come back and try the
problem again. You might find that you spend half as much time thinking as you
used to spend typing.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I’ve heard from many folks who have had difficulty learning functional programming. In attempting to complete seemingly simple tasks, even the most experienced imperative and object oriented programmers fall flat on their faces when first attempting to program in a functional style. Yet, experienced functional programmers rave about their productivity and their small, beautiful codebases. Are these functional programmers simply that much smarter? Or is there some other force at work?]]></summary></entry><entry><title type="html">SemVer: A Technical Solution to a Social Problem</title><link href="https://www.brandonbloom.name/blog/2013/06/19/semver/" rel="alternate" type="text/html" title="SemVer: A Technical Solution to a Social Problem" /><published>2013-06-19T11:35:00+00:00</published><updated>2013-06-19T11:35:00+00:00</updated><id>https://www.brandonbloom.name/blog/2013/06/19/semver</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2013/06/19/semver/"><![CDATA[<p>“Semantic Versioning”, commonly called <a href="http://semver.org/">SemVer</a>, is a specification for
assigning and reasoning about software version numbers. In short, it codifies
some common practices regarding <code class="language-plaintext highlighter-rouge">$MAJOR.$MINOR.$REVISION</code> style version
numbers, including guarentees about API compatibility and dependency
resolution.</p>

<p>Beautifully simple semantics, outlined by a clear and concise specification.
What’s not to like? Technically, SemVer is very strong. However, statistically
speaking, software developers can not be trusted to maintain the semantics
promised by SemVer. A small handful of individuals and projects use SemVer, or
something like it, to good effect. The rest can’t be trusted not to introduce
major bugs or breaking changes with each and every revision.</p>

<p>Every engineer who has ever worked on a project with more than a handful of
external dependencies has had the horrifying experience of deploying some small
dependency upgrades only to have their entire house of cards come crashing
down. As a result, mature organizations tend to maintain their own package
repositories, vendor all dependencies, or otherwise carefully scrutinize and
control each and every external component.</p>

<p>Packaging systems such as Ruby’s <a href="http://gembundler.com/">Bundler</a> and Node’s <a href="https://npmjs.org/">NPM</a> often default
to or otherwise encourage SemVer. Depending on a
<a href="http://docs.rubygems.org/read/chapter/16#page74">pessimistic version constraint</a>, such as <code class="language-plaintext highlighter-rouge">~&gt; 1.2</code>, is tantamount to saying
“I trust that the maintainer of this project both understands SemVer and is
capable of enforcing its guarantees.” Sadly, this is rarely, if ever, true.</p>

<p>Versioning is a social contract. A maintainer makes a promise regarding API
stability and versioning policy. Consumers make a judgement call regarding the
veracity of the maintainer’s promise. If the README file says “This project uses
SemVer” and the project’s maintainer is <a href="http://tom.preston-werner.com/">Tom Preston-Werner</a>, then you can
trust that pessimistic version constraint in your dependencies file.</p>

<p>However, the README might say “Releases are only packaged for long-term support
versions.  Please use the <code class="language-plaintext highlighter-rouge">stable</code> branch for new production systems.” In such
a case, you might want to consider depending directly on that branch or even on
a particular commit hash. Speaking of branches and commits, this calls to mind
a far preferable default for packaging and dependency resolution systems:
<a href="https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html">refspecs</a>. It would be great if the SemVer spec was updated to include
policies for defining branch and tag names in your version control system of
choice. Instead of depending on <code class="language-plaintext highlighter-rouge">~&gt; 1.2</code>, you could depend on
<code class="language-plaintext highlighter-rouge">branches/v1.2.x</code>. This grants maintainers greater flexibility in making social
contracts.  It also grants consumers greater control over how much trust they
give to maintainers.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[“Semantic Versioning”, commonly called SemVer, is a specification for assigning and reasoning about software version numbers. In short, it codifies some common practices regarding $MAJOR.$MINOR.$REVISION style version numbers, including guarentees about API compatibility and dependency resolution.]]></summary></entry><entry><title type="html">Trivial Cycles in Object Oriented Programming</title><link href="https://www.brandonbloom.name/blog/2013/06/18/oop-cycles/" rel="alternate" type="text/html" title="Trivial Cycles in Object Oriented Programming" /><published>2013-06-18T16:41:00+00:00</published><updated>2013-06-18T16:41:00+00:00</updated><id>https://www.brandonbloom.name/blog/2013/06/18/oop-cycles</id><content type="html" xml:base="https://www.brandonbloom.name/blog/2013/06/18/oop-cycles/"><![CDATA[<p>I’m not against objects. I’m against programming in a style <em>oriented</em> by
objects.</p>

<p>One of the largest causes of big-ball-of-mud architectures is unnecessary cyclic
dependencies. Unfortunately, object-oriented languages allow programmers to
trivially create cyclic dependencies without warning or immediate
repercussions. Overtime, these cycles become a significant source of complexity
and corresponding suffering.</p>

<p>The problem can be summarized in a single line of pseudocode:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">person</span><span class="p">.</span><span class="nf">address</span><span class="p">.</span><span class="nf">residents</span>
</code></pre></div></div>

<p>This innocuous-looking expression embodies a pleasant interface, but its
implementation hides an insidious cyclic relationship between the <code class="language-plaintext highlighter-rouge">Person</code>
class and the <code class="language-plaintext highlighter-rouge">Address</code> class. Worse than that, this cyclic relationship
is extended transitively to any other related classes. Consider the following
diagram with an additional <code class="language-plaintext highlighter-rouge">Company</code> class that may also have an address.</p>

<p><img src="/images/oop-cycle.png" alt="Person / Address / Company ball-of-mud" /></p>

<p>Any time you add a type to this graph, it is instantly tangled-up with
everything else. Compare this with this functional variant:</p>

<p><img src="/images/fp-dag.png" alt="Person / Address / Company untangled" /></p>

<p>Now you can analyze, compile, and reason about a subset of this graph.
Reasoning about any particular node only requires reasoning about the
transitive closure of its dependencies. However, in the presence of ubiquitous
cycles, the transitive closure is equivalent to the entire graph.</p>

<p>Unfortunately, we’ve now lost the convenient <code class="language-plaintext highlighter-rouge">noun.verb</code> or <code class="language-plaintext highlighter-rouge">noun.component</code>
syntax. Instead, our expressions are inside out. Here it is in Ruby or Python
syntax:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">residents</span><span class="p">(</span><span class="n">address</span><span class="p">(</span><span class="n">person</span><span class="p">))</span>
</code></pre></div></div>

<p>And here it is in Lisp syntax:</p>

<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nf">residents</span><span class="w"> </span><span class="p">(</span><span class="nf">address</span><span class="w"> </span><span class="n">person</span><span class="p">))</span><span class="w">
</span></code></pre></div></div>

<p>Luckily, we can recover the pleasant ordering with the help of a macro.  Here
is an example of Clojure’s threading macro:</p>

<div class="language-clojure highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">-&gt;</span><span class="w"> </span><span class="n">person</span><span class="w"> </span><span class="n">address</span><span class="w"> </span><span class="n">residents</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>

<p>In the absense of macros, we can use a binary operator. Here’s an example of
F#’s “pipeline” operator:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">person</span> <span class="p">|&gt;</span> <span class="n">address</span> <span class="p">|&gt;</span> <span class="n">residents</span>
</code></pre></div></div>

<p>Both Scala and C# provide tools for directly emulating the dotted access
syntax.  Respectively, implicit conversions and extension methods leverage the
type system to perform dispatch to non-members in a syntactically identical
way.</p>

<p>It is unfortunate that it is so easy to create cycles. A small sin at first,
but they quickly add up and really start to hurt as a system grows larger.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I’m not against objects. I’m against programming in a style oriented by objects.]]></summary></entry></feed>