GoRuCo 2018

The Twelve-Factor Function

GORUCO 2018: The Twelve-Factor Function by Desmond Rawls

GoRuCo 2018

00:00:00.000 I don't want to stand behind the podium. I have this cool t-shirt on from hot yoga, and it's the first time I've done it in four years.
00:00:17.010 I still need to hold on to the simplest and most powerful idea I've picked up in software development: design isn't about putting things together; it's about pulling things apart. The Twelve-Factor Function pulls apart meaning and magic. It's a set of twelve constraints that isolate meaningful functions. For example, faced with a rampaging dragon, a knight might write a function to decide which village to protect next. Someone whose dream is to open a bowling alley might also write a function, which personalizes your news feed. So what's the big deal about these functions? Well, in just a few lines of code, we can improve our morning routine, get one step closer to achieving our dreams, and even save the lives of countless villagers. Twelve-Factor Functions aren't supposed to be fancy; they're supposed to be meaningful and portable.
00:00:58.050 While there's no one-to-one correlation, the Twelve-Factor Function shares the same goal and approach as the Twelve-Factor App—moving faster by separating the core of your business from the rest of the stack. A Twelve-Factor App is a Software as a Service (SaaS) application that is freed from infrastructure concerns. It delivers business value in a way that can be mixed and matched with a variety of infrastructure solutions. However, there’s something not quite right about the Twelve-Factor App. From my experience, the code in these apps is not solely about business. Infrastructure is a fuzzy word; what if we define it as everything that isn't the rules of your business? Now, we realize we may have drawn the lines incorrectly.
00:01:55.950 The Twelve-Factor Function goes to the logical extreme by asserting that these functions should be 100% made up of business rules. This way, our business value becomes more portable, and the rest of the stack can be more generic. I'm using the Twelve-Factor App to tie the Twelve-Factor Function into the shared consciousness of the programming community. However, the Twelve-Factor App is not where I started. I wasn't motivated by the great need for designers when I arrived at the Twelve-Factor Function. I’d like to take a moment to talk about my journey to this point and how Ruby played a role.
00:02:44.100 Let’s drop the terms business and infrastructure because they’re rather uninspired. Instead, I’ll introduce the words meaning and magic. This is me as a newborn. The Twelve-Factor Function is really about approaching my work in a way I hope my younger self—and perhaps even my own children—will approve of. I was a non-technical baby, eager to understand people. Born with a keen sense of life’s absurdity, I studied various subjects and worked in different jobs searching for clues about how people, with all our absurd passions, fit into the vast universe.
00:03:43.680 Eventually, I arrived at programming and was fortunate to land in the Ruby community. I witnessed how the Ruby community worked hard to humanize software, and I thought I could learn something from that. I was taught that good code reads like a novel. I appreciated this idea, and still do, but soon found myself confronting a lot of esoteric computer concepts that I struggled to humanize. I began to evaluate my code and realized it didn't read like a novel; instead, it was as readable as a QR code. While I took pride in its power, it didn't exude any meaningful storytelling.
00:04:16.470 So, what does this esoteric computer stuff have to do with people? What does cache invalidation have to do with the human experience? My conclusion is—nothing. However, not all the code I write revolves around cache invalidation, nor does it all read like a QR code. Some of it carries a slice of humanity. Meanwhile, other portions communicate information across networks and data stores in extremely powerful but often incomprehensible ways. The meaningful parts are ones I am confident I could explain to my children; the other parts I would merely gloss over, attributing them to 'computer magic'. So sometimes we’re searching for meaning, and sometimes we are just transferring information—these two activities are very different.
00:05:05.420 Software development gains its power by uniting our understanding of people with our understanding of computers. However, because these aspects differ significantly, we progress independently in our roles as meaning creators and magicians. The trouble arises when we tangle up meaning with magic, allowing them to hold each other back. If we instead decouple meaning from magic, I will find it easier to justify my existence to my children, and I can also move faster along these important axes. This leads us back to the Twelve-Factor Function; instead of discussing business and infrastructure, let’s talk about meaning and magic.
00:05:47.290 I chose the word meaning partly because it’s so problematic in software, and I want this word choice to resonate with you. The Twelve-Factor Function states that if you isolate your meaningful code and functions that meet defined criteria, you’ll be able to change the meaning of your software with minimal impact on the magic that manages information, and vice versa—the magic can change with minimal impact on the meaningful bits. The last eight constraints are refinements, so we won't address them today, but the first four core criteria of the Twelve-Factor Function must produce meaning, take arguments, not rely on deployment strategy, and not reference persistent strategy.
00:06:43.910 Let’s examine an example to highlight these core criteria. Suppose we have a data set that contains 100 facts about every person on earth. How interesting would you find this information if I simply printed it out? How much of it would you actually read? Now imagine we pass this information to a function that ranks compatibility across all fields. Picture me identifying the single most compatible person among the 7.5 billion inhabitants of Earth. How captivating would you find this output? I predict this concept would be the essence of a highly successful dating app—this is what we, in the meaning creation industry, would call 'embarrassingly meaningful'. Now let’s explore a slightly different implementation.
00:07:51.970 We start with the same dataset, but this time we format the backend in a Postgres database. We select a row from the database using SQL, send the data through an Nginx proxy, place it into a Kafka queue, and query it using Rack. What does this accomplish? This approach, in our industry, is referred to as a 'blind date'. The first criterion of a Twelve-Factor Function is that users must find the output more valuable than the inputs; in this initial filtering function, that criterion is met. In contrast, the second convoluted example, rife with sophisticated computer science, fails to meet this standard.
00:08:46.632 To produce meaning, our function should accept arguments; otherwise, we are making declarations. Additionally, our function should be agnostic about its invocation context and not concern itself with how the information reaches it—that is all part of the 'computer magic'. Let’s further elaborate on the deployment strategy aspect. Deployment strategies relate to where we consume information, particularly its physical location, even if we are oblivious to the zip code governing the process executing it. Our processes run in various locations, passing information across networks. Networks are designed to transfer information but do not infuse it with meaning; therefore, they belong to the domain of magic.
00:09:54.620 Let’s consider a few scenarios: Would the output of my matchmaking function change if it ran in a browser instead of a server? What about when executing it on a mainframe, within a container, or even as a function within a service or a retro emulated Nintendo64? Would any of these scenarios result in differing meanings? No. The relationship between the information and its meaning remains constant, regardless of where the transformation occurs. I aim to free my function from worrying about its placement in the network, enabling me to rearrange processes without affecting my meaningful function. Likewise, I can modify my meaningful function without being bogged down by the network. In both cases, my changes yield smaller footprints and less complexity, allowing me to operate more quickly, deliver more value, and expend less emotional energy worrying over compromises.
00:10:52.610 Thus, a persistence strategy pertains to time, while a deployment strategy relates to space. Together, they provide us with the magic needed to move information through both time and space. Once we have processed this information, we can pass it to a function that generates meaning, all without needing to concern ourselves with the complicated journey that brought the information to our fingertips. By decoupling meaning and magic, I can mix and match my meaningful functions along with different processes for gathering information.
00:11:37.760 Meaningful functions may comprise a tiny component of the code executed at runtime. If executed with precision, they could substantially dominate the overall code that you write. In an ideal world, developers would devote 40 hours each week solely to crafting meaningful functions. If we collectively focus on this goal and collaborate, someday—maybe far off—perhaps we can achieve this. So there you have it: that’s the Twelve-Factor Function. If you’re interested in hearing more about the other eight constraints or wish to see a more developed example, you can find that information here. Thank you.