<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Radify - Rapid Application Development</title><atom:link href="http://radify.io/feed.xml" rel="self" type="application/rss+xml"></atom:link><link>http://radify.io</link><description>We architect beautiful APIs and implement gorgeous user interfaces for the best user experience.</description><pubDate>Thu, 19 May 2016 00:00:00 -0400</pubDate><generator>Wintersmith - https://github.com/jnordberg/wintersmith</generator><language>en</language><item><title>Using front-end build tools</title><link>http://radify.io/blog/using-build-tools/</link><pubDate>Thu, 19 May 2016 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/using-build-tools/</guid><author></author><description>&lt;blockquote&gt;
&lt;p&gt;This e-book was originally published in 2015 by &lt;a href=&quot;https://www.fivesimplesteps.com/&quot;&gt;Five Simple Steps&lt;/a&gt;. Five Simple Steps have closed their online store and graciously returned the rights to the authors, so we are offering this book for free.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;/downloads/Using-Build-Tools.pdf&quot; title=&quot;Download the book in its original form&quot;&gt;Download as PDF&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This book is aimed at designers who also do front end development. These days, it seems that we all wear multiple hats in our jobs!&lt;/p&gt;
&lt;p&gt;Since the turn of the century, web development has become far more sophisticated. This has led to more complexity, and many of us are finding we have to work with many new things. This can seem a little intimidating (I have certainly found myself wishing that the pace of progress would slow down!).&lt;/p&gt;
&lt;p&gt;To take advantage of this sophistication whilst reducing its complexity, front-end developers use build tools. These tools allow us to work at a higher level and automate away repetitive tasks, thereby saving time and producing more sophisticated results. Automation streamlines our processes so that we can focus on creative work, rather than spending hours lost in the weeds of tedious tasks.&lt;/p&gt;
&lt;p&gt;In this short book, we will go through some of the build tools that are available, what they can do for you, and how you can get started with them. I will refer to some specific tools, but this book will not teach you the specifics of a particular build tool; after all, each build tool is well documented online and in print already. Instead, this book functions as a primer on what build tools are and how to assemble powerful, efficient build workflows with them.&lt;/p&gt;
&lt;p&gt;The goal of this book is that, once you have read it, you will be able to improve your workflow by incorporating build tools. I aim to give you the confidence and knowledge needed to dive into this world of powerful and flexible utilities, become more productive, and enjoy your work more as a result.&lt;/p&gt;
&lt;h1 id=&quot;let-s-talk-about-workflow&quot;&gt;Let’s talk about workflow&lt;/h1&gt;
&lt;p&gt;Workflow is the set of tasks that one goes through when doing a job. Everyone’s workflow is different, and you might have multiple workflows for different aspects of your role. We will look at web development workflow and how to optimise it.&lt;/p&gt;
&lt;h2 id=&quot;basic-web-development-workflow&quot;&gt;Basic web development workflow&lt;/h2&gt;
&lt;p&gt;In developing websites and applications, you probably have phases that look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/workflow-basic.png&quot; alt=&quot;Basic web development workflow&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don’t worry if your workflow is different. I’ve just selected a number of common tasks; the principles found in book will apply no matter what your workflow is.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are a number of problems with this common, simplistic workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File size - there is no minification of the assets or compression of the images, so the application will perform slower than it ought.&lt;/li&gt;
&lt;li&gt;Consistency - pushing to a server can be error prone: assets may be cached, transfers can fail, etc.&lt;/li&gt;
&lt;li&gt;Speed of workflow - pushing and refreshing manually is time consuming and takes you out of the &amp;quot;zone&amp;quot; of your workflow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s add a few more tasks to this workflow to address these issues.&lt;/p&gt;
&lt;h2 id=&quot;creating-an-asset-pipeline&quot;&gt;Creating an asset pipeline&lt;/h2&gt;
&lt;p&gt;To resolve the problems we have identified in the basic workflow, we can incorporate compression, minification, and concatenation. Minification compresses code without changing its functionality. Concatenation combines multiple files together into a single file, improving download speeds. Let’s add these tasks to the process:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/workflow-asset-pipeline.png&quot; alt=&quot;Asset pipeline&quot;&gt;&lt;/p&gt;
&lt;p&gt;This approach, commonly known as the &lt;em&gt;asset pipeline&lt;/em&gt;, takes assets from an input area, transforms them, and delivers them to an output area. We will look at how to structure and automate an asset pipeline.&lt;/p&gt;
&lt;p&gt;A common convention is to have two separate directories in the root (top level) of your project. The first is &lt;code&gt;src&lt;/code&gt;, which contains source code - the files you edit. The second is &lt;code&gt;build&lt;/code&gt;, which contains files that are generated and delivered to the end user. You never edit anything in &lt;code&gt;build&lt;/code&gt; directly. The project’s specific location is not important, but this book assumes that the project is saved in &lt;code&gt;/home/user/myproject&lt;/code&gt; on OSX/Linux or &lt;code&gt;C:\Users\user\myproject&lt;/code&gt; on Windows.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In some projects, &lt;code&gt;build&lt;/code&gt; may be called &lt;code&gt;dist&lt;/code&gt;, which is short for &amp;quot;distribution&amp;quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directory&lt;/th&gt;
&lt;th&gt;OSX/Linux&lt;/th&gt;
&lt;th&gt;Windows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/src&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\src&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\build&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Once &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; are separated, move any existing project files into the &lt;code&gt;src&lt;/code&gt; directory. These are the files that you will edit. Everything in &lt;code&gt;build&lt;/code&gt; will be generated using your build tool - we never edit files in &lt;code&gt;build&lt;/code&gt; directly. Hands off!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s best to test something that’s as representative as possible of what the end-user will receive. Therefore, it’s a good practice to test in &lt;code&gt;build&lt;/code&gt;, not in &lt;code&gt;src&lt;/code&gt;, so as to catch any potential problems that the transformations might have introduced.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A full treatment of SCM (Software Configuration Management) is outside the scope of this book, but I will make one suggestion: when using a version control tool like Git, Mercurial, or Subversion, add the &lt;code&gt;build&lt;/code&gt; directory to your SCM’s ignore file. You do not want to commit anything in &lt;code&gt;build&lt;/code&gt; - it’s considered volatile. In SCM, only the source files are committed to your SCM, and these generate the build. This keeps commit logs clean and uncluttered by the build assets.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To learn about Git, check out &lt;a href=&quot;http://www.fivesimplesteps.com/products/version-control-with-git&quot;&gt;Version Control with Git by Ryan Taylor&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is how the asset pipeline might look:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/workflow-asset-pipeline-build-level.png&quot; alt=&quot;Asset pipeline&quot;&gt;&lt;/p&gt;
&lt;p&gt;Assuming that you have two javascript files, &lt;code&gt;src/js/a.js&lt;/code&gt; and &lt;code&gt;src/js/b.js&lt;/code&gt;, and two CSS files, &lt;code&gt;src/css/first.css&lt;/code&gt; and &lt;code&gt;src/css/second.css&lt;/code&gt;, the build would output &lt;code&gt;build/js/all.min.js&lt;/code&gt; and &lt;code&gt;build/css/all.min.css&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/workflow-asset-pipeline-build-level-detail.png&quot; alt=&quot;Asset pipeline detail&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because we have concatenated multiple assets into single files, we will have to replace the references to the assets. In &lt;code&gt;src/index.html&lt;/code&gt;, we have four such references:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/js/a.js&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;undefined&quot;&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/js/b.js&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;undefined&quot;&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;media&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;all&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/css/first.css&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;media&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;all&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/css/second.css&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;build/index.html&lt;/code&gt;, this becomes just two references:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/js/all.min.js&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;undefined&quot;&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;rel&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;media&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;all&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;/css/all.min.css&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, the minified and concatenated assets, bundled up cleanly in the &lt;code&gt;build&lt;/code&gt; directory, are ready to be pushed to the server. There are some problems, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isn’t this process unnecessarily complex?&lt;/li&gt;
&lt;li&gt;How do we know if there are problems with the code?&lt;/li&gt;
&lt;li&gt;How do we manage this process?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is where we introduce the wonderful world of build tools!&lt;/p&gt;
&lt;h1 id=&quot;automated-workflows-with-build-tools&quot;&gt;Automated workflows with build tools&lt;/h1&gt;
&lt;p&gt;A build tool is software that automates the transformation of source code into a deliverable. Any time a change is made to the source code, the build tool should be run - usually from the command line. The build tool is how we implement asset pipelines:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automated-workflows-asset-pipeline-with-tool.png&quot; alt=&quot;Asset pipeline automated by a build tool&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;available-build-tools&quot;&gt;Available build tools&lt;/h2&gt;
&lt;p&gt;There are many build tools available. This book focuses on the web and therefore looks at those tailored to HTML, CSS, and JavaScript. Grunt and Gulp, the two most popular, will be our focus because of their widespread adoption. There are many others, such as Broccoli, Middleman and Brunch, but this book’s principles apply to all build tools.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If your needs are simple, the package manager NPM can be used as a build tool - NPM along with Browserify can be quite a powerful combination. See &lt;a href=&quot;http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/&quot;&gt;http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/&lt;/a&gt; for details.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-build-file&quot;&gt;The build file&lt;/h2&gt;
&lt;p&gt;The build file tells the build tool what to do. It defines a set of tasks that the build tool can perform. In Grunt, this file is called &lt;code&gt;Gruntfile.js&lt;/code&gt;. In Gulp, it is called &lt;code&gt;Gulpfile.js&lt;/code&gt;. As a rule, the build file goes at the root of the project, above the &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; directories.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;OSX/Linux&lt;/th&gt;
&lt;th&gt;Windows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source dir&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/src&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\src&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build dir&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\build&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build file (Gulp)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/Gulpfile.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\Gulpfile.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build file (Grunt)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/user/myproject/Gruntfile.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C:\Users\user\myproject\Gruntfile.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;tasks&quot;&gt;Tasks&lt;/h2&gt;
&lt;p&gt;Build tools run tasks. A task is simply an action or a set of actions that can be performed. For example, a task could be &amp;quot;copy files from &lt;code&gt;src&lt;/code&gt; to &lt;code&gt;build&lt;/code&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;In most build tools, tasks are composable, meaning that a task can depend on or delegate to other tasks. For example, task &lt;code&gt;copy-assets&lt;/code&gt; could depend on task &lt;code&gt;clean&lt;/code&gt;, so that whenever &lt;code&gt;copy-assets&lt;/code&gt; is run, &lt;code&gt;clean&lt;/code&gt; is automatically run beforehand. The advantage of composability is that the code for the &lt;code&gt;clean&lt;/code&gt; task won’t be repeated every time you need to call it.&lt;/p&gt;
&lt;p&gt;Tasks are stored inside the build file; here is an example of a build file that contains some tasks:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automated-workflows-build-file.png&quot; alt=&quot;Build file containing tasks&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;anatomy-of-a-task&quot;&gt;Anatomy of a task&lt;/h3&gt;
&lt;p&gt;A task generally has these attributes:&lt;/p&gt;
&lt;dl&gt;
    &lt;dt&gt;Name&lt;/dt&gt;&lt;dd&gt;The name of the task. Most tasks can be run in isolation by passing the task’s name to the tool on the command line. For example, &lt;code&gt;grunt clean&lt;/code&gt; or &lt;code&gt;gulp clean&lt;/code&gt; would run the &lt;code&gt;clean&lt;/code&gt; task.&lt;/dd&gt;
    &lt;dt&gt;Description&lt;/dt&gt;&lt;dd&gt;Some build tools supply an optional task description, an explanation of the task that doubles as documentation for people on your team.&lt;/dd&gt;
    &lt;dt&gt;Dependencies&lt;/dt&gt;&lt;dd&gt;A list of tasks that must be run before a certain task can run. For example, the &lt;code&gt;build&lt;/code&gt; task may have &lt;code&gt;clean&lt;/code&gt; as a dependency, meaning that if you call the &lt;code&gt;build&lt;/code&gt; task, the &lt;code&gt;clean&lt;/code&gt; task automatically runs first.&lt;/dd&gt;
    &lt;dt&gt;Functionality&lt;/dt&gt;&lt;dd&gt;This is the specific code or configuration that you write to implement your task. For example, the &lt;code&gt;scripts&lt;/code&gt; task could minify and concatenate a set of files from &lt;code&gt;src&lt;/code&gt; and then copy them into &lt;code&gt;build/js&lt;/code&gt;.&lt;/dd&gt;
&lt;/dl&gt;



&lt;h1 id=&quot;creating-your-first-build-file&quot;&gt;Creating your first build file&lt;/h1&gt;
&lt;p&gt;We will create a build file that automates the workflow that we have defined. I’m not going to write the actual code here, as it will differ based for each build tool, but I will represent it in an abstract manner.&lt;/p&gt;
&lt;p&gt;These tasks will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clean the &lt;code&gt;build&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Compress and minify assets&lt;/li&gt;
&lt;li&gt;Copy the transformed results into the &lt;code&gt;build&lt;/code&gt; directory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is the order in which the tasks will run:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/your-first-build-file-task-order.png&quot; alt=&quot;Build file tasks running in order&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some build tools can run tasks in parallel; others will run them one at a time in sequence. In the diagram above, we have assumed that we can run &lt;code&gt;scripts&lt;/code&gt;, &lt;code&gt;styles&lt;/code&gt;, &lt;code&gt;images&lt;/code&gt; and &lt;code&gt;html&lt;/code&gt; in parallel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;explanation&quot;&gt;Explanation&lt;/h2&gt;
&lt;h3 id=&quot;task-clean-cleans-out-build-directory&quot;&gt;Task &lt;code&gt;clean&lt;/code&gt; - cleans out &lt;code&gt;build&lt;/code&gt; directory&lt;/h3&gt;
&lt;p&gt;This simple task cleans out the &lt;code&gt;build&lt;/code&gt; directory by deleting everything in it.&lt;/p&gt;
&lt;h3 id=&quot;task-build-calls-the-subtasks&quot;&gt;Task &lt;code&gt;build&lt;/code&gt; - calls the subtasks&lt;/h3&gt;
&lt;p&gt;Depends on task &lt;code&gt;clean&lt;/code&gt; via the dependency mechanism discussed earlier, so when &lt;code&gt;build&lt;/code&gt; is called, it first triggers &lt;code&gt;clean&lt;/code&gt;. After &lt;code&gt;clean&lt;/code&gt; completes, the build task delegates to the &lt;code&gt;scripts&lt;/code&gt;, &lt;code&gt;styles&lt;/code&gt;, &lt;code&gt;images&lt;/code&gt; and &lt;code&gt;html&lt;/code&gt; tasks.&lt;/p&gt;
&lt;h3 id=&quot;task-scripts-transforms-javascript&quot;&gt;Task &lt;code&gt;scripts&lt;/code&gt; - transforms javascript&lt;/h3&gt;
&lt;p&gt;Takes &lt;code&gt;src/js/a.js&lt;/code&gt; and &lt;code&gt;src/js/b.js&lt;/code&gt;, minifies them, then concatenates them into &lt;code&gt;build/js/all.min.js&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;task-styles-transforms-css&quot;&gt;Task &lt;code&gt;styles&lt;/code&gt; - transforms CSS&lt;/h3&gt;
&lt;p&gt;Takes &lt;code&gt;src/css/first.css&lt;/code&gt; and &lt;code&gt;src/css/second.css&lt;/code&gt;, minifies them, then concatenates them into &lt;code&gt;build/css/all.min.css&lt;/code&gt;. For designers writing in Sass or LESS, styles will also compile those files into CSS before minification and concatenation.&lt;/p&gt;
&lt;h3 id=&quot;task-images-compresses-images&quot;&gt;Task &lt;code&gt;images&lt;/code&gt; - compresses images&lt;/h3&gt;
&lt;p&gt;Takes the images in &lt;code&gt;src/img&lt;/code&gt;, compresses them, and outputs them to &lt;code&gt;build/img&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;task-html-transforms-html&quot;&gt;Task &lt;code&gt;html&lt;/code&gt; - transforms HTML&lt;/h3&gt;
&lt;p&gt;Takes &lt;code&gt;src/index.html&lt;/code&gt; and minifies it. It then modifies the HTML, directing the asset paths to &lt;code&gt;build&lt;/code&gt;, not &lt;code&gt;src&lt;/code&gt;. The output is then directed to &lt;code&gt;build/index.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once the &lt;code&gt;build&lt;/code&gt; task completes, you have your complete website, ready for use in the &lt;code&gt;build&lt;/code&gt; directory.&lt;/p&gt;
&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;
&lt;p&gt;For each task, there is an installable plugin for your build tool. This is great because it means you usually have to write very little code.&lt;/p&gt;
&lt;p&gt;The Gulp team maintains a list of verified plugins and their community ensures that there is only one plugin for each task. In contrast, the Grunt community often offers a number of alternatives for each plugin. The &lt;code&gt;grunt-contrib-*&lt;/code&gt; plugins are the best starting point because they are officially maintained.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The specifics of how to install and use these plugins are beyond the scope of this book.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;clean&lt;/td&gt;
&lt;td&gt;&lt;code&gt;del&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-clean&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scripts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-uglify&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-uglify&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;styles&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-minify-css&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-cssmin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;images&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-imagemin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-imagemin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;html&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-minify-html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-htmlmin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Look over the sample project for this book at &lt;a href=&quot;https://github.com/gavD/5ss-build-tools&quot;&gt;https://github.com/gavD/5ss-build-tools&lt;/a&gt;. There, you will find example build files for Grunt and Gulp that follow this approach.&lt;/p&gt;
&lt;h1 id=&quot;automating-your-workflow&quot;&gt;Automating your workflow&lt;/h1&gt;
&lt;p&gt;At this point, the areas in green are automated:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-1.png&quot; alt=&quot;Areas in green are automated&quot;&gt;&lt;/p&gt;
&lt;p&gt;Design and editing source code in &lt;code&gt;src&lt;/code&gt; isn’t automatable - if it were, robots would be doing our jobs. Therefore, we will omit these workflow stages from the future diagrams. The rest of these tasks, however, we can use build tools for.&lt;/p&gt;
&lt;h2 id=&quot;task-watch-automating-your-automation&quot;&gt;Task &lt;code&gt;watch&lt;/code&gt; - automating your automation&lt;/h2&gt;
&lt;p&gt;Right now, you are probably running the tool on the command line every time you make a change. This is pretty laborious, and also error prone - chances are you will make a change, forget to run the tool, reload the browser, and be confused as to why your changes aren’t showing up… I know I’ve certainly done that!&lt;/p&gt;
&lt;p&gt;Thankfully, we can automate this. We will create a new task, &lt;code&gt;watch&lt;/code&gt;, which will monitor the &lt;code&gt;src&lt;/code&gt; directory, and whenever anything changes in there, it automatically runs the default task, which has the &lt;code&gt;build&lt;/code&gt; task as a dependency:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-2.png&quot; alt=&quot;Using watch to automatically trigger builds&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, the build tool runs automatically when anything changes in &lt;code&gt;src&lt;/code&gt;, so that any time you update your source code, the website is regenerated automatically. This automates the build:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-3.png&quot; alt=&quot;Build automatically called&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;task-serve-run-a-local-server&quot;&gt;Task &lt;code&gt;serve&lt;/code&gt; - run a local server&lt;/h2&gt;
&lt;p&gt;Instead of constantly pushing code up to a web server, build tools allow you to run a server locally, which serves the &lt;code&gt;build&lt;/code&gt; directory, so you’re seeing the compressed, minified, concatenated versions of files, just like your users will. This means that we can remove the &amp;quot;Push to server&amp;quot; stage of the workflow entirely:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-4.png&quot; alt=&quot;Push to server stage removed&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don’t worry if you were hoping to cover deployment in your build workflow; we will talk about deployment later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;task-refresh-browser-refresh-your-browser&quot;&gt;Task &lt;code&gt;refresh-browser&lt;/code&gt;: refresh your browser&lt;/h2&gt;
&lt;p&gt;One task that we spend a lot of time doing is making changes, then going over to a browser and reloading the page. A LiveReload will ensure that when a build occurs in response to a change to &lt;code&gt;src&lt;/code&gt;, not only is the &lt;code&gt;build&lt;/code&gt; task called, but also the browser is automatically reloaded:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-5.png&quot; alt=&quot;Automatic browser reload&quot;&gt;&lt;/p&gt;
&lt;p&gt;We’ve now automated a huge amount of the workflow:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/using-build-tools/automating-your-workflow-6.png&quot; alt=&quot;Automate all the things!&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-do-we-use-to-write-these-tasks-&quot;&gt;What do we use to write these tasks?&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-watch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-connect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-connect&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refresh-browser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-livereload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-watch&lt;/code&gt; (built in)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h1 id=&quot;finished-build-file&quot;&gt;Finished build file&lt;/h1&gt;
&lt;p&gt;We end up with a set of tasks that we can run. Here are the &amp;quot;top level&amp;quot; tasks, i.e., the ones that we will commonly call from the command line:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Dependencies&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;default&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default task so that when your build tool is called with no parameters, it simply delegates to the &lt;code&gt;build&lt;/code&gt; task.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clean&lt;/code&gt;, &lt;code&gt;scripts&lt;/code&gt;, &lt;code&gt;styles&lt;/code&gt;, &lt;code&gt;images&lt;/code&gt;, &lt;code&gt;html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minifies, concatenates, and compresses assets, then moves the compressed versions into the &lt;code&gt;build&lt;/code&gt; directory.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;live-reload&lt;/code&gt;, &lt;code&gt;serve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Launches the local server, which serves the &lt;code&gt;build&lt;/code&gt; directory. Watches the &lt;code&gt;src&lt;/code&gt; directory. Any change to any file inside &lt;code&gt;src&lt;/code&gt; will trigger the &lt;code&gt;default&lt;/code&gt; task. This is the task you will run when you are working on your project, and it will whirr away in the background keeping everything up to date for you.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h1 id=&quot;what-else-can-build-tools-do-for-us-&quot;&gt;What else can build tools do for us?&lt;/h1&gt;
&lt;p&gt;We’ve automated the workflow that we defined earlier, but build tools can do lots more. Here are a few examples.&lt;/p&gt;
&lt;h2 id=&quot;linting&quot;&gt;Linting&lt;/h2&gt;
&lt;p&gt;Linting, also known as static analysis, is the automated inspection of your source code (files in &lt;code&gt;src&lt;/code&gt;). Think of it as having a more experienced colleague checking your work and making sure that you haven’t made any common mistakes.&lt;/p&gt;
&lt;p&gt;JavaScript can be automatically checked using a tool called &lt;code&gt;jshint&lt;/code&gt;. This can check for common performance, security, and stylistic problems. Following the recommendations of &lt;code&gt;jshint&lt;/code&gt; makes your code standards-compliant, and protects you from common clangers.&lt;/p&gt;
&lt;p&gt;Similarly, CSS can be linted using tools like &lt;code&gt;csslint&lt;/code&gt;. This can help you to automatically detect whether you’ve used invalid or deprecated rules. It can also help you to make more efficient CSS that the browser can use without friction.&lt;/p&gt;
&lt;p&gt;HTML can also be linted!&lt;/p&gt;
&lt;p&gt;I generally recommend obeying every recommendation that linters make - as legendary programmer John Carmack once put it, &amp;quot;If you have to explain it to the computer, you’ll probably have to explain it to your colleagues.&amp;quot;&lt;/p&gt;
&lt;p&gt;All linters can be &amp;quot;tuned&amp;quot; to your specific needs - for example, if you are breaking one rule for a good reason, then you can tell your linter to ignore it.&lt;/p&gt;
&lt;p&gt;Here are some example tools you could use:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Functionality&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lint css&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-csslint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-csslint&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lint javascript&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-jshint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-jshint&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify html&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-htmlhint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-htmlhint&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;css-preprocessing&quot;&gt;CSS preprocessing&lt;/h2&gt;
&lt;p&gt;CSS is great but it’s fiddly. A preprocessor makes CSS far easier to work with. I use LESS day-to-day, but there are many others, including Sass and Stylus. All preprocessors add features like variables, mixins, and so forth, which greatly reduce the amount of code you need to write and make it far easier to maintain.&lt;/p&gt;
&lt;p&gt;Using a preprocessor, the &lt;code&gt;styles&lt;/code&gt; task can transform styles into raw CSS. This means that you would never need to edit raw CSS; you could work entirely in the far more pleasant world of LESS (or whichever you prefer).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Functionality&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LESS to CSS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-less&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-less&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;script-preprocessing-transpiling-&quot;&gt;Script preprocessing (transpiling)&lt;/h2&gt;
&lt;p&gt;Instead of plain JavaScript, you might be using something like CoffeeScript. You would need a transpiling stage, which converts from CoffeeScript into JavaScript.&lt;/p&gt;
&lt;p&gt;You might also be using a more cutting-edge version of JavaScript than is available in current web browsers. At the time of writing, ES6 is a forthcoming version of JavaScript that is not available for general usage in many web browsers. Therefore, we can use tools to transpile it into ES5.&lt;/p&gt;
&lt;p&gt;Once you have these tools in your workflow, you would have your CoffeeScript or ES6 code in &lt;code&gt;src&lt;/code&gt;, and standard ES5 code in &lt;code&gt;build&lt;/code&gt;. It makes debugging a little more difficult, but it can be worth it if you want to use cutting edge features.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Functionality&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CoffeeScript transpiler&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-coffee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-contrib-coffee&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ES6 transpiler&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-babel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-babel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;push-to-server&quot;&gt;Push to server&lt;/h2&gt;
&lt;p&gt;Build tools can even be used for deployment. There are all sorts of options here and it is out of our scope to cover them in detail, so here are a few examples:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Functionality&lt;/th&gt;
&lt;th&gt;Gulp plugin&lt;/th&gt;
&lt;th&gt;Grunt plugin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FTP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-ftp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-ftp-deploy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Github pages&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-git-pages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-gh-pages&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rsync&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gulp-rsync&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grunt-rsync&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&quot;best-practice&quot;&gt;Best practice&lt;/h1&gt;
&lt;p&gt;Generally, you can use a build tool for any automation task. As with any software, build tools are open to misuse, however, so here are some guidelines to help you to make sure you are using the build tool as it was intended.&lt;/p&gt;
&lt;h2 id=&quot;never-edit-anything-in-the-build-directory&quot;&gt;Never edit anything in the &lt;code&gt;build&lt;/code&gt; directory&lt;/h2&gt;
&lt;p&gt;You should never manually edit anything in the &lt;code&gt;build&lt;/code&gt; directory. Similarly, your build tool should never modify anything in the &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;If there is anything that you have to do in the &lt;code&gt;build&lt;/code&gt; directory, you can almost certainly find a way to get the tool to do it for you.&lt;/p&gt;
&lt;h2 id=&quot;never-let-your-build-tool-modify-anything-in-the-src-directory&quot;&gt;Never let your build tool modify anything in the &lt;code&gt;src&lt;/code&gt; directory&lt;/h2&gt;
&lt;p&gt;Conversely, if your build tool modifies your &lt;code&gt;src&lt;/code&gt; directory, you are going to have a bad time. Such behaviour breaks the &amp;quot;pipeline&amp;quot; approach and can create circular actions that never fully resolve. Therefore, you need to be confident that your build tool will stay out of the &lt;code&gt;src&lt;/code&gt; directory entirely.&lt;/p&gt;
&lt;p&gt;Think of it like this: &lt;code&gt;src&lt;/code&gt; is yours, &lt;code&gt;build&lt;/code&gt; belongs to your build tool.&lt;/p&gt;
&lt;h2 id=&quot;short-sharp-composable-tasks&quot;&gt;Short, sharp, composable tasks&lt;/h2&gt;
&lt;p&gt;Whilst you CAN create tasks that are huge and have a large amount of code, it is usually better to separate these into smaller tasks and compose them using task dependencies.&lt;/p&gt;
&lt;h2 id=&quot;your-normal-workflow-should-be-encapsulated-by-a-single-task&quot;&gt;Your normal workflow should be encapsulated by a single task&lt;/h2&gt;
&lt;p&gt;You shouldn’t need to be constantly running a bunch of separate tasks. Instead, one task should rely upon or kick off the subtasks that it needs. Generally, you should use some kind of &lt;code&gt;watch&lt;/code&gt; and run it in the background. As you do your normal work, it will detect changes, and then run everything it needs to.&lt;/p&gt;
&lt;p&gt;If you’re finding yourself constantly having to stop your watch task and run things, then consider putting them into your main (default) task.&lt;/p&gt;
&lt;h2 id=&quot;have-tasks-that-aren-t-part-of-your-main-workflow-as-separate-tasks&quot;&gt;Have tasks that aren’t part of your main workflow as separate tasks&lt;/h2&gt;
&lt;p&gt;Conversely, for tasks that aren’t part of your regular workflow, don’t have the main workflow call them.&lt;/p&gt;
&lt;p&gt;For example, you don’t want to deploy every tiny little tinker you make in your local workspace. Therefore, you might have a task like &lt;code&gt;deploy&lt;/code&gt; that you only call once you’ve done all of your testing and you’re confident that it’s time to go live.&lt;/p&gt;
&lt;h2 id=&quot;don-t-store-credentials-in-plain-text&quot;&gt;Don’t store credentials in plain text&lt;/h2&gt;
&lt;p&gt;Speaking of deployments, it might be tempting to store things like passwords or authentication tokens in your build file. This is generally a bad move from a security perspective - if someone accesses your build file, they could compromise your live systems.&lt;/p&gt;
&lt;p&gt;A full treatment of security issues is outside of the scope of this book, but suffice to say, don’t store credentials in plain text and certainly don’t keep them directly in your build file.&lt;/p&gt;
&lt;h2 id=&quot;debugging-with-source-maps&quot;&gt;Debugging with source maps&lt;/h2&gt;
&lt;p&gt;If you have &amp;quot;compiled&amp;quot; (minified, concatenated) JavaScript code in &lt;code&gt;build&lt;/code&gt;, it will look different to your code in &lt;code&gt;src&lt;/code&gt;. It will have had whitespace removed, variable names shortened - all sorts of changes that make it hard to debug. You can use a source map to help you here. A source map holds information about your original source files. Browsers like Chrome and Firefox support source maps, and enable you to debug as if you were using your original code. This is really handy as it means you are testing the same code the user would receive, but debugging it in its original form.&lt;/p&gt;
&lt;p&gt;Similarly, with a CSS preprocessor like LESS or SaSS, the CSS in &lt;code&gt;build&lt;/code&gt; is different to the CSS in &lt;code&gt;src&lt;/code&gt;. LESS and SaSS support source maps as well, so you can use the same approach.&lt;/p&gt;
&lt;h2 id=&quot;being-idiomatic&quot;&gt;Being idiomatic&lt;/h2&gt;
&lt;p&gt;Try to ensure that your project is idiomatic. By that, I mean that you should follow the conventions that other people use for similar projects. This has the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easier to apply code snippets you find online&lt;/li&gt;
&lt;li&gt;Easier to explain to people than some bespoke system&lt;/li&gt;
&lt;li&gt;The wheel remains un-reinvented!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a couple of ways you could go about this. Firstly, you could clone an existing repository and modify it to suit your needs. Feel free to clone the sample source code for this book from &lt;a href=&quot;https://github.com/gavD/5ss-build-tools&quot;&gt;https://github.com/gavD/5ss-build-tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The second option is to use a scaffolding tool. These are tools that create a &amp;quot;skeleton&amp;quot; project for your app that has the tools you will need installed and ready to use. So, you don’t have to create the &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; directories, and you don’t have to create your build file - your scaffolding tool does it all for you. Handy!&lt;/p&gt;
&lt;p&gt;If you’re starting with a brand-new app, &lt;a href=&quot;http://yeoman.io/&quot;&gt;Yeoman&lt;/a&gt; is a great scaffolding tool that uses generators to get you up and running with a project structure. It supports a huge range of project types. For example, are you building an AngularJS app? Then use the yeoman angular generator! Working on a PhoneGap project? Then use the yeoman phonegap generator! No matter what you are building, there is likely to be a Yeoman generator that can help you to get started.&lt;/p&gt;
&lt;h2 id=&quot;see-also-browserify&quot;&gt;See also: Browserify&lt;/h2&gt;
&lt;p&gt;Check out Browserify. It’s not a build tool as such, but it offers a nice minimalist approach to the JavaScript asset pipeline.&lt;/p&gt;
&lt;h1 id=&quot;go-forth-and-build-&quot;&gt;Go forth and build!&lt;/h1&gt;
&lt;p&gt;In this book, we started out by looking at common web development workflows. We then went on to look at how we can improve upon that workflow. We then took a detailed look at what a build tool is, what a build file is, and what tasks are. We then went through creating some tasks to automate the workflow.&lt;/p&gt;
&lt;p&gt;Thanks for reading, I hope that this book has been a useful introduction to the wonderful world of build tools!&lt;/p&gt;
&lt;h1 id=&quot;further-reading&quot;&gt;Further reading&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;James Cryer’s &lt;a href=&quot;http://www.amazon.co.uk/Pro-Grunt-js-James-Cryer/dp/1484200144&quot;&gt;Pro Grunt.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Travis Maynard’s &lt;a href=&quot;http://www.amazon.co.uk/Getting-Started-Gulp-Travis-Maynard/dp/1784395765&quot;&gt;Getting Started with Gulp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;thanks&quot;&gt;Thanks&lt;/h1&gt;
&lt;p&gt;Many thanks to the following proof readers for valuable insights and corrections:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nate Abele&lt;/li&gt;
&lt;li&gt;Andrew Canham&lt;/li&gt;
&lt;li&gt;Kathryn Davies&lt;/li&gt;
&lt;li&gt;Aryella Lacerda&lt;/li&gt;
&lt;li&gt;John Mercer&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;download-as-pdf&quot;&gt;Download as PDF&lt;/h1&gt;
&lt;p&gt;Use the button below to get the book in its original form.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;/downloads/Using-Build-Tools.pdf&quot; title=&quot;Download the book in its original form&quot;&gt;Download as PDF&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>Picking up the ball</title><link>http://radify.io/blog/recovering-from-failure/</link><pubDate>Wed, 27 Apr 2016 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/recovering-from-failure/</guid><author></author><description>&lt;p&gt;Recently, Mark posted &lt;a href=&quot;http://radify.io/blog/avoiding-bumbling-professionals/&quot;&gt;an article about recovering from a failed relationship&lt;/a&gt;. This got me thinking that a certain amount of failure should perhaps be expected as part of doing business -  not least because failure can be incredibly instructive.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve made some great mistakes in my time. In my first job, I accidentally emailed some classic Gothic fiction to a large number of customers. Thankfully, I was not subjected to the fate as Poe&amp;#39;s protagonists, but I&amp;#39;ve never forgotten the sweaty palmed terror as the realisation gradually dawned on me that I had failed to check the &amp;quot;test mode&amp;quot; box...&lt;/p&gt;
&lt;p&gt;At conferences and meetups, in blog posts and tweets, successes are shouted. Perhaps there is something of a &lt;strong&gt;cult of competence&lt;/strong&gt;. Most of us are obsessed with appearing hyper-competent, but really, we are not paid to be right all the time - we are paid to build value. Naturally, all organisations want to look as competent as possible, but the truth is that every individual makes mistakes, and no process can prevent them all. As organisations are made up of people, it follows that every organisation makes mistakes.&lt;/p&gt;
&lt;p&gt;In a 2012 talk entitled &amp;quot;&lt;a href=&quot;https://vimeo.com/37279704&quot;&gt;the loneliness of the long distance coder&lt;/a&gt;&amp;quot;, Carey Hiles admitted to some priceless blunders. Four years on from that talk, I still hear people talk about how it was encouraging to hear someone admit to mistakes. Similarly, Craig and I occasionally talk about screw ups on the &lt;a href=&quot;http://www.neveroutofbetapodcast.com/&quot;&gt;Never Out of Beta podcast&lt;/a&gt;, and the feedback from our listeners has been that it&amp;#39;s good to hear experienced engineers talk as candidly as possible about their weaknesses.&lt;/p&gt;
&lt;p&gt;If taking ownership of our fallibility can be encouraging to our peers, can there also be benefits to our organisations? Perhaps even benefits to our clients?&lt;/p&gt;
&lt;h2 id=&quot;prevention-of-and-elegant-recovery-from-failure&quot;&gt;Prevention of and elegant recovery from failure&lt;/h2&gt;
&lt;p&gt;Pretending we are perfect as an organisation is fooling no-one, least of all ourselves. Accepting occasional failure as part of doing business enables us to be proactive on three fronts:&lt;/p&gt;
&lt;h3 id=&quot;1-reduce-the-likelihood-of-failure&quot;&gt;1. Reduce the likelihood of failure&lt;/h3&gt;
&lt;p&gt;We learn, grow and improve over time to make a &lt;strong&gt;better class of mistake&lt;/strong&gt;. That is, instead of making &amp;quot;novice errors&amp;quot; with wide consequences, we make more sophisticated clangers that have fewer ramifications. A more experienced engineer, for example, will partition work in such a way that a failure in one module will not disable an entire system. The novice, having experienced fewer errors, may not think in such terms. The experienced engineer will still have problems, but they are of a better class - no longer the sweepingly disastrous bumblings of the neophyte.&lt;/p&gt;
&lt;h3 id=&quot;2-reduce-the-cost-of-failure&quot;&gt;2. Reduce the cost of failure&lt;/h3&gt;
&lt;p&gt;As part of accepting that failures occur, it is wise to make it easier to recover from problems. This can include technical aspects such as having a disaster recovery (DR) strategy, continuous deployment, and rolling backups. The non-technical side is even more important - you should also have good, honest, &lt;strong&gt;genuinely respectful relationships with your clients&lt;/strong&gt;. Think about your relationships with your family - some of the same things that allow you to recover from arguments with your family - respect, trust - come into play when a deployment goes wrong and you have to tell the client.&lt;/p&gt;
&lt;h3 id=&quot;3-respond-proactively-to-failure&quot;&gt;3. Respond proactively to failure&lt;/h3&gt;
&lt;p&gt;This may sound cliched, but &lt;strong&gt;try treating a mistake as a lesson&lt;/strong&gt; - it&amp;#39;s an opportunity to improve your process, tooling or knowledge. The very fact that a failure has occurred demonstrates room for improvement.&lt;/p&gt;
&lt;h2 id=&quot;going-public-boundaries-in-response-to-failure&quot;&gt;Going public? Boundaries in response to failure&lt;/h2&gt;
&lt;p&gt;Sometimes, we can derive general instructions from a specific failure and publish those in the form of &lt;a href=&quot;http://radify.io/blog/overachieving-software-projects/&quot;&gt;secondary deliverables&lt;/a&gt;. This is not something to be taken lightly, however - whilst we believe that we shouldn&amp;#39;t shovel all our errors under the carpet, it&amp;#39;s naive to think that we should broadcast every mistake.&lt;/p&gt;
&lt;p&gt;Once we have resolved an issue, there are 3 sets of people that we may inform:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/recovering-from-failure/failure-announcement-groups.png&quot; alt=&quot;Failure announcement groups&quot;&gt;&lt;/p&gt;
&lt;p&gt;We should generally inform the first set, our colleagues, of most non-trivial problems - there are certain problems that can be resolved internally and need go no further. This is where an organisation does a lot of its learning and growing. Agile retrospectives are just one example of how this may be applied.&lt;/p&gt;
&lt;p&gt;The second set of people, clients, should not be bombarded with every triviality, but if an incident seriously affected them, it is worth discussing with them how it can be prevented and whether things can be improved. Discussion of mistakes with clients should:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Be honest&lt;/li&gt;
&lt;li&gt;Be timely (otherwise trust becomes eroded)&lt;/li&gt;
&lt;li&gt;Be accompanied with a strategy to prevent the issue in future&lt;/li&gt;
&lt;li&gt;Give them options, but leave them in charge&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From the client&amp;#39;s perspective, they should see our organisations respond proactively and professionally. This can actually improve trust and help us to work together with our clients: psychologically speaking, occasional failures, if recovered from professionally, actually improve the perception of an organisation.&lt;/p&gt;
&lt;p&gt;Our first responsibility is to our clients and we must never leave them exposed; we should never disclose anything that can harm our client&amp;#39;s reputation, business or security. If we can anonymise an incident, we may, with a client&amp;#39;s consent, consider &amp;quot;go public&amp;quot; to our third set of people - the world at large - with some lessons learned from the problem. This diagram defines a potential flow for responding to a failure and maximising benefit without exposing a client:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/recovering-from-failure/failure-response-flowchart.png&quot; alt=&quot;Failure response flowchart&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Anything you &amp;quot;go public&amp;quot; with must be anonymised and must not give away any of the client&amp;#39;s information&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;is-there-an-optimal-failure-rate-&quot;&gt;Is there an optimal failure rate?&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve suggested that occasional failures can help us to reassess our processes, tools and skills and demonstrate our ability to react, change and improve. If, however, we make mistakes frequently, are simply incompetent and do not benefit. If, however, we never make mistakes at all, perhaps we are stagnant and in a false sense of security. Perhaps there is such a thing as an &lt;strong&gt;optimal failure rate&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/recovering-from-failure/optimum-failure-ratio.png&quot; alt=&quot;Optimum failure ratio&quot;&gt;&lt;/p&gt;
&lt;p&gt;This hypothetical sweet spot could be expressed as &amp;quot;things rarely go wrong, but when they do, the organisation responds very quickly,&amp;quot; a state of affairs which inspires maximum confidence in clients.&lt;/p&gt;
&lt;p&gt;Failures can be classified into two camps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;quot;True&amp;quot; failures that affect your customers and their customers&lt;/li&gt;
&lt;li&gt;Failures caught by process and automation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The latter category of failures prevented from ever manifesting &amp;quot;in the wild&amp;quot; by processes, practises and automation you have designed to avoid &amp;quot;true&amp;quot; failures.&lt;/p&gt;
&lt;p&gt;The ratio of these failures can be compared to an &lt;strong&gt;Optimal Failure Ratio (OFR)&lt;/strong&gt;. This allows us to accept the potential for future failure and continually improve guards to protect our colleagues, clients and the world at large from ever having to experience them.&lt;/p&gt;
&lt;p&gt;The reason why ratio is better than rate is because rate is just a indicator, ratio is a measure against something else. If you can&amp;#39;t measure you&amp;#39;re relegated to being only an observer. &lt;strong&gt;Failure rate is interesting, while ratio is actionable&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;All organisations and individuals make mistakes, but we can use them to learn, improve and build trust. There are even advantages to occasional failures, provided we respond to them professionally and do not exceed the Optimal Failure Ratio (OFR). We can also derive some useful secondary deliverables using lessons learned from failures.&lt;/p&gt;
</description></item><item><title>Rise of the machine users</title><link>http://radify.io/blog/rise-of-the-machine-users/</link><pubDate>Wed, 06 Apr 2016 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/rise-of-the-machine-users/</guid><author></author><description>&lt;p&gt;With the rise of microservice architectures, an increasing amount of what we do is weaving parts of Amazon Web Services (AWS) into distributed applications.&lt;/p&gt;
&lt;p&gt;To manage these components, we use a large amount of automation. To use AWS programmatically, you need keypairs, which are associated with user accounts. In this article, we’ll take a look at our approach to managing these accounts.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We’ll talk about AWS here, but the principles in this article cover can be applied more broadly.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;common-mistakes-overpowered-users&quot;&gt;Common mistakes - overpowered users&lt;/h2&gt;
&lt;p&gt;Many organisations simply have one AWS user with administrative privileges and generate a keypair for this user, which they use for everything. Similar to the &lt;a href=&quot;https://en.wikipedia.org/wiki/God_object&quot;&gt;&amp;quot;God Object&amp;quot; anti-pattern&lt;/a&gt;, this is lazy and very dangerous for three reasons.&lt;/p&gt;
&lt;p&gt;Firstly, if the API keys for this machine user are compromised, an attacker can do anything in the application.&lt;/p&gt;
&lt;p&gt;Secondly, if an organisation is using a key/value pair for a &amp;quot;real&amp;quot; user, that user could end up locked out of their own account!&lt;/p&gt;
&lt;p&gt;Thirdly, even if there is no compromise, the fact that automation has more privileges than it needs means that it can misbehave - for example, it might terminate all nodes when you only meant to terminate a certain group of nodes, or it might drop a database.&lt;/p&gt;
&lt;h2 id=&quot;better-practise-machine-users&quot;&gt;Better practise - machine users&lt;/h2&gt;
&lt;p&gt;The essence of security is the &lt;em&gt;principle of least privilege&lt;/em&gt; - only give the minimal permissions necessary. It follows that our objectives in setting up our automation users are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Limit what an attacker can do if a keypair is compromised&lt;/li&gt;
&lt;li&gt;Use a keypair that is not tied to a real human being&lt;/li&gt;
&lt;li&gt;Limit what an application can do if it misbehaves&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To do this, we configure &lt;strong&gt;machine users&lt;/strong&gt;. Machine users are user accounts that don’t have a login password — they can’t use the AWS console. They’re not people, they’re simply accounts that are created to fulfil specific purposes. When faced with an automation task, we create a specific AWS user to do that task and only that task — we never give it administrative privileges, or access to services it doesn’t need.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;
&amp;quot;In future user X might need role Y&amp;quot; is faulty thinking — you should add roles when and only when you need them.
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;We generally set up multiple machine users for a project: one might have the responsibility of provisioning EC2 nodes, whereas another would be responsible for managing a static S3 bucket where the application uploads files. After all, provisioning servers in DevOps land and end users uploading files in userland are very different concerns, so it makes sense for separate machine users to be assigned these privileges.&lt;/p&gt;
&lt;p&gt;This approach meets our objectives:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If a key is captured, an attacker can only do what that machine user can do.&lt;/li&gt;
&lt;li&gt;If a key is captured, no human’s account is compromised. We have a clean separation of responsibilities between humans and automatons. &lt;/li&gt;
&lt;li&gt;If the application misbehaves, it is doing so in a &amp;quot;sandbox&amp;quot; and the catastrophe will be contained.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are further advantages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The machine user can be invalidated in one fell swoop.&lt;/li&gt;
&lt;li&gt;In logs, we can clearly see which machine users are doing what, rather than having some generic user doing everything. This helps us to identify misbehaviour.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Essentially, we have restricted each machine user on 2 axes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What the machine user can do&lt;/li&gt;
&lt;li&gt;Where the machine user can do it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Similar to the &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;DevOps principle&lt;/a&gt; of &amp;quot;treat servers like cattle, not like pets&amp;quot;, machine users should be treated as disposable. They are not precious things, so don’t give them a funky name that might cause you to get attached to them!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Do you use cloud services? Are you using machine users? A good place to start is the AWS documentation on IAM (Identity and Access Management) roles.&lt;/p&gt;
</description></item><item><title>Aspect-Oriented Programming In PHP</title><link>http://radify.io/blog/aspect-oriented-programming/</link><pubDate>Tue, 29 Mar 2016 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/aspect-oriented-programming/</guid><author></author><description>&lt;p&gt;There are always units or features in an application which need to &amp;quot;cut across&amp;quot; many different parts of the architecture at once.&lt;/p&gt;
&lt;p&gt;This problem is not really obvious when you are using a &amp;quot;full-featured&amp;quot; framework. Indeed, since your issue is probably a common one, there&amp;#39;s a good chance the framework resolved this cross-cutting issue either by sacrificing separation of concerns or by providing an abstraction on top the framework to solve it. A number of frameworks use an event-driven architecture to address the cross-cutting problem. But there&amp;#39;s always a point where the framework can&amp;#39;t provide the control you need in a specific piece of logic. This is particularly the case if you&amp;#39;re using a microframework or prefer building your own one with specialised libraries. The more your application respects the separation of concerns principle, the more your cross cutting needs will come to play a crucial role in your architecture.&lt;/p&gt;
&lt;h2 id=&quot;aspect-oriented-programming-in-php&quot;&gt;Aspect-Oriented programming in PHP&lt;/h2&gt;
&lt;p&gt;Aspect-Oriented Programming, or AOP, is a programming paradigm that focuses on the organization and modularity of cross-cutting concerns. Use cases can be, for example, ACL, logging, error handling, or caching.&lt;/p&gt;
&lt;p&gt;PHP&amp;#39;s built-in (internal) assumptions (i.e. when you define a function/constant/class it stays defined forever) make the AOP paradigm difficult to implement.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/UnionOfRAD/lithium&quot;&gt;Li3&lt;/a&gt; was the first one to address the cross cutting issue by offering a filter mechanism to allows to filter method&amp;#39;s logic through closures. The Li3&amp;#39;s implementation requires manually adding some necessary boilerplate code to make a method filterable. With such a constraint, AOP techniques are limited to filtered methods.&lt;/p&gt;
&lt;p&gt;The others well known AOP implementation in PHP are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/AOP-PHP/AOP&quot;&gt;AOP&lt;/a&gt; (PECL extension)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/lisachenko/go-aop-php&quot;&gt;Go!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AOP PECL extension is an interesting approach and at the same time a risky gamble since it&amp;#39;s a PECL extension which is not a widely supported. The other option is the &lt;a href=&quot;https://github.com/lisachenko/go-aop-php&quot;&gt;Go!&lt;/a&gt; library which is an AOP implementation which patches PHP code on the fly to allow AOP techniques to be used.&lt;/p&gt;
&lt;p&gt;There are other existing implementations, but most of them are workarounds based on top of proxies (to the best of my knowledge), an approach which has a lot of limitations.&lt;/p&gt;
&lt;h2 id=&quot;a-new-kid-on-the-block&quot;&gt;A new kid on the block&lt;/h2&gt;
&lt;p&gt;Automatic code generation is not new in PHP, and is used in a number of libraries like &lt;a href=&quot;https://github.com/Ocramius/ProxyManager&quot;&gt;ProxyManager&lt;/a&gt; to name one. And thanks to the adoption of Composer, &lt;a href=&quot;https://github.com/lisachenko/go-aop-php&quot;&gt;Go!&lt;/a&gt; also demonstrates that Just In Time code patching was possible.&lt;/p&gt;
&lt;p&gt;If code generation is easy, code patching is a bit more complicated. First, because PHP doesn&amp;#39;t provide a built-in code parser, and also because there aren&amp;#39;t a lot of libraries addressing the PHP code parsing problem. The best known is the &lt;a href=&quot;https://github.com/nikic/PHP-Parser&quot;&gt;PHP-Parser&lt;/a&gt; library. PHP-Parser is a great tool, but the fact it simply ignores whitespace formating in its generated abstract syntax trees makes it problematic to use for some code patching. Indeed, the code to be patched is the real executed code. So if you want to have your backtrace accurate on errors, the line numbers need to be respected in patched files.&lt;/p&gt;
&lt;p&gt;So we used the &lt;a href=&quot;https://github.com/crysalead/kahlan&quot;&gt;Kahlan&lt;/a&gt;&amp;#39;s JIT code patcher for this task. Kahlan is a new Unit &amp;amp; BDD test framework which allows stubbing or monkey patching your code directly like in Ruby or JavaScript, thanks to some JIT patching techniques. Under the hood, this library is based on a rudimentary PHP parser but it has proven to be fast and stable enough for our needs here.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/crysalead/filter&quot;&gt;filter library is available at github.com/crysalead/filter&lt;/a&gt; and can be used like the following.&lt;/p&gt;
&lt;p&gt;First, the JIT code patcher must be initialized as soon as possible (for example just after including the composer autoloade) like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/../vendor/autoload.php'&lt;/span&gt;;

&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Lead&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Filter&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Filters&lt;/span&gt;;

Filters::patch(&lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that code patching will only work for classes loaded by the Composer autoloader. If a class is included using a &lt;code&gt;require&lt;/code&gt; or &lt;code&gt;include&lt;/code&gt; statement, or has already been loaded before the &lt;code&gt;Filters::patch(true)&lt;/code&gt; call, it won&amp;#39;t be patched.&lt;/p&gt;
&lt;p&gt;By default all patched code will be stored in the &lt;code&gt;/tmp/jit&lt;/code&gt; folder but you can set your own:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;Filters::patch(&lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;, [&lt;span class=&quot;string&quot;&gt;'cachePath'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;string&quot;&gt;'my/cache/path/jit'&lt;/span&gt;]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cached files will be regenerated automatically every time a PHP file is modified.&lt;/p&gt;
&lt;p&gt;Warning! Because &lt;code&gt;Filters::patch(true)&lt;/code&gt; is the no-brainer way to setup the patcher, you should keep in mind that all your code will be patched. Having all methods of your codebase (and vendor code) to be wrapped inside a filter closure can be time-consuming.&lt;/p&gt;
&lt;p&gt;Fortunately, if cross cutting concerns play a crucial role in well designed code, it&amp;#39;s only required in a couple of methods in a project. So, the prefered approach is to only patch the methods which are going to be filtered:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;Filters::patch([
 &lt;span class=&quot;string&quot;&gt;'A\ClassName'&lt;/span&gt;,
 &lt;span class=&quot;string&quot;&gt;'An\Example\ClassName::foo'&lt;/span&gt;,
 &lt;span class=&quot;string&quot;&gt;'A\Second\Example\ClassName'&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt;],
], [
    &lt;span class=&quot;string&quot;&gt;'cachePath'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;string&quot;&gt;'my/cache/path/jit'&lt;/span&gt;,
]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That way, you can choose to patch all methods of a specific class, one method only, or just a couple of them.&lt;/p&gt;
&lt;h2 id=&quot;the-filter-api&quot;&gt;The Filter API&lt;/h2&gt;
&lt;p&gt;Now that the JIT patcher is enabled, let&amp;#39;s create a logging filter:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Chaos&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Filter&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Filters&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Chaos&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Database&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Database&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Monolog&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Logger&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Monolog&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Handler&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;StreamHandler&lt;/span&gt;;

&lt;span class=&quot;variable&quot;&gt;$logger&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Logger(&lt;span class=&quot;string&quot;&gt;'database'&lt;/span&gt;);
&lt;span class=&quot;variable&quot;&gt;$logger&lt;/span&gt;-&amp;gt;pushHandler(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; StreamHandler(&lt;span class=&quot;string&quot;&gt;'my/log/path/db.log'&lt;/span&gt;, Logger::WARNING));

Filters::apply(Database::class, &lt;span class=&quot;string&quot;&gt;'query'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$next&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$sql&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$data&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$options&lt;/span&gt;)&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$logger&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$logger&lt;/span&gt;-&amp;gt;info(&lt;span class=&quot;string&quot;&gt;'Ran SQL query: '&lt;/span&gt; . &lt;span class=&quot;variable&quot;&gt;$sql&lt;/span&gt;);
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$next&lt;/span&gt;(&lt;span class=&quot;variable&quot;&gt;$sql&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$data&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$options&lt;/span&gt;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above example creates a SQL query logger filter for the Chaos database library. More information on &lt;a href=&quot;https://github.com/crysalead/filter&quot;&gt;the filter API at github.com/crysalead/filter&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;AOP is, in my opinion, the true answer for all cross cutting concerns. All other abstractions are at the same time unnecessary and most of the time limited to a specific scope. I have not given up hope that one day PHP will provide a built-in Aspect-Oriented Programming API, but for the moment, I think JIT code patching is the best option, since the benefits largely outperform the CPU overhead which is almost negligible when the JIT code patching is not applied globally.&lt;/p&gt;
</description></item><item><title>Avoiding Bumbling Professionals</title><link>http://radify.io/blog/avoiding-bumbling-professionals/</link><pubDate>Tue, 15 Mar 2016 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/avoiding-bumbling-professionals/</guid><author></author><description>&lt;p&gt;A few years ago April 15th started with a bang. We were embarking on a year-long journey of unanticipated costs, cleaning up our books, tax filings, and corporate records. The problem was, we had no idea it was coming. It started with an impromptu conference call: it was our certified public accountant (CPA) telling us that we’d need to file an extension and make huge estimated tax payments that were due &lt;em&gt;by the end of the day&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But this was only the beginning: it took the next several months for the full extent of our CPA’s malfeasance to become clear.&lt;/p&gt;
&lt;p&gt;Today we are in a completely different place thanks to our new accountant Regina O&amp;#39;Keefe (CPA, CVA) at the firm &lt;a href=&quot;http://gpmllp.net/&quot;&gt;Gable Peritz Mishkin, LLP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking back at the journey we took in 2014 from that shocking call to finding Gable Peritz Mishkin to setting things straight holds a number of important lessons for anyone looking to grow a business or clean up from a failed professional relationship.&lt;/p&gt;
&lt;p&gt;No business is an island and any growing business can benefit tremendously from the hard work and pertinent expertise of the right professionals. But the stakes are high because choosing the right professional can be tricky and getting the wrong professional can serve the equivalent of a punch to the gut.&lt;/p&gt;
&lt;p&gt;Here are some notes on how to find the best professional and avoid what I now refer to as a &amp;quot;Bumbler.”&lt;/p&gt;
&lt;h2 id=&quot;get-to-know-yourself&quot;&gt;Get To Know Yourself&lt;/h2&gt;
&lt;p&gt;This is the place to start. Make a short list of things that are important to your organization and will be absolutely necessary for a successful business relationship with a Professional. This might be as fundamental as mine were: “highly responsive and proactive” or as practical as “is comfortable with Google Docs.”&lt;/p&gt;
&lt;p&gt;If you are very proactive maybe you can successfully work with a more reactive firm but it’s important to know for sure so that you don’t end up in a reactive/reactive relationship.&lt;/p&gt;
&lt;p&gt;Defining the key requirements helped me narrow in on exactly who would be best for us. The two firms we shied away from had only part of the equation. The first was technically savvy but was not proactive and ignored several follow-up e-mails and phone calls. The second was proactive but was clearly uninterested in the fact that our firm doesn’t use paper fax machines to share documents.&lt;/p&gt;
&lt;p&gt;Both looked great on paper -- well recommended, professional, and easy to talk with: But by knowing ourselves we avoided getting swept up in those things and could stay focused on finding the best possible match &lt;em&gt;for us&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;do-your-own-research&quot;&gt;Do Your Own Research&lt;/h2&gt;
&lt;p&gt;We got burned by a Bumbling CPA that was/is very well-respected and enjoys glowing references from many businesses in our industry. They even market themselves as cutting-edge specialists for small, tech-savvy organizations. A seemingly perfect fit. A quick scan showed every indication that we should have been treated as well as everyone else. (And, to be fair, I’m sure there are clients who did not have the same disastrous outcome as us.)&lt;/p&gt;
&lt;p&gt;But not only were we not treated fairly -- we were actively harmed. So how does one avoid being underserved (or even worse, sucker punched) by a Bumbler?&lt;/p&gt;
&lt;p&gt;By the time we were again searching for our next CPA I knew to hold recommendations loosely and (once I had someone whom I felt met our personality well) was prepared with the following key questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How big is your client base &amp;amp; firm? (What’s the fish-size/pond-size ratio?)&lt;/li&gt;
&lt;li&gt;What are your specialties? (Familiarity with our filing status, states, and industry?)&lt;/li&gt;
&lt;li&gt;Who will be handling your account primarily? (Will we be quickly relegated to the lowest-paid team member?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I asked these question and outlined the background of the damages we were trying to repair. Instead of a slick-talking sales approach or lofty corporate goals the answers I received from Regina were no-nonsense and pertinent to our unique situation -- and without ego. This is, I realized, the hallmark of a true professional: actually listening and responding.&lt;/p&gt;
&lt;h2 id=&quot;avoid-billing-conflicts&quot;&gt;Avoid Billing Conflicts&lt;/h2&gt;
&lt;p&gt;I doubt many CPAs do blanket use-it-or-lose-it style monthly retainers. Our Bumbler did. We signed up for a monthly retainer that included a defined list of online software and a number of tasks and quarterly meetings. This pricing plan seemed progressive at first but, in retrospect, it created a clear conflict of interest because we were committed to making the same high month-after-month payment without clearly defined deliverables associated with the cost. This pricing approach itself is fine but when combined with a lack of structure and definition it provides too much incentive to under-deliver. That is, the firm’s character must be strong or the relationship can become a money grab.&lt;/p&gt;
&lt;p&gt;Pricing structure is often the clearest window into the heart of an organization.&lt;/p&gt;
&lt;p&gt;Deposits and retainers are normal; don’t get me wrong; but unless you have a high level of trust, it’s important that billing is transparent, detailed, and is tied as tightly as possible to work actually performed. Billing that makes little room for accountability is a clear warning sign.&lt;/p&gt;
&lt;h2 id=&quot;be-sensitive-to-the-other-warning-signs&quot;&gt;Be Sensitive to the other Warning Signs&lt;/h2&gt;
&lt;p&gt;If you are worried that you might already be working with a Bumbler, here are a few warning signs we ignored until it was too late:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The fees were growing and increasingly tied to gimmicks like secure file vaults and overkill processes that we didn’t ask for and never used. Worse still, they should have known this or inquired after a year or so. &lt;em&gt;At some point we became a billing item and not a client.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Meeting schedules spelled out in the contract never materialized. Our Bumbling professional was not interested in leading the conversation or, it seemed, helping at all. This is critical because the passive approach was the opposite of how they characterized their service in the agreement. &lt;em&gt;They weren’t being honest with themselves or us.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;In the few meetings actually held the questions raised demonstrated a lack of basic knowledge of our business... even years (and a pile of money) into our working relationship. &lt;em&gt;We had made a significant financial commitment which wasn’t being reciprocated.&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;Missed deadlines. We leaned on our CPA to be proactive and deal with legally-required deadlines without hand-holding. When several early tax deadlines were flagrantly ignored &lt;em&gt;we should have taken decisive action.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;There is a saying, “All style and no class.” One thing that irked me early on but that I couldn’t articulate until it was too late was the amount of effort Bumbler put into things other than doing the work we hired him to do. &lt;em&gt;Beware when you see a lot of style but no class.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I hope that these tips will help you avoid a year like our in 2014. It’s always hard work to find the right partner and it’s often tempting to take the easy road (after all, you’re paying money to create less work not &lt;em&gt;more&lt;/em&gt;, right?) but, in the end, a long term relationship that works will be worth the upfront cost of the search.&lt;/p&gt;
&lt;p&gt;Have you ever had a Bumbler that hurt your organization and learned something important from the experience? Feel free to help future readers by adding a comment.&lt;/p&gt;
</description></item><item><title>Routing in PHP - a Complete Benchmark</title><link>http://radify.io/blog/routing-in-php-a-complete-benchmark/</link><pubDate>Tue, 01 Mar 2016 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/routing-in-php-a-complete-benchmark/</guid><author></author><description>&lt;p&gt;Over the last 2 years, &lt;a href=&quot;https://github.com/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt; has become the de facto standard PHP routing solution. It&amp;#39;s now used in popular frameworks like &lt;a href=&quot;http://www.slimframework.com/&quot;&gt;Slim3&lt;/a&gt; and &lt;a href=&quot;https://lumen.laravel.com/&quot;&gt;lumen&lt;/a&gt;, and is the foundation of other advanced routing libraries.&lt;/p&gt;
&lt;p&gt;The basic idea behind &lt;a href=&quot;https://github.com/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt; is to combine routes regular expressions together in chunks to minimize &lt;code&gt;preg_match()&lt;/code&gt; calls. At a first glance &lt;a href=&quot;http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html&quot;&gt;nikis&amp;#39;s article &amp;quot;Fast request routing using regular expressions&amp;quot;&lt;/a&gt; makes a lots of sense. After a couple of hours of benchmarking, however, the regular expressions combination doesn&amp;#39;t seem to live up to its promises.&lt;/p&gt;
&lt;aside&gt;
    &lt;blockquote&gt;
        I&amp;#39;d recommend &lt;a href=&quot;http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html&quot;&gt;reading the article&lt;/a&gt; anyway since the regular expression part is very instructive!
    &lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;The story began when I was looking for a routing library. &lt;a href=&quot;https://github.com/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt; was obviously one of the front runners. However, FastRoute doesn&amp;#39;t support advanced features like reverse routing or subdomain routing out of the box, and despite the large numbers of routing libraries available, I didn&amp;#39;t really find the one which suited all my needs. So, I decided to &lt;a href=&quot;https://github.com/crysalead/router&quot;&gt;create a new routing library&lt;/a&gt; following nikic&amp;#39;s precepts.&lt;/p&gt;
&lt;p&gt;Once done, I decided to do some benchmarking to evaluate the final outcome - but the results weren&amp;#39;t as good I&amp;#39;d hoped. And that&amp;#39;s where things became interesting...&lt;/p&gt;
&lt;h2 id=&quot;establishing-a-benchmarking-process&quot;&gt;Establishing a Benchmarking Process&lt;/h2&gt;
&lt;p&gt;Having seen that my implementation did not perform as well as FastRoute, I decided to benchmark other routers. Benchmarks for &lt;a href=&quot;https://github.com/tyler-sommer/php-router-benchmark&quot;&gt;php-router-benchmark&lt;/a&gt; also seemed pretty poor compared to &lt;a href=&quot;https://github.cob/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt;. So, I started to investigate to understand why FastRoute was beating its competition.&lt;/p&gt;
&lt;p&gt;I quickly realized that the benchmarking script wasn&amp;#39;t really realistic. Moreover, it only benchmarks the actual routing step and not the route creation phase. So I decided to create &lt;a href=&quot;https://github.com/jails/php-router-benchmark&quot;&gt;a more elaborate benchmarking script&lt;/a&gt; to carry out my investigations.&lt;/p&gt;
&lt;p&gt;So to have a larger overview, I decided to benchmark the three different situations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the best case (i.e when a request matches the first route for all HTTP methods)&lt;/li&gt;
&lt;li&gt;the worst case (i.e when a request matches the last route for all HTTP methods)&lt;/li&gt;
&lt;li&gt;the average case (i.e the mean which is probably the most realistic test).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are, however, many different ways to configure routes. For example, in a controller/action strategy, each route generally matches a single HTTP method only. Conversely, in a REST approach, the same route&amp;#39;s pattern can handle several HTTP methods. So, to take advantage of all different routing implementation&amp;#39;s optimizations, I ran the benchmark using the following sets of routes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;in the first set all routes matches all HTTP methods.&lt;/li&gt;
&lt;li&gt;in the second set all routes match only a single HTTP method.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Taken separately, none of these sets are very realistic, but it should allow us to triangulate a real world scenario.&lt;/p&gt;
&lt;p&gt;I then picked up the following routing implementations to do the benchmarking:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/crysalead/router&quot;&gt;Router&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/UnionOfRAD/lithium&quot;&gt;Li3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/symfony/routing&quot;&gt;Symfony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/auraphp/Aura.Router&quot;&gt;Aura3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mrjgreen/phroute&quot;&gt;PHRoute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-results&quot;&gt;The Results&lt;/h2&gt;
&lt;p&gt;Instead of copy pasting &lt;a href=&quot;https://github.com/jails/php-router-benchmark&quot;&gt;the whole benchmark results&lt;/a&gt; in this article, I&amp;#39;ll just pick up the most interesting parts.&lt;/p&gt;
&lt;p&gt;So the first bar chart is obtained with 100 routes using the route set number 1:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/router_benchmarks1.png&quot; alt=&quot;router_benchmarks1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;While the second bar chart is obtained with 100 routes using the route set number 2:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/router_benchmarks2.png&quot; alt=&quot;router_benchmarks2.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, performance really depends on the route set. The different performances obtained by FastRoute can be explained by how routes are stored internally. FastRoute indexes routes by HTTP method names. So when a &lt;code&gt;PUT&lt;/code&gt; request is done, FastRoute only need to iterate over &lt;code&gt;PUT&lt;/code&gt; routes. Whilst this optimization works well when routes matches only a single HTTP Verb, it doesn&amp;#39;t help much when routes matches all HTTP Verbs. Furthermore, when FastRoute needs to process the whole routes collection the same way as Symfony does, Symfony reach better performances here.&lt;/p&gt;
&lt;h2 id=&quot;further-investigations&quot;&gt;Further Investigations&lt;/h2&gt;
&lt;p&gt;Many questions remains... How can a library using a classic routing strategy obtain better performances than FastRoute? Does FastRoute&amp;#39;s performance has something to do with its &amp;quot;combined regular expression&amp;quot; strategy?&lt;/p&gt;
&lt;p&gt;To answer these questions I decided to write a &lt;a href=&quot;https://github.com/jails/FastRoute/commit/114676515b636b637f6cac53945c2e04875b60eb&quot;&gt;classic routing strategy for FastRoute&lt;/a&gt;. The created classic strategy simply works through a route&amp;#39;s patterns one by one until one matches the request path. You can see the benchmark results below.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: below FastRoute* will stands for FastRoute using a classic routing strategy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, to focus on the combined regular expression optimization, the results below only benchmark the routing step (i.e we are simply ignoring routes creation here).&lt;/p&gt;
&lt;p&gt;Results obtained with the route set number 1:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/fastroute1.png&quot; alt=&quot;fastroute1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Results obtained with the route set number 2:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/fastroute2.png&quot; alt=&quot;fastroute2.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fewer calls to &lt;code&gt;preg_match()&lt;/code&gt; on combined regular expressions clearly shows better performance.&lt;/p&gt;
&lt;p&gt;Routing in PHP is a process which is executed once per request and the routes creation can&amp;#39;t be ignored any more, so below you can find benchmark results, which also include the routes creation step.&lt;/p&gt;
&lt;p&gt;Results obtained with the route set number 1:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/fastroute3.png&quot; alt=&quot;fastroute3.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;Results obtained with the route set number 2:
&lt;img src=&quot;/blog/routing-in-php-a-complete-benchmark/fastroute4.png&quot; alt=&quot;fastroute4.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;So in this last benchmark results, the conclusion is pretty unambiguous: the time saved by using combined regular expression doesn&amp;#39;t really compensate for the extra complexity added by all intermediate introduced structures to make the approach faster.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The fact that FastRoute&amp;#39;s strategy doesn&amp;#39;t bring any additional performance to a classic routing strategy has at least one positive point: route instances can be responsible for their own matching logic, which simplifies greatly the codebase.&lt;/p&gt;
&lt;p&gt;Trying to increase routing library performance is fine, but it&amp;#39;s not the only way to solve a routing performance issue. There are, for example, libraries like &lt;a href=&quot;https://github.com/nateabele/li3_resources&quot;&gt;li3_resources&lt;/a&gt;, which minimize route creation by a simple design abstraction. Indeed, in li3_resources, HTTP methods management has been delegated up to the Resource instance, so instead of creating one route per supported HTTP method, only one route accepting all HTTP methods is created and then it&amp;#39;s up to the Resource instance to respond or not to it. This kind of separation of responsibility can also be used with a classic controller/action strategy. A single &lt;code&gt;&amp;#39;/{controller}/{action}[/{args}]&amp;#39;&lt;/code&gt; pattern coupled with a &lt;code&gt;class_exists()&lt;/code&gt; and a &lt;code&gt;method_exists()&lt;/code&gt; can supports an infinite number of requests by defining only one route.&lt;/p&gt;
&lt;p&gt;So, there are a lot of possibilities to explore in routing design - it seems there is room for improvement in clarity, expressiveness and performance.&lt;/p&gt;
</description></item><item><title>On Boundaries</title><link>http://radify.io/blog/on-boundaries/</link><pubDate>Thu, 19 Nov 2015 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/on-boundaries/</guid><author></author><description>&lt;h1 id=&quot;on-boundaries&quot;&gt;On Boundaries&lt;/h1&gt;
&lt;p&gt;Over the past few years, I&amp;#39;ve been on an exploration of how software, and the process of creating &amp;amp; maintaining it, has become so complicated, difficult, and expensive. One theme I&amp;#39;m continually led back
to is the concept of boundaries.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;The whole monolith vs. microservice thing is just a red herring for the fact that we suck at managing boundaries in any formal/explicit way.&lt;/p&gt;&amp;mdash; Nate Abele (@nateabele) &lt;a href=&quot;https://twitter.com/nateabele/status/608716970582773761&quot;&gt;June 10, 2015&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;Boundaries are omnipresent in all aspects of the software industry, yet rarely acknowledged or thought about as a first-class concept.&lt;/p&gt;
&lt;p&gt;Whether abstract or concrete, having a unified mental model for reasoning about boundaries should yield some interesting insights. Here are a few examples from across the spectrum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Queries &amp;amp; cursors&lt;/strong&gt; are boundaries between databases and applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP messages&lt;/strong&gt; are boundaries between apps and browsers, or apps and other apps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queues&lt;/strong&gt; are boundaries between apps and expensive jobs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time&lt;/strong&gt; is a boundary between different states in an execution context, (object-oriented) application, a database, a filesystem, the universe, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apps&lt;/strong&gt; are boundaries between me and data or functionality that I care about&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Installation&lt;/strong&gt; is a boundary between me and an app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Programming languages&lt;/strong&gt; that I don&amp;#39;t know (or that haven&amp;#39;t been invented yet) are the boundaries between me and the ideal expression of some problem domain that I face&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wireframes&lt;/strong&gt; are boundaries for communicating about user interfaces between designers, project stakeholders, and developers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML &amp;amp; CSS&lt;/strong&gt; are boundaries between wireframes and real user interfaces&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt; is a boundary between ideas and computers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As the tech community, these are a few of the boundaries that we face today. Some of them are useful. For the ones that aren&amp;#39;t, our future is on the other side of them.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;The next wave of innovation in software development is going to come about by treating time and boundaries as first-class things.&lt;/p&gt;&amp;mdash; Nate Abele (@nateabele) &lt;a href=&quot;https://twitter.com/nateabele/status/590931424791941120&quot;&gt;April 22, 2015&lt;/a&gt;&lt;/blockquote&gt;
</description></item><item><title>Comic book continuity and Git rebase</title><link>http://radify.io/blog/comic-continuity-and-git-rebase/</link><pubDate>Mon, 19 Oct 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/comic-continuity-and-git-rebase/</guid><author></author><description>&lt;p&gt;When helping companies improve their development practises, one common sticking point for the &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;pull request workflow&lt;/a&gt; that we often recommend is the need to occasionally &lt;code&gt;git rebase&lt;/code&gt; feature branches - it can be hard to understand, and a lot of people are initially pretty scared of it.&lt;/p&gt;
&lt;p&gt;In this article, I’m not going to give any code examples - there are thousands of articles that do that. Instead, I am going to illustrate the concept of git rebase using the world of comic books.&lt;/p&gt;
&lt;h2 id=&quot;retconning-in-comic-books&quot;&gt;Retconning in comic books&lt;/h2&gt;
&lt;p&gt;Comic books often run for years. Top titles like Batman or Spiderman have been going for decades and exist in an enormous shared universe, making continuity difficult to manage. Periodically, a character’s origin story will be retold, and it might be different, which can change the canonical history of the storyline. This is known as retconning (retroactive continuity) in the industry.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;A classic example of retconning this is that in early Batman he used a gun, which was later retconned out in favour of the vigilante refusing to kill&lt;/blockquote&gt;&lt;/aside&gt;

&lt;p&gt;Just like comic books, Git allows you to “rewrite history” to suit your application as it is now - you are not bound to the past. This also allows you to work on different features in parallel - just like two writers both producing separate stories at the same time (which happens all the time with popular characters like Wolverine).&lt;/p&gt;
&lt;p&gt;We will work through an example here and explain Git in terms of comic books!&lt;/p&gt;
&lt;h2 id=&quot;establishing-canon&quot;&gt;Establishing canon&lt;/h2&gt;
&lt;p&gt;An artist, Alex, creates a character in a story that we will refer to as A1:&lt;/p&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip1a.png&quot; alt=&quot;Ordinary high school student Ralph Whiskers is getting bullied in high school&quot; title=&quot;Ordinary high school student Ralph Whiskers is getting bullied in high school&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip1b.png&quot; alt=&quot;Running into the lab to escape, he knocks over chemicals!&quot; title=&quot;Running into the lab to escape, he knocks over chemicals!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip1c.png&quot; alt=&quot;The chemicals mix, Ralph inhales, and his skin turns to living stone. He vows to fight crime as Rock Savage&quot; title=&quot;The chemicals mix, Ralph inhales, and his skin turns to living stone. He vows to fight crime as Rock Savage&quot;&gt;
&lt;/div&gt;

&lt;p&gt;This comic book (although short!) is a huge success, selling thousands of copies. This is like our first few commits to a Git repository - they establish something useful that other people can develop on top of.&lt;/p&gt;
&lt;h2 id=&quot;another-artist-gets-involved&quot;&gt;Another artist gets involved&lt;/h2&gt;
&lt;p&gt;At this point, Alex starts writing the next story in the Rock Savage adventures (we will call this A2). The publishing company smells money, and hires another writer, Bryce, to write another story (B1) in parallel.&lt;/p&gt;
&lt;p&gt;At this point, we can think of the situation like feature branches in git - both Alex and Bryce are working in parallel from Alex’s original work:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/branches-B1-and-A2.png&quot; alt=&quot;branches-B1-and-A2.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;They come up with a story each.&lt;/p&gt;
&lt;h3 id=&quot;alex-s-second-story-a2-&quot;&gt;Alex&amp;#39;s second story (A2):&lt;/h3&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip2a.png&quot; alt=&quot;Rock Savage spies a mugging!&quot; title=&quot;Rock Savage spies a mugging!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip2b.png&quot; alt=&quot;He takes action!&quot; title=&quot;He takes action!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip2c.png&quot; alt=&quot;Rock Savage captures the mugger&quot; title=&quot;Rock Savage captures the mugger&quot;&gt;
&lt;/div&gt;

&lt;h3 id=&quot;bryce-s-first-story-b1-&quot;&gt;Bryce&amp;#39;s first story (B1):&lt;/h3&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip3a.png&quot; alt=&quot;An evil scientist is building a laser beam!&quot; title=&quot;An evil scientist is building a laser beam!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip3b.png&quot; alt=&quot;Rock Savage SMASHES through the wall!&quot; title=&quot;Rock Savage SMASHES through the wall!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip3c.png&quot; alt=&quot;...Capturing the evil scientist&quot; title=&quot;...Capturing the evil scientist&quot;&gt;
&lt;/div&gt;

&lt;p&gt;Alex and Bryce both send their comics off to the publishing companies for approval. This is like &lt;strong&gt;raising a pull request&lt;/strong&gt; via Github or Bitbucket.&lt;/p&gt;
&lt;p&gt;There are no conflicts, and the publishing company decide to publish Bryce’s story first. This is like &lt;strong&gt;merging a pull request&lt;/strong&gt; via Github or Bitbucket. Therefore the continuity looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/B1-merged.png&quot; alt=&quot;B1-merged.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;The publishing company then accepts and publishes story A2 (again, this is like &lt;strong&gt;merging a pull request&lt;/strong&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/A2-merged.png&quot; alt=&quot;A2-merged.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;So far, so good! There are no conflicts with these stories, the continuity is in harmony. If this was git, we have three &lt;strong&gt;commits&lt;/strong&gt; (stories) in a row in our canonical continuity (or &lt;strong&gt;master branch&lt;/strong&gt;).&lt;/p&gt;
&lt;h2 id=&quot;mixing-it-up&quot;&gt;Mixing it up&lt;/h2&gt;
&lt;p&gt;Alex and Bryce get started on new stories (like creating &lt;strong&gt;feature branches&lt;/strong&gt; in Git) based on A2. We will call these stories A3 and B2:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/branches-A3-and-B2-created.png&quot; alt=&quot;branches-A3-and-B2-created&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;alex-s-third-story-a3-&quot;&gt;Alex&amp;#39;s third story (A3):&lt;/h3&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip4a.png&quot; alt=&quot;Rock Savage is saving a school bus froma  werewolf!&quot; title=&quot;Rock Savage is saving a school bus from werewolf&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip4b.png&quot; alt=&quot;He draws back his hand to strike!&quot; title=&quot;He draws back his hand to strike!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip4c.png&quot; alt=&quot;No Rock Savage does not kill&quot; title=&quot;No, Rock Savage does not kill&quot;&gt;
&lt;/div&gt;

&lt;h3 id=&quot;bryce-s-second-story-b2-&quot;&gt;Bryce&amp;#39;s second story (B2):&lt;/h3&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5a.png&quot; alt=&quot;Rock Savage interrupts the kidnapping of the mayor&amp;#39;s daughter&quot; title=&quot;Rock Savage interrupts the kidnapping of the mayor&amp;#39;s daughter&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5b.png&quot; alt=&quot;The kidnapper shoots Rock Savage, but the bullets bounce off!&quot; title=&quot;The kidnapper shoots Rock Savage, but the bullets bounce off!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5c_1.png&quot; alt=&quot;Rock Savage kills the kidnapper!&quot; title=&quot;Rock Savage kills the kidnapper!&quot;&gt;
&lt;/div&gt;

&lt;p&gt;Now, these stories are in conflict. In Bryce’s continuity, Rock Savage is willing to kill. In Alex’s, he is not. Whilst Bryce is still tidying up story B2, the publishing company publishes A3:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/A3-merged.png&quot; alt=&quot;A3-merged&quot;&gt;&lt;/p&gt;
&lt;p&gt;Alex’s work is considered canonical - story A3 has been published. Bryce’s story B2 is now in conflict with the canon. The publishing company looks at Bryce’s draft and realises that it does not fit the continuity. Bryce needs to take into account the new things that Alex has revealed about the Rock Savage character. Therefore, Bryce fetches an updated copy of the continuity by getting A3. This is like doing &lt;strong&gt;git pull&lt;/strong&gt; on the &lt;strong&gt;master branch&lt;/strong&gt;, so that you have the canonical story locally.&lt;/p&gt;
&lt;p&gt;Then, having got the updated continuity, Bryce effectively &lt;strong&gt;rebases&lt;/strong&gt; off A3:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/B2-rebased.png&quot; alt=&quot;B2-rebased&quot;&gt;&lt;/p&gt;
&lt;p&gt;Instead of being &lt;strong&gt;based on&lt;/strong&gt; the story A2, Bryce’s story (or &lt;strong&gt;feature branch&lt;/strong&gt;, in Git parlance) is now &lt;strong&gt;based on&lt;/strong&gt; the story A3. This is what &lt;strong&gt;rebasing&lt;/strong&gt; is - changing what a branch is based on.&lt;/p&gt;
&lt;p&gt;Bryce now has the extra facts to hand and can modify story B2 so that it fits the continuity. This is analogous to &lt;strong&gt;conflict resolution&lt;/strong&gt; in git.&lt;/p&gt;
&lt;p&gt;Bryce then resolves the conflict by making the panel make sense within the updated continuity:&lt;/p&gt;
&lt;h3 id=&quot;bryce-s-second-story-b2-retconned-rebased-from-a3-&quot;&gt;Bryce&amp;#39;s second story (B2), retconned (rebased) from A3:&lt;/h3&gt;
&lt;div class=&quot;comic-strip&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5a.png&quot; alt=&quot;Rock Savage interrupts the kidnapping of the mayor&amp;#39;s daughter&quot; title=&quot;Rock Savage interrupts the kidnapping of the mayor&amp;#39;s daughter&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5b.png&quot; alt=&quot;The kidnapper shoots Rock Savage, but the bullets bounce off!&quot; title=&quot;The kidnapper shoots Rock Savage, but the bullets bounce off!&quot;&gt;
&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/strip5c_2.png&quot; alt=&quot;Rock Savage captures the kidnapper!&quot; title=&quot;Rock Savage captures the kidnapper!&quot;&gt;
&lt;/div&gt;

&lt;p&gt;At this point, Bryce then sends off the updated draft of story B2 to the publishing company. This is like &lt;strong&gt;updating a pull request&lt;/strong&gt; by doing a &lt;strong&gt;push&lt;/strong&gt; to your &lt;strong&gt;feature branch&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This time, the publishing company is happy with Bryce’s story, and publishes it. Again, this is analogous to &lt;strong&gt;merging a pull request&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/comic-continuity-and-git-rebase/final-resolved-continuity.png&quot; alt=&quot;final-resolved-continuity&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;lookup-table&quot;&gt;Lookup table&lt;/h2&gt;
&lt;p&gt;Here is our handy print-out-and-keep guide to Git concepts for a pull request workflow in terms of comic books continuities!&lt;/p&gt;
&lt;dl class=&quot;cut-out-and-keep&quot;&gt;
    &lt;dt&gt;Repository&lt;/dt&gt;&lt;dd&gt;Comic book series&lt;/dd&gt;
    &lt;dt&gt;Commit&lt;/dt&gt;&lt;dd&gt;Issue of the comic&lt;/dd&gt;
    &lt;dt&gt;Raise pull request&lt;/dt&gt;&lt;dd&gt;Send first draft to publisher&lt;/dd&gt;
    &lt;dt&gt;Master branch&lt;/dt&gt;&lt;dd&gt;Canon continuity&lt;/dd&gt;
    &lt;dt&gt;Feature branch&lt;/dt&gt;&lt;dd&gt;Draft being worked on by writer/artist&lt;/dd&gt;
    &lt;dt&gt;Rebase&lt;/dt&gt;&lt;dd&gt;Updating continuity&lt;/dd&gt;
    &lt;dt&gt;Conflict resolution&lt;/dt&gt;&lt;dd&gt;Changing a draft based on an updated continuity&lt;/dd&gt;
    &lt;dt&gt;Update pull request&lt;/dt&gt;&lt;dd&gt;Send a new draft to the publisher&lt;/dd&gt;
    &lt;dt&gt;Merge pull request&lt;/dt&gt;&lt;dd&gt;Publish an issue of the comic&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&quot;how-true-is-this-&quot;&gt;How true is this?&lt;/h2&gt;
&lt;p&gt;Of course, both comic books and Git can have far more complex histories than we have hinted at here. Furthermore, the metaphor of comic book continuity is not perfect (see &lt;a href=&quot;http://www.joelonsoftware.com/articles/LeakyAbstractions.html&quot;&gt;Spolsky’s law of leaky abstractions&lt;/a&gt;). Hopefully, though, by reading this post you feel confident that you understand what Git rebase is for, how it is used, and why it is such a crucial tool when you are working on different things in parallel.&lt;/p&gt;
</description></item><item><title>End-to-End Functional Testing With Kahlan</title><link>http://radify.io/blog/end-to-end-functional-testing-with-kahan/</link><pubDate>Tue, 13 Oct 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/end-to-end-functional-testing-with-kahan/</guid><author></author><description>&lt;p&gt;End-to-End Functional Testing is the process of testing interactions between multiple modules of an application from a &amp;quot;start to finish&amp;quot; perspective.&lt;/p&gt;
&lt;p&gt;Since End-to-End tests represent real-world scenarios, the DSL (Domain-Specific Language) used to describe such scenarios needs to be as expressive as possible. It is therefore important to use tooling that is flexible enough to allow the creation of semantically meaningful tests.&lt;/p&gt;
&lt;p&gt;In this article, we are going to build a basic DSL (similar to &lt;a href=&quot;https://github.com/jnicklas/capybara&quot;&gt;Capybara&lt;/a&gt;) on top of &lt;a href=&quot;https://github.com/crysalead/kahlan&quot;&gt;Kahlan&lt;/a&gt; and &lt;a href=&quot;https://github.com/minkphp/Mink&quot;&gt;Mink&lt;/a&gt; to perform End-to-End tests. Here is the final result:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;testing&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;spec&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;suite&lt;/span&gt;;

describe(&lt;span class=&quot;string&quot;&gt;&quot;Google&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{

    it(&lt;span class=&quot;string&quot;&gt;&quot;displays the Google logo&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{

        browser()-&amp;gt;visit(&lt;span class=&quot;string&quot;&gt;'http://www.google.fr'&lt;/span&gt;);
        expect(element(&lt;span class=&quot;string&quot;&gt;'#hplogo'&lt;/span&gt;)-&amp;gt;getAttribute(&lt;span class=&quot;string&quot;&gt;'title'&lt;/span&gt;))-&amp;gt;toBe(&lt;span class=&quot;string&quot;&gt;'Google'&lt;/span&gt;);

    });

    it(&lt;span class=&quot;string&quot;&gt;&quot;can search for and find Kahlan&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{

        browser()-&amp;gt;visit(&lt;span class=&quot;string&quot;&gt;'http://www.google.fr'&lt;/span&gt;);
        page()-&amp;gt;fillField(&lt;span class=&quot;string&quot;&gt;'q'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'Unit/BDD PHP Test Framework for Freedom, Truth, and Justice'&lt;/span&gt;);
        page()-&amp;gt;pressButton(&lt;span class=&quot;string&quot;&gt;'btnG'&lt;/span&gt;);
        wait(page())-&amp;gt;toContain(&lt;span class=&quot;string&quot;&gt;'Kahlan'&lt;/span&gt;);

    });

}, &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are familiar with &lt;a href=&quot;http://jasmine.github.io/&quot;&gt;Jasmine&lt;/a&gt;-like testing frameworks, you should have been able to understand the code above. Let&amp;#39;s dig deeper to see how things as been wired up under the hood.&lt;/p&gt;
&lt;p&gt;Note: you can find the &lt;a href=&quot;https://github.com/jails/testing&quot;&gt;code used in this article at github.com/jails/testing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;configuring-kahlan-config-php-&quot;&gt;Configuring &lt;code&gt;kahlan-config.php&lt;/code&gt;&lt;/h2&gt;
&lt;h3 id=&quot;setting-up-the-webdriver-server&quot;&gt;Setting up the WebDriver server&lt;/h3&gt;
&lt;p&gt;To interact with browsers, we are going to need a WebDriver server like &lt;a href=&quot;http://www.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; (or similar). For this part, we shall use the &lt;a href=&quot;https://github.com/peridot-php/webdriver-manager&quot;&gt;WebDriver Manager&lt;/a&gt; library. This library allows you to keep Selenium server binaries up to date and also provides an API for easily starting a Selenium server. To use it inside Kahlan, we are going to configure &lt;code&gt;kahlan-config.php&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Peridot&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;WebDriverManager&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Manager&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;box&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Box&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;code&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Code&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;code&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;TimeoutException&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;filter&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Filter&lt;/span&gt;;

&lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt; = box(&lt;span class=&quot;string&quot;&gt;'spec'&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Box());

&lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt;-&amp;gt;service(&lt;span class=&quot;string&quot;&gt;'manager'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$manager&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Manager();
    &lt;span class=&quot;variable&quot;&gt;$manager&lt;/span&gt;-&amp;gt;update();
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$manager&lt;/span&gt;-&amp;gt;startInBackground();
});

Filter::register(&lt;span class=&quot;string&quot;&gt;'run.webdriver'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$process&lt;/span&gt; = box(&lt;span class=&quot;string&quot;&gt;'spec'&lt;/span&gt;)-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'manager'&lt;/span&gt;);
    &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt; {
        &lt;span class=&quot;variable&quot;&gt;$fp&lt;/span&gt; = Code::spin(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; @fsockopen(&lt;span class=&quot;string&quot;&gt;'localhost'&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;4444&lt;/span&gt;);
        }, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;);
        fclose(&lt;span class=&quot;variable&quot;&gt;$fp&lt;/span&gt;);
    } &lt;span class=&quot;keyword&quot;&gt;catch&lt;/span&gt; (TimeoutException &lt;span class=&quot;variable&quot;&gt;$e&lt;/span&gt;) {
        &lt;span class=&quot;keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;Unable to run the WebDriver binary, abording.\n&quot;&lt;/span&gt;;
        &lt;span class=&quot;variable&quot;&gt;$process&lt;/span&gt;-&amp;gt;close();
        &lt;span class=&quot;keyword&quot;&gt;exit&lt;/span&gt;(-&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);
    }
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;-&amp;gt;next();
});


Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'run'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'run.webdriver'&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: In the code above, &lt;code&gt;box()&lt;/code&gt; is the rudimentary &lt;a href=&quot;http://www.martinfowler.com/articles/injection.html&quot;&gt;Dependency Injection Container&lt;/a&gt; included by default in Kahlan, but you can use your own implementation if you prefer.&lt;/p&gt;
&lt;p&gt;The first step in the script above was to create the &lt;code&gt;&amp;#39;manager&amp;#39;&lt;/code&gt; service, which runs the WebDriver server and returns the created process when invoked.&lt;/p&gt;
&lt;p&gt;The second part of the script consists of configuring the &lt;code&gt;&amp;#39;run.webdriver&amp;#39;&lt;/code&gt; closure to run just before the &lt;code&gt;&amp;#39;run&amp;#39;&lt;/code&gt; step (i.e. before the test specs run).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Code::spin()&lt;/code&gt; is a simple utility function which loops over a closure until a timeout is reached or until the executed closure returns a non-empty value (another approach to this could be using the &lt;code&gt;sleep(x)&lt;/code&gt; pattern).&lt;/p&gt;
&lt;p&gt;Note: In this example we are going to use the &lt;a href=&quot;http://www.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; driver, but since Mink supports a lot of different drivers, pick the driver that suits you best.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-the-mink-instance&quot;&gt;Setting up the Mink instance&lt;/h3&gt;
&lt;p&gt;In order to use Firefox to runs our suite of specs, we need to also setup Mink accordingly using the &lt;a href=&quot;https://github.com/minkphp/MinkSelenium2Driver&quot;&gt;MinkSelenium2Driver&lt;/a&gt; driver.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Behat&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Mink&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Driver&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Selenium2Driver&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Behat&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Mink&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Mink&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Behat&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Mink&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Session&lt;/span&gt;;

&lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt;-&amp;gt;service(&lt;span class=&quot;string&quot;&gt;'mink'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$selenium&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Selenium2Driver(&lt;span class=&quot;string&quot;&gt;'firefox'&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;null&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'http://localhost:4444/wd/hub'&lt;/span&gt;);
    &lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Mink([&lt;span class=&quot;string&quot;&gt;'firefox'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Session(&lt;span class=&quot;variable&quot;&gt;$selenium&lt;/span&gt;)]);
    &lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt;-&amp;gt;setDefaultSessionName(&lt;span class=&quot;string&quot;&gt;'firefox'&lt;/span&gt;);
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt;;
});

Filter::register(&lt;span class=&quot;string&quot;&gt;'register.globals'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$root&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;suite();
    &lt;span class=&quot;variable&quot;&gt;$root&lt;/span&gt;-&amp;gt;mink = &lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt; = box(&lt;span class=&quot;string&quot;&gt;'spec'&lt;/span&gt;)-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'mink'&lt;/span&gt;);

    &lt;span class=&quot;variable&quot;&gt;$root&lt;/span&gt;-&amp;gt;afterEach(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
        &lt;span class=&quot;variable&quot;&gt;$mink&lt;/span&gt;-&amp;gt;resetSessions();
    });
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;-&amp;gt;next();
});

Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'run'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'register.globals'&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the script above, the &lt;code&gt;&amp;#39;register.globals&amp;#39;&lt;/code&gt; filter has been created to inject the &lt;code&gt;mink&lt;/code&gt; variable to all scopes and make it available in all specs. Similarly, the closure passed to &lt;code&gt;afterEach()&lt;/code&gt; will be executed after each specs in the suite completes its run. This will help to keep specs isolated, without having to explicitly tear down state in each spec.&lt;/p&gt;
&lt;h3 id=&quot;registering-a-custom-matcher&quot;&gt;Registering a custom matcher&lt;/h3&gt;
&lt;p&gt;In Kahlan it&amp;#39;s possible to register a matcher to be used only for a specific class name. This feature can be used in our example to match with Mink&amp;#39;s &lt;code&gt;Behat\Mink\Element\Element&lt;/code&gt; instances. Note that all of these instances have a &lt;code&gt;getText()&lt;/code&gt; method, which returns the textual representation of an element. So, to avoid having to deal with &lt;code&gt;getText()&lt;/code&gt; everywhere, and in the interests of a consistent API, we can delegate these checks to a specific matcher:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;kahlan&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Matcher&lt;/span&gt;;

Filter::register(&lt;span class=&quot;string&quot;&gt;'register.matchers'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    Matcher::register(&lt;span class=&quot;string&quot;&gt;'toContain'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'testing\spec\matcher\ToContain'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'Behat\Mink\Element\Element'&lt;/span&gt;);
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;-&amp;gt;next();
});

Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'run'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'register.matchers'&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can get the full &lt;a href=&quot;https://github.com/jails/testing/blob/master/spec/matcher/ToContain.php&quot;&gt;matcher code here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;post-suite-cleanup&quot;&gt;Post-suite cleanup&lt;/h3&gt;
&lt;p&gt;When the entire test suite has completed, the following script will clean things up properly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;Filter::register(&lt;span class=&quot;string&quot;&gt;'cleanup'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt; = box(&lt;span class=&quot;string&quot;&gt;'spec'&lt;/span&gt;);
    &lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt;-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'mink'&lt;/span&gt;)-&amp;gt;stopSessions();
    &lt;span class=&quot;variable&quot;&gt;$box&lt;/span&gt;-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'manager'&lt;/span&gt;)-&amp;gt;close();
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;-&amp;gt;next();
});

Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'stop'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'cleanup'&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;setting-up-the-dsl&quot;&gt;Setting up the DSL&lt;/h2&gt;
&lt;p&gt;In order to write meaningful specs, we would also like to create a DSL similar to the &lt;a href=&quot;https://github.com/jnicklas/capybara&quot;&gt;Capybara&lt;/a&gt; one. To this end, we are going to write some helper functions to interact with the browser, the page and elements à la Capybara:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$session&lt;/span&gt; = null)&lt;/span&gt;
&lt;/span&gt;{
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Suite::current()-&amp;gt;mink-&amp;gt;getSession(&lt;span class=&quot;variable&quot;&gt;$session&lt;/span&gt;);
}

&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$session&lt;/span&gt; = null)&lt;/span&gt;
&lt;/span&gt;{
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; browser(&lt;span class=&quot;variable&quot;&gt;$session&lt;/span&gt;)-&amp;gt;getPage();
}

&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$selector&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;'body'&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$parent&lt;/span&gt; = null)&lt;/span&gt;
&lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$parent&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$parent&lt;/span&gt; ?: page();
    &lt;span class=&quot;variable&quot;&gt;$element&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$parent&lt;/span&gt;-&amp;gt;find(&lt;span class=&quot;string&quot;&gt;'css'&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$selector&lt;/span&gt;);
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$element&lt;/span&gt; ?: &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; ElementNotFound(&lt;span class=&quot;variable&quot;&gt;$selector&lt;/span&gt;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These helper functions are not exhaustive, and you can of course add whatever functions you need to the DSL.&lt;/p&gt;
&lt;h3 id=&quot;dealing-with-asynchronous-expectations&quot;&gt;Dealing with asynchronous expectations&lt;/h3&gt;
&lt;p&gt;When interacting with a browser, elements appear or disappear from a page asynchronously. To perform asynchronous tests, you can use the kahlan &lt;code&gt;waitsFor()&lt;/code&gt; statement, which runs a closure until some condition passes or until a timeout is reached.&lt;/p&gt;
&lt;p&gt;We are going to use this &lt;code&gt;waitsFor()&lt;/code&gt; statement to create the following additional helper function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$actual&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$timeout&lt;/span&gt; = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;/span&gt;{
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; waitsFor(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$actual&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$actual&lt;/span&gt;;
    }, &lt;span class=&quot;variable&quot;&gt;$timeout&lt;/span&gt;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last step is then to include the helper in the &lt;code&gt;kahlan-config.php&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;&quot;/spec/api/helpers.php&quot;&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you are done! You should now be able to configure your own environment to write End-to-End tests which fit your requirements.&lt;/p&gt;
&lt;h1 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h1&gt;
&lt;p&gt;End to End tests are a vital part of any testing strategy. With a little configuration, Kahlan allows you to write your End to End, Unit and &lt;a href=&quot;http://radify.io/blog/characterisation-tests/&quot;&gt;Characterisation tests&lt;/a&gt; within a consistent testing environment.&lt;/p&gt;
</description></item><item><title>Characterisation Tests for Legacy Projects</title><link>http://radify.io/blog/characterisation-tests/</link><pubDate>Tue, 22 Sep 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/characterisation-tests/</guid><author></author><description>&lt;p&gt;A legacy project is any project that you or your team did not create. It might have been left to you by another organisation, or it could have been brought in as part of a competitor buy-out.&lt;/p&gt;
&lt;p&gt;Many legacy projects are still in use because they are robust, they do the job, and they are mature. There are, however, many common challenges that come with maintaining or developing on a legacy system. We all have to deal with these challenges at least some of the time.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;I would not be surprised if the majority of software developers today are working on code that they did not originally write.&lt;br&gt;- Alberto Savoia&lt;/blockquote&gt;&lt;/aside&gt;


&lt;h2 id=&quot;risks-of-legacy-projects&quot;&gt;Risks of Legacy Projects&lt;/h2&gt;
&lt;p&gt;The risks in legacy projects include:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Poor comprehension.&lt;/strong&gt; When we take on a project, we take on its conceptual model and programming paradigm, which may be alien to us. Even if it follows patterns we are familiar with, there will be design decisions and technical debt of which we are unaware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stale dependencies.&lt;/strong&gt; Many legacy projects use deprecated frameworks or languages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lack of tests.&lt;/strong&gt; The most common problem with legacy systems is lack of tests.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;Legacy code is code without tests.&lt;br&gt;Code without tests is bad code.&lt;br&gt;- Michael Feathers&lt;/blockquote&gt;&lt;/aside&gt;

&lt;p&gt;Most legacy systems I have worked with have exhibited these risks. In the worst case, I had to deal with code that was over a decade old with no documentation, had no tests, was built in an  archaic language, and did not even have a build script to compile it!&lt;/p&gt;
&lt;p&gt;Thankfully, there are strategies for dealing with these kinds of projects. This article will focus on one of those strategies: using characterisation tests.&lt;/p&gt;
&lt;p&gt;First, though, let us take a moment to consider the nature of change in software so as to have context for our objectives.&lt;/p&gt;
&lt;h2 id=&quot;the-nature-of-software-change&quot;&gt;The Nature of Software Change&lt;/h2&gt;
&lt;p&gt;There are two sources of change to software: intended and unintended change.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/characterisation-tests/change-sources.png&quot; alt=&quot;change-sources.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intended change&lt;/strong&gt; is deliberate. It is intentional, such as a bug fix or new feature that did not break anything. &lt;strong&gt;Unintended change&lt;/strong&gt; is mistakes, misunderstandings and side effects.&lt;/p&gt;
&lt;p&gt;To avoid unintended, haphazard change, we need to manage change - we can’t make a set of alterations to an unknown product and expect it to work. As software professionals, we have a responsibility to make sure that all change to the system is &lt;em&gt;intended&lt;/em&gt; change.&lt;/p&gt;
&lt;h3 id=&quot;characteristics-of-change&quot;&gt;Characteristics of Change&lt;/h3&gt;
&lt;p&gt;Here we identify characteristics that change should and should not have:&lt;/p&gt;
&lt;h4 id=&quot;should-be&quot;&gt;Should be&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intentional&lt;/strong&gt; - deliberate change that has the effect that it is supposed to.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atomic&lt;/strong&gt; - discrete alterations which affect one thing only. Has no side effects. See our blog post &amp;quot;&lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;perfect pull requests&lt;/a&gt;&amp;quot; for related information.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;should-not-be&quot;&gt;Should not be&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Haphazard&lt;/strong&gt; - poorly thought out, ad-hoc, and unstructured.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Side effect-y&lt;/strong&gt; - change that does not affect only one part of the system, but has unintended side-effects elsewhere in the product.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By asserting that change matches our desired criteria, we begin to stabilise our understanding of our legacy project. One mechanism to help us to achieve this is characterisation tests.&lt;/p&gt;
&lt;h2 id=&quot;characterisation-tests&quot;&gt;Characterisation Tests&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.amazon.co.uk/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052&quot;&gt;Michael Feathers&lt;/a&gt; defines characterisation tests as &lt;em&gt;&amp;quot;tests that characterize the actual behavior of a piece of code&amp;quot;&lt;/em&gt;. A characterisation test is likely to use similar or even the same tools as unit tests. They are similar to unit tests, except that they are only the &lt;em&gt;what&lt;/em&gt;, not the &lt;em&gt;why&lt;/em&gt; - they snapshot what a piece of code does, but do not necessarily represent any kind of understanding of the system under test.&lt;/p&gt;
&lt;p&gt;They are used for detecting unintended change:&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;Characterization tests are, essentially, change detectors. It is up to the person analyzing the results to determine if the detected change was expected and/or desirable, or unexpected and/or undesirable.&lt;br&gt;- &lt;a href=&quot;https://books.google.co.uk/books?id=o2mFgGjktncC&quot;&gt;Software Testing, Wikipedians&lt;/a&gt;&lt;/blockquote&gt;&lt;/aside&gt;

&lt;h3 id=&quot;producing-characterisation-tests&quot;&gt;Producing Characterisation Tests&lt;/h3&gt;
&lt;p&gt;There are two ways to produce a characterisation test. Firstly, they can be produced manually using a unit test tool. I recommend choosing something that allows you to &lt;a href=&quot;http://radify.io/blog/faster-php-code-coverage/&quot;&gt;mock and stub easily, such as Kahlan&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Secondly, characterisation tests can be generated. &lt;a href=&quot;http://follesoe.github.io/BlackBoxRecorder/&quot;&gt;BlackBoxRecorder in .Net&lt;/a&gt; and &lt;a href=&quot;https://github.com/nomuda/jackbox&quot;&gt;JackBoxRecorder for Java&lt;/a&gt; allow a sort of &amp;quot;record and playback&amp;quot; approach.&lt;/p&gt;
&lt;h3 id=&quot;example-characterisation-test&quot;&gt;Example Characterisation Test&lt;/h3&gt;
&lt;p&gt;Here is a very simple snippet of code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;bar&quot;&lt;/span&gt;; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To characterise this function, we can write a test such as the following (which uses the &lt;a href=&quot;http://kahlan.readthedocs.org/&quot;&gt;excellent PHP testing tool, Kahlan&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;describe(&lt;span class=&quot;string&quot;&gt;&quot;foo()&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
  it(&lt;span class=&quot;string&quot;&gt;&quot;returns bar&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
    expect(foo())-&amp;gt;toEqual(&lt;span class=&quot;string&quot;&gt;&quot;bar&quot;&lt;/span&gt;);
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if &lt;code&gt;foo()&lt;/code&gt; changes in any way, we will know about it (as all characterisation tests should run on commit, as per our article &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;4 Principles of DevOps&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;characterisation-test-workflow&quot;&gt;Characterisation Test Workflow&lt;/h2&gt;
&lt;p&gt;When a commit is made, all tests are run. We then make a decision on whether that change was what was intended based on our &amp;quot;managing change&amp;quot; criteria as defined earlier.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/characterisation-tests/workflow.png&quot; alt=&quot;workflow.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;We do this by checking the change against our criteria. Is the change intentional and atomic? Is it free of side effects? Our characterisation tests help us to establish this by failing if something is no longer doing what it used to be.&lt;/p&gt;
&lt;p&gt;Let’s assume we have the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;bar&quot;&lt;/span&gt;; }

&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ApplicationDescriber&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; foo() . &lt;span class=&quot;string&quot;&gt;&quot; app&quot;&lt;/span&gt;; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the following characterisation tests:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;describe(&lt;span class=&quot;string&quot;&gt;&quot;foo()&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
  it(&lt;span class=&quot;string&quot;&gt;&quot;returns bar&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
    expect(foo())-&amp;gt;toEqual(&lt;span class=&quot;string&quot;&gt;&quot;bar&quot;&lt;/span&gt;);
  });
});

describe(&lt;span class=&quot;string&quot;&gt;&quot;ApplicationDescriber&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
  describe(&lt;span class=&quot;string&quot;&gt;&quot;getName()&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
    it(&lt;span class=&quot;string&quot;&gt;&quot;returns the name of the application&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{
      expect(ApplicationDescriber::getName())-&amp;gt;toEqual(&lt;span class=&quot;string&quot;&gt;&quot;foo app&quot;&lt;/span&gt;);
    });
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, someone makes the following change:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;boop&quot;&lt;/span&gt;; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the tests run, they will tell us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Before this change to &lt;code&gt;foo()&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;foo()&lt;/code&gt; returned &amp;quot;bar&amp;quot;, now it returns &amp;quot;boop&amp;quot;&lt;/li&gt;
&lt;li&gt;Class &lt;code&gt;ApplicationDescriber&lt;/code&gt; method &lt;code&gt;getName()&lt;/code&gt; used to return &amp;quot;bar app&amp;quot;, now returns &amp;quot;boop app&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not only did the change to function &lt;code&gt;foo()&lt;/code&gt; trip its own test, it also tripped the characterisation test for class &lt;code&gt;ApplicationDescriber&lt;/code&gt;! This has exposed a coupling in the system - changes to &lt;code&gt;foo()&lt;/code&gt; affect function &lt;code&gt;getName()&lt;/code&gt; in class &lt;code&gt;ApplicationDescriber&lt;/code&gt;. At this point, we would step back and examine this change against the criteria we defined earlier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Was it an &lt;strong&gt;intention&lt;/strong&gt; of this change to affect the application name from &lt;code&gt;ApplicationDescriber::getName()&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Should the system be refactored to decouple these components?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is, of course, a very simple and contrived example, but it serves to illustrate the practical usage of characterisation tests.&lt;/p&gt;
&lt;h2 id=&quot;lifecycle&quot;&gt;Lifecycle&lt;/h2&gt;
&lt;p&gt;Here is the lifecycle of a characterisation test in 4 phases:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/characterisation-tests/lifecycle.png&quot; alt=&quot;lifecycle.png&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;phase-1-panic&quot;&gt;Phase 1: Panic&lt;/h3&gt;
&lt;p&gt;Let’s say we are assigned a feature to work on. We start off with no knowledge of the feature and minimal confidence.&lt;/p&gt;
&lt;h3 id=&quot;phase-2-characterisation&quot;&gt;Phase 2: Characterisation&lt;/h3&gt;
&lt;p&gt;We characterise this feature. Characterisation increases our confidence because, if a change happens, we will know about it, but it does not necessarily increase our understanding.&lt;/p&gt;
&lt;h3 id=&quot;phase-3-understanding&quot;&gt;Phase 3: Understanding&lt;/h3&gt;
&lt;p&gt;Just because we have &lt;em&gt;characterised&lt;/em&gt; something doesn’t mean we’ve &lt;em&gt;understood&lt;/em&gt; it. We therefore refactor and write proper tests. Our understanding can now develop from a position of stability, helping to ensure that change is intentional.&lt;/p&gt;
&lt;h3 id=&quot;phase-4-confidence&quot;&gt;Phase 4: Confidence&lt;/h3&gt;
&lt;p&gt;Once we are comfortable with our tests and documentation, we can throw away our characterisation tests. We don’t need them any more - there’s no need for this safety net because characterisation tests have no &lt;em&gt;context&lt;/em&gt;. Semantically they don’t mean much; they are just a snapshot that we can now move past.&lt;/p&gt;
&lt;h4 id=&quot;why-throw-characterisation-tests-away-&quot;&gt;Why throw characterisation tests away?&lt;/h4&gt;
&lt;p&gt;They are only useful when you have low confidence and low test coverage. As confidence and test coverage grow, characterisation tests can actually become a &lt;em&gt;drag&lt;/em&gt; on your velocity. Let’s illustrate this with an example.&lt;/p&gt;
&lt;p&gt;You have two controllers that both use a DateParser. You then either write or generate characterisation tests for your project. You now have a characterisation test for each.&lt;/p&gt;
&lt;p&gt;Let’s say you make a change to the date parser.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/characterisation-tests/disposal.png&quot; alt=&quot;disposal.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;A change to the date parser might well invalidate all three tests, tripping three alarms! Of course, this depends on a lot of variables, such as how well factored the project is and how well written the tests are. Regardless, you can start to get false positives. When we start getting false positives in tests, people lose confidence. Therefore, these characterisation tests are now stale.&lt;/p&gt;
&lt;h4 id=&quot;when-is-a-characterisation-test-stale-&quot;&gt;When is a characterisation test stale?&lt;/h4&gt;
&lt;p&gt;A characterisation test is stale when you have unit tests around the same region of code. Remember that characterisation tests are &lt;em&gt;not&lt;/em&gt; based on an understanding of a system - they simply describe what it does right now. Once you have unit tests which reflect an actual understanding of the system, throw away the characterisation tests as they are now exerting drag rather than adding value.&lt;/p&gt;
&lt;h2 id=&quot;strategy-for-using-characterisation-tests&quot;&gt;Strategy for Using Characterisation Tests&lt;/h2&gt;
&lt;h3 id=&quot;1-don-t-change-until-you-have-tests-around-the-code&quot;&gt;1. Don’t change until you have tests around the code&lt;/h3&gt;
&lt;p&gt;Without tests, you risk making unintentional changes.&lt;/p&gt;
&lt;h3 id=&quot;2-delete-when-they-become-stale&quot;&gt;2. Delete when they become stale&lt;/h3&gt;
&lt;p&gt;False positives cause people to lose confidence in tests, so throw away characterisation tests after they are made redundant by unit/integration tests.&lt;/p&gt;
&lt;h3 id=&quot;3-separate-out-characterisation-tests&quot;&gt;3. Separate out characterisation tests&lt;/h3&gt;
&lt;p&gt;Do not mix in characterisation tests with your unit tests; instead, put them in a separate directory. Characterisation tests are not based on an understanding of the system; they are more like a snapshot of the application’s functionality, so they should not be mingled in with more mature tests.&lt;/p&gt;
&lt;h3 id=&quot;4-make-increasing-test-coverage-a-deliverable&quot;&gt;4. Make increasing test coverage a deliverable&lt;/h3&gt;
&lt;p&gt;There is always pressure to produce features, which can result in perceived pressure to skip testing. This is a totally false economy; if change is not managed, side effects can cause a legacy application to crumble in a matter of weeks. Instead, make increasing test coverage an achievable, trackable sprint deliverable - for example, &amp;quot;increase test coverage by 1% this sprint&amp;quot;.&lt;/p&gt;
&lt;h3 id=&quot;5-be-aware-of-the-broader-picture&quot;&gt;5. Be aware of the broader picture&lt;/h3&gt;
&lt;p&gt;Characterisation tests must &lt;em&gt;not&lt;/em&gt; be all you use to stabilise your legacy projects. Rather, they are a part of a broader picture of stabilisation. Here are some complementary strategies, all with the goal of stabilisation:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/characterisation-tests/big-picture.png&quot; alt=&quot;big-picture.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Taking on a legacy application can be fraught with peril, and it is vital to ensure stability as quickly as possible. We, as testing professionals, have a responsibility to make sure that all change to the system is intended change. Characterisation tests are a great stepping stone towards assuring that change to a legacy application is intentional and atomic, rather than haphazard and unpredictable.&lt;/p&gt;
</description></item><item><title>Announcing Radiian</title><link>http://radify.io/blog/announcing-radiian/</link><pubDate>Tue, 08 Sep 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/announcing-radiian/</guid><author></author><description>&lt;p&gt;At Radify, we greatly favor immutable infrastructure, which we described in two previous posts, &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;Reducing Infrustration&lt;/a&gt; and &lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;Immutable Demo Nodes&lt;/a&gt;. We also outlined a simple method for setting up &lt;a href=&quot;http://radify.io/blog/painless-immutable-infrastructure-with-ansible-and-aws/&quot;&gt;immutable infrastructure on AWS with Ansible&lt;/a&gt;. We have now gone a step further and created &lt;a href=&quot;https://www.npmjs.com/package/radiian&quot;&gt;Radiian&lt;/a&gt; (RADify Immutable Infrastructure for ANsible), a tool which automates the process of creating a ready-to-go Ansible playbook to deploy immutable infrastructure on AWS.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://www.npmjs.com/package/radiian&quot;&gt;Radiian on NPM&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-radiian-&quot;&gt;What is Radiian?&lt;/h2&gt;
&lt;p&gt;Radiian scaffolds an Ansible playbook for deploying immutable infrastructure on AWS. This playbook provides a template for deploying whatever Ansible roles you like in an &lt;a href=&quot;http://radify.io/blog/painless-immutable-infrastructure-with-ansible-and-aws/&quot;&gt;immutable fashion&lt;/a&gt;. It will take care of all the immutable infrastructure side of things (standing up nodes, tearing them down, etc), leaving you free to focus on what you want installed on your nodes.&lt;/p&gt;
&lt;p&gt;The generated playbook takes care of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tagging old EC2 nodes for termination&lt;/li&gt;
&lt;li&gt;Standing up new EC2 nodes&lt;/li&gt;
&lt;li&gt;Adding the new EC2 nodes to the Elastic Load Balancer (ELB)&lt;/li&gt;
&lt;li&gt;Terminating tagged old EC2 nodes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/blog/painless-immutable-infrastructure-with-ansible-and-aws/workflow.png&quot; alt=&quot;What the playbook does&quot;&gt;&lt;/p&gt;
&lt;p&gt;Your job is then just to configure the Ansible roles that you need to provision your EC2 nodes.&lt;/p&gt;
&lt;h2 id=&quot;workflow&quot;&gt;Workflow&lt;/h2&gt;
&lt;p&gt;Radiian has a simple workflow:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/announcing-radiian/Radiian-Workflow.png&quot; alt=&quot;Radiian-Workflow.png&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-radiian-is-not&quot;&gt;What Radiian is not&lt;/h2&gt;
&lt;p&gt;As you can see from the diagram above, Radiian creates an Ansible playbook, but is &lt;em&gt;not&lt;/em&gt; responsible for running and debugging that playbook. For example, from the diagram it is clear that Radiian is not responsible for creating and saving your private &lt;code&gt;.pem&lt;/code&gt; key. Radiian is not an Ansible installer, nor does it set up AWS for you. If you&amp;#39;re having trouble with Ansible, there is &lt;a href=&quot;https://docs.ansible.com/ansible/intro_installation.html&quot;&gt;extensive documentation&lt;/a&gt;. If you&amp;#39;re new to AWS, &lt;a href=&quot;https://aws.amazon.com/getting-started/&quot;&gt;Amazon explains&lt;/a&gt; how to get started.&lt;/p&gt;
&lt;p&gt;The only service that Radiian provides is to scaffold a template Ansible playbook for deploying immutable infrastructure on AWS.&lt;/p&gt;
&lt;h2 id=&quot;what-sets-radiian-apart&quot;&gt;What Sets Radiian Apart&lt;/h2&gt;
&lt;p&gt;Immutable Infrastructure makes Radiian different from many other Ansible tools. Yeoman&amp;#39;s &lt;a href=&quot;https://www.npmjs.com/package/generator-ansible&quot;&gt;Ansible generator&lt;/a&gt; creates a playbook, but without immutable architecture. Radiian does not &lt;a href=&quot;https://www.npmjs.com/package/ansible-ubuntu&quot;&gt;tie you to Ubuntu&lt;/a&gt;, or &lt;a href=&quot;https://www.npmjs.com/package/do-inventory&quot;&gt;to DigitalOcean&lt;/a&gt;, or &lt;a href=&quot;https://www.npmjs.com/package/dockerflow&quot;&gt;to Docker&lt;/a&gt;. All Radiian seeks to do is to layout a simple project template that relies upon immutable infrastructure.&lt;/p&gt;
&lt;h2 id=&quot;sample-use-cases&quot;&gt;Sample Use Cases&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;A new project: If you want to create a new project using immutable cloud infrastructure, Radiian is exactly what you need.&lt;/li&gt;
&lt;li&gt;An existing project: You like the idea of immutable infrastructure, but aren&amp;#39;t sure how to migrate your existing work to such an architecture. Radiian gives you a minimal playbook from which you can begin to migrate your project to immutable infrastructure, AWS, or both.&lt;/li&gt;
&lt;li&gt;&amp;quot;Tinkering fatigue&amp;quot;: &amp;quot;Who has changed what in our servers? Who has been tinkering around in EC2?&amp;quot; If you get tired of asking such questions (i.e., you are suffering from &lt;a href=&quot;http://kief.com/configuration-drift.html&quot;&gt;configuration drift&lt;/a&gt;), Radiian&amp;#39;s approach to AWS architecture will keep you from having to ask those questions ever again. All changes to your AWS configuration are preserved in your Ansible playbook, which in turn is kept under version control history, so you can always know who changed something and when it was done. More importantly, every update to the playbook destroys the old nodes and creates new ones. At all times, your architecture is &lt;em&gt;exactly&lt;/em&gt; what is described in the playbook.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;video-walkthrough&quot;&gt;Video Walkthrough&lt;/h2&gt;
&lt;div class=&quot;video&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/ZcSwvHaKgfc?vq=hd720&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;h2 id=&quot;moving-forward&quot;&gt;Moving forward&lt;/h2&gt;
&lt;p&gt;Radiian offers a minimal framework to get started with immutable infrastructure. Thanks to Radiian you can quickly and efficiently create a new project on, or switch an old project to, immutable infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://www.npmjs.com/package/radiian&quot;&gt;Radiian on NPM&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>In Search of the One True Gulpfile</title><link>http://radify.io/blog/one-true-gulpfile/</link><pubDate>Wed, 26  Aug 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/one-true-gulpfile/</guid><author></author><description>&lt;p&gt;Ever since switching from Grunt to Gulp, one of my first steps when starting a new JavaScript project has been to copy the &lt;code&gt;Gulpfile&lt;/code&gt; from my &lt;em&gt;previous&lt;/em&gt; JavaScript project, and modify it accordingly. Modifications are necessary firstly to suit the subtly different needs of each new project, and secondly of course, for taste.&lt;/p&gt;
&lt;p&gt;While comparing &lt;code&gt;Gulpfile&lt;/code&gt;s over time is an interesting little window into how my style and preferences have evolved, it pains me to have so much subtly duplicated functionality spread across so many projects, none of which are kept consistently up-to-date.&lt;/p&gt;
&lt;p&gt;Aside from my own meandering laziness, I believe this is partly owing to Gulp&amp;#39;s design, and partly what Gulp was created in reaction to. Whereas Grunt expected you to cram every varying combination of options into declarative configuration, which is easy to store and move around, but not very expressive, Gulp encourages composition through the definition of many small sub-tasks, which is highly expressive but tends to result in tightly-coupled processes &amp;amp; repeated steps, and managing configuration is left up to the developer. Both approaches leave something to be desired.&lt;/p&gt;
&lt;h3 id=&quot;the-middle-path&quot;&gt;The middle path&lt;/h3&gt;
&lt;p&gt;Furthermore, while Gulp&amp;#39;s chaining style makes for terse syntax, and its factory-function style makes it easy to configure individual process steps, it presents no clear way to configure the process itself. The ideal is a unified way to configure both the steps &lt;em&gt;and&lt;/em&gt; the process. Also, a way to cleanly separate the process from the configuration, compose them in one place, and extract out any project-specific details, so that one &lt;code&gt;Gulpfile&lt;/code&gt; can rule them all.&lt;/p&gt;
&lt;p&gt;Fortunately, most of our projects have similar needs, and follow a relatively consistent directory structure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;build/&lt;/code&gt;: intermediate build files&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dist/&lt;/code&gt;: production-ready distributable files&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spec/&lt;/code&gt;: BDD spec files, suffixed as &lt;code&gt;*Spec.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/&lt;/code&gt;: library/application source files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most new JS projects are written in ES6 (ES2015), so our needs for each project generally look something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile source &amp;amp; tests to a particular module format (usually CommonJS or UMD)&lt;/li&gt;
&lt;li&gt;Run tests using built files&lt;/li&gt;
&lt;li&gt;Generate minified and non-minified production builds&lt;/li&gt;
&lt;li&gt;Generate sourcemaps&lt;/li&gt;
&lt;li&gt;Watch source &amp;amp; tests for changes during development, re-run tests&lt;/li&gt;
&lt;li&gt;Run a dev server to serve files for in-browser testing (sometimes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After reviewing a few of our most recent projects, I was able to come up with a &lt;code&gt;Gulpfile&lt;/code&gt; that meets the above requirements, but also satisfies my desired constraints on process &amp;amp; configuration. Without further ado, weighing in at 55 lines (at the time of this writing), here is the listing in its entirety:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/090bd6bda8b3e8f2de31.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;p&gt;Important things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As of Gulp 3.9, files named &lt;code&gt;Gulpfile.babel.js&lt;/code&gt; are automatically transpiled from ES6, which for us means that &lt;code&gt;Gulpfile&lt;/code&gt;s are no longer the one bit of a project where our brains must revert to old-school JavaScript&lt;/li&gt;
&lt;li&gt;Almost all of the configuration is encapsulated in 2 blocks: one for file and directory paths, one for build settings&lt;/li&gt;
&lt;li&gt;Project-specific configuration, such as the name of the build file and the port on which to run the dev server (where applicable) has been extracted out to &lt;code&gt;package.json&lt;/code&gt; in a custom key called (naturally) &lt;code&gt;build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;All possible build steps are listed out in one place (&lt;code&gt;pipeline()&lt;/code&gt;, lines 29-36); since the order of each step relative to others is always consistent, configuration can be used to toggle them on and off &amp;mdash; which is made easy with &lt;a href=&quot;https://github.com/robrich/gulp-if&quot;&gt;gulp-if&lt;/a&gt; (aliased as &lt;code&gt;gif()&lt;/code&gt; above)&lt;/li&gt;
&lt;li&gt;A few small utility functions (&lt;code&gt;build()&lt;/code&gt;, &lt;code&gt;chain()&lt;/code&gt;) are used to map named build configurations (with optional overrides) to a flattened-out &lt;code&gt;.pipe()&lt;/code&gt; chain, and tighten up function-handling syntax (&lt;code&gt;bind()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Though it&amp;#39;s not really necessary for low-complexity scripts like this, I&amp;#39;ve gotten into the habit of declaring things as &lt;code&gt;const&lt;/code&gt; whenever possible (even though &lt;a href=&quot;http://raganwald.com/2015/05/30/de-stijl.html&quot;&gt;JS &lt;code&gt;const&lt;/code&gt;s aren&amp;#39;t &lt;em&gt;really&lt;/em&gt; real constants&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each build task is then assigned a function with a named configuration, which can be merged with passed parameters (in the form of command line arguments in the case of &lt;code&gt;&amp;#39;dist&amp;#39;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The end result is that almost everything is expressed exactly once. Not only that, it allows for any configurable option to be overidden from the command line, for free. For example, if I wanted a minified production file with sourcemaps and AMD-formatted modules, I could run &lt;code&gt;gulp dist --min --smaps --modules=amd&lt;/code&gt;. This approach also has the benefit of programatically enforcing project structure conventions.&lt;/p&gt;
&lt;p&gt;While the above is only appropriate for JavaScript library projects (it doesn&amp;#39;t address CSS or other front-end tasks), the structure and patterns serve as a good basis for a generalized &lt;code&gt;Gulpfile&lt;/code&gt;, and project-specific tasks can always be added transparently by introducing a &lt;a href=&quot;https://www.npmjs.com/package/require-dir&quot;&gt;&lt;code&gt;requireDir&lt;/code&gt;-style pattern&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So that&amp;#39;s my take. If you too are obsessive enough about build configuration to have a philosophy for managing it, I&amp;#39;d love to hear about it.&lt;/p&gt;
</description></item><item><title>AWS Lambda Workflow</title><link>http://radify.io/blog/aws-lambda-workflow/</link><pubDate>Wed, 29 Jul 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/aws-lambda-workflow/</guid><author></author><description>&lt;p&gt;&lt;a href=&quot;http://aws.amazon.com/documentation/lambda/&quot;&gt;AWS Lambda&lt;/a&gt; is definitely the New Hotness - it allows you to run functions in the cloud with no persistent infrastructure!&lt;/p&gt;
&lt;p&gt;Lambda can be described as &amp;quot;able to respond to predefined events by launching AWS resources and executing functions, without the user needing to manage the underlying infrastructure&amp;quot;. Lambda is essentially user-created functions that run on demand in the cloud. This has the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only pay for what you use - no ongoing costs&lt;/li&gt;
&lt;li&gt;Hugely scalable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In some projects, we were able to do away with EC2 nodes or containers entirely. For example, we recently built an application with no infrastructure at all - only a web site in S3, and functions executed in Lambda which talked to a Firebase database. This meant that we had absolutely no web nodes at all to run our code:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/aws-lambda-workflow/aws-lambda-s3-firebase.png&quot; alt=&quot;Application running on S3, Lambda and Firebase&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-about-workflow-&quot;&gt;What about workflow?&lt;/h2&gt;
&lt;p&gt;This is a novel way of doing software; it is certainly quite different to much of what we have done before. We have a few &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;principles&lt;/a&gt; that we like to apply to our development practises, and so, one of our first questions was, &amp;quot;how can we incorporate this into our workflow?&amp;quot;. This includes considerations like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt; - How can we automatically deploy our application?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed of development&lt;/strong&gt; - How can we run it locally so we don&amp;#39;t have to keep uploading our code through Amazon&amp;#39;s console every time we make a change?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing&lt;/strong&gt; - How can we test our code?&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;working-with-node-lambda&quot;&gt;Working with node-lambda&lt;/h2&gt;
&lt;p&gt;Whilst we can use the AWS console to manage our Lambda functions, we can get a smoother development workflow using &lt;a href=&quot;https://www.npmjs.com/package/node-lambda&quot;&gt;node-lambda&lt;/a&gt;. This tool allows both pushing of Lambda function and, crucially, means we can run our Lambda functions locally.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/aws-lambda-workflow/development-with-node-lambda.png&quot; alt=&quot;Development with node-lambda&quot;&gt;&lt;/p&gt;
&lt;p&gt;To get started, run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;node-lambda setup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You now have two new files - &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;event.json&lt;/code&gt;. &lt;code&gt;.env&lt;/code&gt; is a file that node-lambda uses to configure your function - what its name is, which role is used to access it, how much memory, and so on. &lt;code&gt;event.json&lt;/code&gt; is the data that &lt;code&gt;node-lambda&lt;/code&gt; will pass to your function when you invoke it with &lt;code&gt;node-lambda run&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;local-testing-with-node-lambda&quot;&gt;Local testing with node-lambda&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s assume that your function is in a file &lt;code&gt;index.js&lt;/code&gt; and looks like the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;exports.handler = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;event, context&lt;/span&gt;) &lt;/span&gt;{
    &lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log( &lt;span class=&quot;string&quot;&gt;&quot;event&quot;&lt;/span&gt;, event );
    context.done( );
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, let&amp;#39;s assume that in &lt;code&gt;event.json&lt;/code&gt; you have:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;{
    &lt;span class=&quot;string&quot;&gt;&quot;foo&quot;&lt;/span&gt;:&lt;span class=&quot;string&quot;&gt;&quot;bar&quot;&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can run it with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;node-lambda run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because it posts whatever data it finds in &lt;code&gt;event.json&lt;/code&gt; to your function, you should see:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;event { foo: &amp;#39;bar&amp;#39; }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To verify it&amp;#39;s running truly offline, turn off wifi, unplug your ethernet, and then run &lt;code&gt;node-lambda run&lt;/code&gt; again. This proves that it&amp;#39;s running locally and not connecting to AWS.&lt;/p&gt;
&lt;h3 id=&quot;deployment-with-node-lambda&quot;&gt;Deployment with node-lambda&lt;/h3&gt;
&lt;aside class=&quot;sidebar&quot;&gt;
Before getting started with node-lambda deploy, it&amp;#39;s a good idea to go through and create a Lambda function manually through the &lt;a href=&quot;https://console.aws.amazon.com/lambda&quot;&gt;Amazon web interface&lt;/a&gt;. This will ensure that you have all the role configuration set up and it&amp;#39;s a really good exercise.
&lt;/aside&gt;

&lt;p&gt;To set this up, configure &lt;code&gt;.env&lt;/code&gt; so it has all the right values:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;AWS_ENVIRONMENT=development
AWS_ACCESS_KEY_ID=YOUR_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET
AWS_ROLE_ARN=your_amazon_role
AWS_FUNCTION_NAME=your_&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;_name
AWS_MODE=event
AWS_MEMORY_SIZE=&lt;span class=&quot;number&quot;&gt;128&lt;/span&gt;
AWS_TIMEOUT=&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;
AWS_DESCRIPTION=
AWS_RUNTIME=nodejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most of these defaults will work without modification, but the ones you really need to pay attention to are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;: access key assigned by AWS. See our post &lt;a href=&quot;http://radify.io/blog/painless-immutable-infrastructure-with-ansible-and-aws/&quot;&gt;Painless Immutable Infrastructure with Ansible and AWS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AWS_ROLE_ARN&lt;/code&gt;: looks something like &lt;code&gt;arn:aws:iam::1234567890123:role/lambda_basic_execution&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AWS_FUNCTION_NAME&lt;/code&gt;: the name of your function. Must be unique. &lt;code&gt;node-lambda&lt;/code&gt; will automatically suffix the version number from &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Running the following will publish your function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;node-lambda deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check out &lt;code&gt;.env&lt;/code&gt; for the configuration of the function. Essentially, it creates or updates the function {AWS_FUNCTION_NAME}-{version}, where version is taken from your &lt;code&gt;package.json&lt;/code&gt;. If your function name is &lt;code&gt;foo&lt;/code&gt; and your package.json has version &lt;code&gt;1.2.3&lt;/code&gt;, function &lt;code&gt;foo-1.2.3&lt;/code&gt; will be set up in Lambda. Here&amp;#39;s an example:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/aws-lambda-workflow/aws-lambda-functions.png&quot; alt=&quot;A couple of versions of the same function&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;troubleshooting-node-lambda-deploy-&quot;&gt;Troubleshooting &lt;code&gt;node-lambda deploy&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;When telling &lt;code&gt;.env&lt;/code&gt; which role to use, make sure you use a role ARN, not the function ARN. I got:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;#39;validation error detected: Value \&amp;#39;arn:aws:lambda:REDACTED:REDACTED:function:REDACTED\&amp;#39; at \&amp;#39;role\&amp;#39; failed to satisfy constraint: Member must satisfy regular expression pattern: arn:aws:iam::\\d{12}:role/?[a-zA-Z_0-9+=,.@\\-_/]+&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I had to enable these Managed Policies for the role &lt;code&gt;lambda_basic_execution&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AWSLambdaBasicExecutionRole&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AWSLambdaRole&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;recommended-practise&quot;&gt;Recommended practise&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Modularise your code and unit test it outside of Lambda - your lambda function should hand off to a library that you have built and tested separately using more conventional tools. This way, it&amp;#39;s easy to unit test your code in a normal workflow.&lt;/li&gt;
&lt;li&gt;Test locally with &lt;code&gt;node-lambda run&lt;/code&gt;. This verifies that it all integrates well.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;node-lambda deploy&lt;/code&gt; to update your function in the cloud.&lt;/li&gt;
&lt;li&gt;Use the version number is &lt;code&gt;package.json&lt;/code&gt; for versioning.&lt;/li&gt;
&lt;li&gt;Be careful about invoking Lambda directly in browser. Yes, you can do it, but be careful not to expose your client key and secret key.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;These are practises that have worked well for us so far; hopefully this has given you a few ideas to help you to get started with working with AWS Lambda.&lt;/p&gt;
&lt;h2 id=&quot;other-resources&quot;&gt;Other resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@AdamRNeary/a-gulp-workflow-for-amazon-lambda-61c2afd723b6&quot;&gt;Adam Neary: A Gulp Workflow for Amazon Lambda&lt;/a&gt; - you can use Gulp to create zips and upload them to Lambda.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/gulp-awslambda&quot;&gt;gulp-awslambda&lt;/a&gt; - allows you to push Lambda to AWS as part of your Gulp workflow.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/grunt-aws-lambda&quot;&gt;grunt-aws-lambda&lt;/a&gt; - allows both pushing of Lambda function and local development&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@AdamRNeary/developing-and-testing-amazon-lambda-functions-e590fac85df4&quot;&gt;Adam Neary: Developing and Testing Amazon Lambda Functions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://aws.amazon.com/lambda/faqs/&quot;&gt;Amazon&amp;#39;s AWS Lambda FAQs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://research.gigaom.com/2015/01/why-aws-lambda-is-a-masterstroke-from-amazon/&quot;&gt;Why AWS Lambda is a masterstroke from Amazon - Janakiram MSV&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description></item><item><title>Understanding NGModelController By Example - part 2</title><link>http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-2/</link><pubDate>Fri, 05 Jun 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-2/</guid><author></author><description>&lt;p&gt;In our &lt;a href=&quot;http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/&quot;&gt;previous post on NGModelController&lt;/a&gt;, we had a look at the way that it all hangs together and worked through a quick example of building our own custom directives with powerful data transformations. In this second post in the series, we will look at how we can apply validation to our directives.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;http://jsfiddle.net/L2qnsmgd/&quot;&gt;View the code!&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;parsers-bigger-than-they-look&quot;&gt;Parsers: bigger than they look&lt;/h2&gt;
&lt;p&gt;Parsers have two purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;to convert the &lt;code&gt;$viewValue&lt;/code&gt; that is represented in the browser into the underlying value. We saw this in the &lt;a href=&quot;http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/&quot;&gt;our previous post on NGModelController&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;to sanitise or validate the &lt;code&gt;$viewValue&lt;/code&gt; - so we can apply validation in the view layer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is this second purpose we are going to look at here: adding validation that asserts that blue is not a valid colour selection for our directive. You can &lt;a href=&quot;http://jsfiddle.net/L2qnsmgd/&quot;&gt;view the example code on JSFiddle&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;adding-validation&quot;&gt;Adding validation&lt;/h2&gt;
&lt;p&gt;Again, we are developing our example from part 1 a little bit further. Let&amp;#39;s modify the HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-app&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;RadifyExample&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;container&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-controller&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;ColourPickerController&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;myform&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;Colours&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;h2&lt;/span&gt;&amp;gt;&lt;/span&gt;Foreground&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;h2&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-model&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;foreground&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-show&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;'myform.$error.foreground_badColour'&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;bg-danger&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;No blue please!&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;h2&lt;/span&gt;&amp;gt;&lt;/span&gt;Background&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;h2&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-model&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;background&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-show&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;'myform.$error.background_badColour'&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;bg-danger&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;No blue please!&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-style&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;{'background': background, 'color': foreground }&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;results&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
        Results
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-disabled&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;myform.$invalid&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-click&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;test()&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;btn btn-primary&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;button&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;form&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that we&amp;#39;ve:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Created a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; paragraphs that say &amp;quot;No blue please!&amp;quot;&lt;/li&gt;
&lt;li&gt;Added a button that is disabled if the form is invalid&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, let&amp;#39;s add something to the controller:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;.controller(&lt;span class=&quot;string&quot;&gt;'ColourPickerController'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;$scope&lt;/span&gt;) &lt;/span&gt;{
    $scope.background = &lt;span class=&quot;string&quot;&gt;'F00'&lt;/span&gt;;
    $scope.foreground = &lt;span class=&quot;string&quot;&gt;'000'&lt;/span&gt;;

    angular.extend($scope, {
        test: &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;{
            alert(&lt;span class=&quot;string&quot;&gt;&quot;Submitted!&quot;&lt;/span&gt;);
        }
    });
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this does is alerts &amp;quot;Submitted!&amp;quot;, so we can easily see whether the button has been disabled or not.&lt;/p&gt;
&lt;p&gt;Because parsers are a chain, we can have as many as we like, so we are going to insert a new one. We are not transforming the value in this parser (the first purpose of parsers); instead, all we are doing is the second purpose - validating the view value. Therefore, we are going to insert it BEFORE the current parser in our code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// add validation&lt;/span&gt;
ngModelCtrl.$parsers.push(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;viewValue&lt;/span&gt;) &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; blueSelected = (viewValue.red === &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;
      &amp;amp;&amp;amp; viewValue.green === &lt;span class=&quot;string&quot;&gt;&quot;0&quot;&lt;/span&gt;
      &amp;amp;&amp;amp; viewValue.blue === &lt;span class=&quot;string&quot;&gt;&quot;F&quot;&lt;/span&gt;);

  ngModelCtrl.$setValidity(
      iAttrs.ngModel + &lt;span class=&quot;string&quot;&gt;'_badColour'&lt;/span&gt;,
      !blueSelected
  );

  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; viewValue;
});

ngModelCtrl.$parsers.push(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;viewValue&lt;/span&gt;) &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;#&quot;&lt;/span&gt; + [viewValue.red, viewValue.green, viewValue.blue].join(&lt;span class=&quot;string&quot;&gt;''&lt;/span&gt;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if you select blue for either of the colours, the button should be disabled and you should see a warning.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-2/validation.png&quot; alt=&quot;Validation in action&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-does-this-work-&quot;&gt;How does this work?&lt;/h2&gt;
&lt;p&gt;As we noted, we can have as many parsers as we like. We &lt;strong&gt;could&lt;/strong&gt; do all the transformation &lt;strong&gt;and&lt;/strong&gt; validation in a single parser function, but splitting it up into individual validation rules and transformations makes things a bit more modular and composable.&lt;/p&gt;
&lt;p&gt;So, this gives us the validation - which sets &lt;code&gt;myform.$invalid&lt;/code&gt;. Because the directives are bound to model values inside myform, if validation fails in either of them, &lt;code&gt;myform&lt;/code&gt; is considered invalid. We&amp;#39;ve also added the paragraphs with the &lt;code&gt;bg-danger&lt;/code&gt; class, which only show if there is a specific problem. It&amp;#39;s always important to tell the user WHY you&amp;#39;re not prepared to accept their data, otherwise you just look passive-aggressive and crazy! ;-)&lt;/p&gt;
&lt;p&gt;Notice that we have two potential errors that can be set on the form: &lt;code&gt;foreground_badColour&lt;/code&gt; and &lt;code&gt;background_badColour&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;ngModelCtrl.$setValidity(
  iAttrs.ngModel + &lt;span class=&quot;string&quot;&gt;'_badColour'&lt;/span&gt;,
  !blueSelected
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We use &lt;code&gt;iAttrs.ngModel&lt;/code&gt; from the enclosing scope - which allows us to separate out the error messages so we can show the validation messages in the correct places.&lt;/p&gt;
&lt;h2 id=&quot;what-else-can-i-do-with-this-&quot;&gt;What else can I do with this?&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve seen that parsers have two purposes: validation and transformation. We can apply multiple validations - as many as we like - to verify various things about our data. This is an incredibly powerful for providing rich, sophisticated controls for our data!&lt;/p&gt;
&lt;h2 id=&quot;more-on-the-topic&quot;&gt;More on the topic&lt;/h2&gt;
&lt;p&gt;In the third and final article in our series, we will look at unit testing.&lt;/p&gt;
</description></item><item><title>Painless Immutable Infrastructure with Ansible and AWS</title><link>http://radify.io/blog/painless-immutable-infrastructure-with-ansible-and-aws/</link><pubDate>Wed, 27 May 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/painless-immutable-infrastructure-with-ansible-and-aws/</guid><author></author><description>&lt;p&gt;In our blog posts &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;Reducing Infrustration&lt;/a&gt; and &lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;Immutable Demo Nodes&lt;/a&gt;, we talk about our approach to immutable infrastructure and the benefits we have seen from employing this approach. In this article, we explore a practical project example so you can get up and running with immutable infrastructure in less than an hour!&lt;/p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;Ansible is incredibly powerful and features a whole lot of tools for manipulating AWS (Amazon Web Services) infrastructure.&lt;/p&gt;
&lt;p&gt;We&amp;#39;re going to start with the simplest project that we can; let&amp;#39;s assume you have an application that you want to deploy onto immutable EC2 nodes. Your app could be anything - PHP, Python, Ruby, NodeJS - it doesn&amp;#39;t matter!&lt;/p&gt;
&lt;p&gt;We are going to work through an example, step-by-step, to show you how it could be done in a simple way in Ansible.&lt;/p&gt;
&lt;h2 id=&quot;order-of-events&quot;&gt;Order of events&lt;/h2&gt;
&lt;p&gt;Here&amp;#39;s what we&amp;#39;re aiming for. It&amp;#39;s a simple method for immutable infrastructure which is based on adding nodes to the load balancer, then destroying all the old nodes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/painless-immutable-infrastructure-with-ansible-and-aws/workflow.png&quot; alt=&quot;workflow.png&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tag any running instances of your project (if there are any) with oldMyApp=True&lt;/li&gt;
&lt;li&gt;Provision new instance(s)&lt;/li&gt;
&lt;li&gt;Add new instance(s) to the load balancer&lt;/li&gt;
&lt;li&gt;Destroy the nodes you tagged with &amp;quot;oldMyApp=True&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This has the following advantages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If it fails at any point, the load balancer keeps running with its existing nodes - no downtime!&lt;/li&gt;
&lt;li&gt;...and any nodes that&amp;#39;s didn&amp;#39;t provision correctly will automatically be removed on the next run&lt;/li&gt;
&lt;li&gt;It&amp;#39;s super simple!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;step-1-setting-up-aws&quot;&gt;Step 1: Setting up AWS&lt;/h2&gt;
&lt;p&gt;Before we get started, we are going to do a few setup tasks to get our infrastructure ready.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a security group, e.g. &lt;code&gt;sg_myapp&lt;/code&gt; - see &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html&quot;&gt;Amazon&amp;#39;s docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Create a load balancer, e.g. &lt;code&gt;lb-myapp&lt;/code&gt; - see &lt;a href=&quot;http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-getting-started.html&quot;&gt;Amazon&amp;#39;s docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A domain in route53 - see &lt;a href=&quot;http://aws.amazon.com/route53/&quot;&gt;Amazon&amp;#39;s docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;step-2-create-a-directory-for-your-ansible-playbook&quot;&gt;Step 2: Create a directory for your Ansible playbook&lt;/h2&gt;
&lt;p&gt;Pretty much any structure will work. Let&amp;#39;s go with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/ansible - our playbook
/yourapp - your application
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;step-3-dynamic-inventory&quot;&gt;Step 3: Dynamic inventory&lt;/h2&gt;
&lt;p&gt;We use &lt;a href=&quot;http://docs.ansible.com/intro_dynamic_inventory.html&quot;&gt;dynamic inventory&lt;/a&gt; so that Ansible can work out what nodes we have in AWS. So, in directory &lt;code&gt;/ansible/inventory&lt;/code&gt;, put the &lt;code&gt;ec2.ini&lt;/code&gt; and &lt;code&gt;ec2.py&lt;/code&gt; files from the &lt;a href=&quot;http://docs.ansible.com/intro_dynamic_inventory.html&quot;&gt;dynamic inventory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Create &lt;code&gt;/ansible/ansible.cfg&lt;/code&gt; for configuring Ansible to use the dynamic inventory. We suggest:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;title&quot;&gt;[defaults]&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;ansible_managed = &lt;span class=&quot;value&quot;&gt;Ansible managed: {file} modified &lt;span class=&quot;keyword&quot;&gt;on&lt;/span&gt; %Y-%m-%d %H:%M:%S by {uid} &lt;span class=&quot;keyword&quot;&gt;on&lt;/span&gt; {host}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;hostfile = &lt;span class=&quot;value&quot;&gt;inventory/ec2.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;remote_user = &lt;span class=&quot;value&quot;&gt;ubuntu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;title&quot;&gt;[ssh_connection]&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;pipelining = &lt;span class=&quot;value&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;ssh_args = &lt;span class=&quot;value&quot;&gt;-o ControlMaster=auto -o ControlPersist=&lt;span class=&quot;number&quot;&gt;30&lt;/span&gt;m -o StrictHostKeyChecking=&lt;span class=&quot;keyword&quot;&gt;no&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;setting&quot;&gt;control_path = &lt;span class=&quot;value&quot;&gt;/tmp/ansible-ssh-%%h-%%p-%%r&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;sidebar&quot;&gt;
We also recommend having &lt;code&gt;/ansible/inventory/vagrant&lt;/code&gt; and a &lt;code&gt;/Vagrantfile&lt;/code&gt; so that you can run this playbook to start a virtual machine locally that is representative of production. A full treatment of this topic is out of scope of this article, but take a look at our article, &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;4 Principles of DevOps&lt;/a&gt;, for an investigation
&lt;/aside&gt;

&lt;h2 id=&quot;step-4-amazon-access-key-and-secret-key&quot;&gt;Step 4: Amazon access key and secret key&lt;/h2&gt;
&lt;p&gt;Also create &lt;code&gt;/inventory/aws_keys&lt;/code&gt;. This is a file that will simply include your security information so that Ansible can communicate with Amazon Web Services.&lt;/p&gt;
&lt;p&gt;This file should contain information like the following. Your specific values will vary. &lt;a href=&quot;http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html&quot;&gt;Amazon&amp;#39;s documentation tells you how to get these values&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;export&lt;/span&gt; AWS_ACCESS_KEY_ID=&lt;span class=&quot;string&quot;&gt;'HJFLKJ32T32TGEKJG3'&lt;/span&gt;
&lt;span class=&quot;built_in&quot;&gt;export&lt;/span&gt; AWS_SECRET_ACCESS_KEY=&lt;span class=&quot;string&quot;&gt;'HJFLKJ32T32TGEKJG3HJFLKJ32T32TGEKJG3'&lt;/span&gt;
&lt;span class=&quot;built_in&quot;&gt;export&lt;/span&gt; EC2_REGION=&lt;span class=&quot;string&quot;&gt;'us-east-1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;aside class=&quot;sidebar&quot;&gt;
As with any other credential information, handle with care. When committing to a repository, consider &lt;a href=&quot;https://github.com/AGWA/git-crypt&quot;&gt;git-crypt&lt;/a&gt; or similar.
&lt;/aside&gt;


&lt;p&gt;Also, export the .pem from AWS and put it in &lt;code&gt;/ansible/myapp.pem&lt;/code&gt; - follow &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html&quot;&gt;Amazon&amp;#39;s documentation on EC2 keypairs&lt;/a&gt;. This key will be used by Ansible to set your SSH credentials so that it can talk to AWS.&lt;/p&gt;
&lt;h2 id=&quot;step-5-any-specific-roles-your-playbook-may-need&quot;&gt;Step 5: any specific roles your playbook may need&lt;/h2&gt;
&lt;p&gt;We will have a directory &lt;code&gt;/ansible/roles&lt;/code&gt;. These are the roles that install your application. This is out of scope of this article as it will depend on your application.&lt;/p&gt;
&lt;h2 id=&quot;step-6-create-playbook-to-tag-the-old-nodes&quot;&gt;Step 6: create playbook to tag the old nodes&lt;/h2&gt;
&lt;p&gt;Create &lt;code&gt;/ansible/tag-old-nodes.yaml&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;---
- hosts: all
  gather_facts: false
  sudo: no
  tasks:
  - name: Get instance ec2 facts
    action: ec2_facts
    register: ec2_facts
  - name: Add a tag &amp;quot;oldMyApp&amp;quot; to all existing nodes, so we can filter them out later
    local_action: ec2_tag resource={{ec2_facts.ansible_facts.ansible_ec2_instance_id}} region=&amp;#39;us-east-1&amp;#39; state=present
    args:
      tags:
        oldMyApp: true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this does is, using the dynamic inventory, goes through the existing nodes and adds the tag &amp;quot;oldMyApp&amp;quot; (set this tag to something more relevant to your app).&lt;/p&gt;
&lt;h2 id=&quot;step-7-add-playbook-to-stand-up-nodes&quot;&gt;Step 7: add playbook to stand up nodes&lt;/h2&gt;
&lt;p&gt;Create &lt;code&gt;/ansible/immutable.yaml&lt;/code&gt;. Read our comments carefully, please don&amp;#39;t simply copy/paste this!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;---
- hosts: localhost
  connection: local
  gather_facts: false
  vars:
    instance_type: &amp;#39;t2.micro&amp;#39;
    region: &amp;#39;us-east-1&amp;#39;
    aws_zone: &amp;#39;b&amp;#39;
  tasks:
  - name: Launch instance (Ubuntu 14.04 hvm)
    ec2: image=&amp;#39;ami-9eaa1cf6&amp;#39;
         instance_type=&amp;quot;{{ instance_type }}&amp;quot;
         keypair=&amp;#39;myapp&amp;#39;
         instance_tags=&amp;#39;{&amp;quot;Environment&amp;quot;:&amp;quot;myapp&amp;quot;,&amp;quot;Class&amp;quot;:&amp;quot;myapp-immutable&amp;quot;,&amp;quot;Name&amp;quot;:&amp;quot;myapp (immutable)&amp;quot;}&amp;#39;
         region=&amp;#39;{{region}}&amp;#39;
         aws_zone=&amp;#39;{{ region }}{{ aws_zone }}&amp;#39;
         group=&amp;#39;sg_myapp&amp;#39;
         wait=true
    register: ec2_info

  - add_host: hostname={{ item.public_ip }} groupname=&amp;quot;myapp,ec2hosts&amp;quot;
    with_items: ec2_info.instances

  - name: Wait for instances to listen on port 22
    wait_for:
      state=started
      host={{ item.public_dns_name }}
      port=22
    with_items: ec2_info.instances

# Run your specific roles that install and configure your application
- hosts: ec2hosts
  gather_facts: true
  user: ubuntu
  sudo: yes
  roles:
    - myapp

- hosts: ec2hosts
  tasks:
  - name: Gather ec2 facts
    ec2_facts:
  - debug: var=ansible_ec2_instance_id # You can remove this if you like
  - name: Add newly created instance to elb
    local_action:
        module: ec2_elb
        region: &amp;#39;us-east-1&amp;#39;
        instance_id: &amp;quot;{{ ansible_ec2_instance_id }}&amp;quot;
        ec2_elbs: &amp;quot;lb-myapp&amp;quot;
        state: present
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;step-8-add-playbook-to-destroy-old-nodes&quot;&gt;Step 8: add playbook to destroy old nodes&lt;/h2&gt;
&lt;p&gt;Create &lt;code&gt;/ansible/destroy-old-nodes.yaml&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;---
- name: terminate old instances
  hosts: all
  tasks:
    - action: ec2_facts
    - name: terminating old instances
      local_action:
        module: ec2
        state: &amp;#39;absent&amp;#39;
        region: &amp;#39;us-east-1&amp;#39;
        keypair: &amp;#39;myapp&amp;#39;
        instance_ids: &amp;quot;{{ ansible_ec2_instance_id }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All this does is remove any instance that has the tag &amp;quot;oldMyApp&amp;quot;. This tag is actually passed in from the &lt;strong&gt;kick off script&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;kick-off-script&quot;&gt;Kick off script&lt;/h2&gt;
&lt;p&gt;Create &lt;code&gt;/ansible/provision.sh&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;shebang&quot;&gt;#!/bin/bash
&lt;/span&gt;
&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt; -u &lt;span class=&quot;comment&quot;&gt;# Variables must be explicit&lt;/span&gt;
&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;operator&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# If any command fails, fail the whole thing&lt;/span&gt;
&lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt; -o pipefail

&lt;span class=&quot;comment&quot;&gt;# Make sure SSH knows to use the correct pem&lt;/span&gt;
ssh-add myapp.pem
ssh-add &lt;span class=&quot;operator&quot;&gt;-l&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# Load the AWS keys&lt;/span&gt;
. ./inventory/aws_keys

&lt;span class=&quot;comment&quot;&gt;# Tag any existing myapp instances as being old&lt;/span&gt;
ansible-playbook tag-old-nodes.yaml --limit tag_Environment_myapp

&lt;span class=&quot;comment&quot;&gt;# Start a new instance&lt;/span&gt;
ansible-playbook immutable.yaml -vv

&lt;span class=&quot;comment&quot;&gt;# Now terminate any instances with tag &quot;old&quot;&lt;/span&gt;
ansible-playbook destroy-old-nodes.yaml --limit tag_oldmyapp_True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure provision.sh is executable (e.g. &lt;code&gt;chmod u+x provision.sh&lt;/code&gt;). Now, all you have to do, to totally refresh your infrastructure with brand new provisioned nodes, is run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;./provision.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;is-this-a-good-approach-&quot;&gt;Is this a good approach?&lt;/h2&gt;
&lt;p&gt;This is a solid starting point that we use for lots of small projects. It works just great for us for these projects. With more complex projects, we use more sophisticated approaches.&lt;/p&gt;
&lt;p&gt;Larger projects may wish for something more full-featured, for example, creating a new load balancer, running tests, before switching over Route 53.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;This is just one quick-and-easy way of getting started with immutable infrastructure. We hope that it&amp;#39;s given you some confidence to start deploying immutable infrastructure of your own!&lt;/p&gt;
&lt;h2 id=&quot;related-articles&quot;&gt;Related articles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;Immutable Demo Nodes&lt;/a&gt; - how Radify adopted immutable infrastructure and what the benefits have been.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;Four Principles of DevOps&lt;/a&gt; - the principles we apply to our infrastructure and operations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;Reducing Infrustration&lt;/a&gt; - we adopted an immutable infrastructure approach for our web and API nodes. We talk about what it is, why we did it, and what the costs and benefits have been.&lt;/li&gt;
&lt;/ul&gt;
</description></item><item><title>Enforcing Your Pull Request Workflow</title><link>http://radify.io/blog/enforcing-pull-request-workflows/</link><pubDate>Wed, 20 May 2015 08:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/enforcing-pull-request-workflows/</guid><author></author><description>&lt;p&gt;Whether commercial or Open Source, most software projects follow some sort of guidelines for ensuring smooth processes and quality outcomes. On a small team, it&amp;#39;s easy to enforce these rules informally, but to scale up, tools like automated builds and coding-standards checkers are indispensable.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://github.com/radify/PR.js&quot;&gt;PR.js on Github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nowhere is this more acute than Open Source projects. The dueling objectives of keeping barriers to entry low while ensuring the quality of contributions means tools that provide automatic feedback and guidance always win over lengthy contributor guides and human review.&lt;/p&gt;
&lt;p&gt;At Radify, we &lt;a href=&quot;http://labs.radify.io&quot;&gt;run &amp;amp; contribute to a number of different Open Source projects&lt;/a&gt; and, while we have many tools for validating the quality the code itself, we&amp;#39;ve found ourselves having to repeatedly coach would-be contributors on how that code should be submitted. Things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which branch a given change should be submitted to&lt;/li&gt;
&lt;li&gt;that commits for a single, logical change should be squashed&lt;/li&gt;
&lt;li&gt;details a pull request should include&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And everybody&amp;#39;s favorite:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how to format commit messages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As feedback cycles get longer and further away from a contributor, the more likely they are to become discouraged and give up entirely, a loss of unknown potential: could that person have become your next top bug crusher, doc writer, or issue triager?&lt;/p&gt;
&lt;p&gt;We looked around for ways to automate this, but found that the list of existing solutions was... &lt;a href=&quot;https://github.com/radify/PR.js#prior-art&quot;&gt;anemic&lt;/a&gt;... at best. So, we went ahead and made one.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://prjs.radify.io/&quot;&gt;Enter PR.js&lt;/a&gt;. It validates your project&amp;#39;s PRs against a(n optionally configurable) set of rules. It requires no signup, no setup, and no changes to your project. It has built-in rules for most of the above, but you can easily &lt;a href=&quot;https://github.com/radify/PR.js/tree/master/src/rules&quot;&gt;roll your own rules&lt;/a&gt; for anything you like. Internally, we&amp;#39;ll be able to use it for things like validating &lt;a href=&quot;http://radify.io/blog/git-microformats-metrics/&quot;&gt;embedded metadata&lt;/a&gt; in commit messages, ensuring user-facing features have a &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;screenshot and test script&lt;/a&gt;, and that branches are correctly identified for &lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;demo deployment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We now have immediate, linkable, browseable feedback for all of our Open Source projects, and we&amp;#39;re working on further integration with GitHub to manage private projects, as well as provide feedback directly in PRs via the &lt;a href=&quot;https://developer.github.com/v3/repos/statuses/&quot;&gt;Build Status API&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;in-the-wild&quot;&gt;In the wild&lt;/h2&gt;
&lt;p&gt;What kinds of PR workflow rules do you use on your OS project or dev team? Is this something you&amp;#39;d use? Let us know, and if so, feel free to fork and contribute your own rules.&lt;/p&gt;
</description></item><item><title>Understanding NgModelController By Example - part 1</title><link>http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/</link><pubDate>Wed, 06 May 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/</guid><author></author><description>&lt;p&gt;AngularJS’s ngModel.NgModelController is extremely powerful, but it can seem a bit daunting, what with its &lt;code&gt;$formatters&lt;/code&gt; and &lt;code&gt;$render&lt;/code&gt; function and &lt;code&gt;$parsers&lt;/code&gt;... How do we get our heads around it?&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;View the code!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This article assumes you’ve got a little bit of experience with AngularJS. You don’t have to be a brain scientist or a rocket surgeon or anything, so long as you’ve used it a little!&lt;/p&gt;
&lt;p&gt;I developed this article from the notes I wrote as I was learning NgModelController - I found the learning curve a little steep so hopefully this can help somebody else hit the ground running!&lt;/p&gt;
&lt;h2 id=&quot;what-is-ng-model-&quot;&gt;What is ng-model?&lt;/h2&gt;
&lt;p&gt;ng-model is what Angular uses to two-way data bind values to controls, e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;Username
&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-model&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;use.name&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What if you want to display a custom control for a complex value, though? What if you wanted multiple fields to represent a single value? That’s where NgModelController comes in!&lt;/p&gt;
&lt;h2 id=&quot;what-is-ngmodelcontroller-&quot;&gt;What is NgModelController?&lt;/h2&gt;
&lt;p&gt;NgModelController is the same thing that Angular uses to bind ng-model to input boxes and menus and so forth and it has a lot of functionality that you can hook into and take advantage of.&lt;/p&gt;
&lt;h2 id=&quot;what-is-ngmodelcontroller-for-&quot;&gt;What is NgModelController for?&lt;/h2&gt;
&lt;p&gt;NgModelController has the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allows you to set up validation on the ng-model&lt;/li&gt;
&lt;li&gt;Ability to transform the underlying model to and from a view value that can be used to have a sophisticated interface&lt;/li&gt;
&lt;li&gt;Supports transformation of the underlying value into a format that can be displayed differently, and transformation back to the underlying model&lt;/li&gt;
&lt;li&gt;Allows you to monitor when the value has changed and whether it’s clean or dirty&lt;/li&gt;
&lt;li&gt;Neat encapsulation - make the directive self contained&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You would use NgModelController when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You’ve got something you want to bind to ng-model and you need a sophisticated interface to it.&lt;/li&gt;
&lt;li&gt;You want to render a value differently in the UI to how it is represented in the underlying model. For example, a calendar control.&lt;/li&gt;
&lt;li&gt;You have specific validation you want to apply. For example, validating that a dateis within a certain range.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-values-and-life-cycle&quot;&gt;The values and life cycle&lt;/h2&gt;
&lt;p&gt;To allow the conversion of a piece of data into a format it can be manipulated in, and back again, NgModelController works by adding a &lt;code&gt;$modelValue&lt;/code&gt; and a &lt;code&gt;$viewValue&lt;/code&gt; as well as scope values local to the directive. This means that you have:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The actual, real value.&lt;/li&gt;
&lt;li&gt;NgModelController.&lt;code&gt;$modelValue&lt;/code&gt; - the internal value that gets synchronised with the ACTUAL value that’s linked by &lt;code&gt;ng-model&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;NgModelController.&lt;code&gt;$viewValue&lt;/code&gt; - the value that &lt;code&gt;$modelValue&lt;/code&gt; gets translated to.&lt;/li&gt;
&lt;li&gt;scope values - used to bind things in your directive to. Usually a copy of NgModelController.&lt;code&gt;$viewValue&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here are where the values exist:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-1/ng-model-controller-values.png&quot; alt=&quot;NG Model Controller values&quot;&gt;&lt;/p&gt;
&lt;p&gt;NGModelController handles synchronising them through the following process:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-1/ng-model-controller-flow.png&quot; alt=&quot;NG Model Controller values&quot;&gt;&lt;/p&gt;
&lt;p&gt;Yikes! This looks a bit complicated but we are going to go through a worked example bit-by-bit to show how it all works. At some point it will “click” and you will harness the power for yourself!&lt;/p&gt;
&lt;h2 id=&quot;example-a-colour-picker&quot;&gt;Example - a colour picker&lt;/h2&gt;
&lt;p&gt;I’ve made an example colour picker - it’s not amazing but it should illustrate the principles! It allows you to select None, Some or Lots of Red, Green and Blue channels respectively. Under the hood, that’s a single value (e.g. “#FA0”), but in the interface it is three select boxes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-1/picker.png&quot; alt=&quot;Colour picker screenshot&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can play with the code yourself here: &lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;http://jsfiddle.net/cox0sba1/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We have two instances of our colour-picker custom directive and we use ngModelController to convert between the three channel values that the user sees (R, G, B) and the single underlying string that represents the value that ng-model is bound to.&lt;/p&gt;
&lt;h3 id=&quot;the-app-namespace&quot;&gt;The app namespace&lt;/h3&gt;
&lt;p&gt;We define an Angular module called “RadifyExample”:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;angular.module(&lt;span class=&quot;string&quot;&gt;'RadifyExample'&lt;/span&gt;, [])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-controller&quot;&gt;The controller&lt;/h3&gt;
&lt;p&gt;All the controller does is set up background and foreground colour values:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;.controller(&lt;span class=&quot;string&quot;&gt;'ColourPickerController'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;$scope&lt;/span&gt;) &lt;/span&gt;{
    $scope.background = &lt;span class=&quot;string&quot;&gt;'F00'&lt;/span&gt;;
    $scope.foreground = &lt;span class=&quot;string&quot;&gt;'000'&lt;/span&gt;;
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-html-bit&quot;&gt;The HTML bit&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-app&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;RadifyExample&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-controller&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;ColourPickerController&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;Colours&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
        Foreground
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-model&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;foreground&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;
        Background
        &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;ng-model&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;background&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;colour-picker&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;label&lt;/span&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;background: #{{ background }}; color: #{{foreground}};&quot;&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;results&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;
        Results
    &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The two values - foreground and background - from the controller are bound by ng-model to a custom directive colour-picker. This gives us two colour pickers.&lt;/p&gt;
&lt;p&gt;We then have a little area “Results” that simply renders the background and foreground in a div with the word “Results” so we can see what colours the user has selected.&lt;/p&gt;
&lt;h3 id=&quot;the-directive&quot;&gt;The directive&lt;/h3&gt;
&lt;p&gt;First up is a simple template that shows three &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; controls.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;.directive(&lt;span class=&quot;string&quot;&gt;'colourPicker'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; tpl = &lt;span class=&quot;string&quot;&gt;&quot;&amp;lt;div&amp;gt; \
     R &amp;lt;select ng-model='red'&amp;gt; \
         &amp;lt;option value='F'&amp;gt;Lots&amp;lt;/option&amp;gt; \
         &amp;lt;option value='A'&amp;gt;Some&amp;lt;/option&amp;gt; \
         &amp;lt;option value='0'&amp;gt;None&amp;lt;/option&amp;gt; \
     &amp;lt;/select&amp;gt; \
     G &amp;lt;select ng-model='green'&amp;gt; \
         &amp;lt;option value='F'&amp;gt;Lots&amp;lt;/option&amp;gt; \
         &amp;lt;option value='A'&amp;gt;Some&amp;lt;/option&amp;gt; \
         &amp;lt;option value='0'&amp;gt;None&amp;lt;/option&amp;gt; \
     &amp;lt;/select&amp;gt; \
     B &amp;lt;select ng-model='blue'&amp;gt; \
         &amp;lt;option value='F'&amp;gt;Lots&amp;lt;/option&amp;gt; \
         &amp;lt;option value='A'&amp;gt;Some&amp;lt;/option&amp;gt; \
         &amp;lt;option value='0'&amp;gt;None&amp;lt;/option&amp;gt; \
     &amp;lt;/select&amp;gt; \
 &amp;lt;/div&amp;gt;&quot;&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We then have some initialisation - we restrict to ‘E’ for element, assign the template and create an isolate scope. The next bit is where we &lt;code&gt;require &amp;#39;ngModel&amp;#39;&lt;/code&gt;, which gives us all the NgModelController functionality.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; {
      restrict: &lt;span class=&quot;string&quot;&gt;'E'&lt;/span&gt;,
      template: tpl,
      scope: {},
      &lt;span class=&quot;built_in&quot;&gt;require&lt;/span&gt;: &lt;span class=&quot;string&quot;&gt;'ngModel'&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now we have the real meat of the code - the link function with its injected &lt;code&gt;NgModelController&lt;/code&gt; instance &lt;code&gt;ngModelCtrl&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;      link: &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;scope, iElement, iAttrs, ngModelCtrl&lt;/span&gt;) &lt;/span&gt;{
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Inside the link function, we do a bunch of things. Firstly, we set up formatters (which convert the model value to view values):&lt;/p&gt;
&lt;h3 id=&quot;set-up-formatters&quot;&gt;Set up formatters&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;          ngModelCtrl.$formatters.push(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;modelValue&lt;/span&gt;) &lt;/span&gt;{
              &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; colours = modelValue.split(&lt;span class=&quot;string&quot;&gt;''&lt;/span&gt;);
              &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; {
                  red: colours[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],
                  green: colours[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],
                  blue: colours[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;]
              };
          });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Formatters can be a whole chain of functions. We are using just one. All we do is take the &lt;code&gt;$modelValue&lt;/code&gt; - which is the underlying “actual” value within &lt;code&gt;NGModelController&lt;/code&gt; and is a 3 character string - and split it so we have an array of 3 elements &lt;code&gt;[red, green, blue]&lt;/code&gt;. We return these as an object, and they get set on the view value.&lt;/p&gt;
&lt;h3 id=&quot;set-up-render-function&quot;&gt;Set up render function&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;          ngModelCtrl.$render = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;{
              scope.red   = ngModelCtrl.$viewValue.red;
              scope.green = ngModelCtrl.$viewValue.green;
              scope.blue  = ngModelCtrl.$viewValue.blue;
          };
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;$render&lt;/code&gt; function takes the values that are on the &lt;code&gt;$viewValue&lt;/code&gt; of ngModelCtrl and puts them onto the local scope. In other words, it takes the &lt;code&gt;$viewValue&lt;/code&gt; and renders it to the screen. This means that in the directive’s UI we have access to red, green and blue.&lt;/p&gt;
&lt;p&gt;All we are doing here is taking the view value and putting it on the scope variables for access in the HTML template.&lt;/p&gt;
&lt;h3 id=&quot;set-up-a-watch&quot;&gt;Set up a watch&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;          scope.$watch(&lt;span class=&quot;string&quot;&gt;'red + green + blue'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;{
              ngModelCtrl.$setViewValue({
                  red: scope.red,
                  green: scope.green,
                  blue: scope.blue
              });
          });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We are telling the scope to pay attention to the three variables that we have put onto it - red, green and blue. When one of them changes, Angular, in its next digest cycle, will set the view value on the ng model controller, keeping the interface up to date and everything in sync.&lt;/p&gt;
&lt;h3 id=&quot;set-up-parsers-convert-view-value-to-model-value-&quot;&gt;Set up parsers (convert view value to model value)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;
          ngModelCtrl.$parsers.push(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;viewValue&lt;/span&gt;) &lt;/span&gt;{
              &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;'#'&lt;/span&gt; + [viewValue.red, viewValue.green, viewValue.blue].join(&lt;span class=&quot;string&quot;&gt;''&lt;/span&gt;);
          });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://jsfiddle.net/cox0sba1/&quot;&gt;See the code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just like formatters, you can have multiple parsers, and again we’re just using one. All it does is join together the &lt;code&gt;$viewValue&lt;/code&gt;’s &lt;code&gt;[red, green, blue]&lt;/code&gt; array back into a 3 character string.&lt;/p&gt;
&lt;h2 id=&quot;step-by-step-what-is-happening-in-the-colour-picker-&quot;&gt;Step by step - what is happening in the colour picker?&lt;/h2&gt;
&lt;p&gt;Let’s take a look at what is actually going on when we use our &lt;code&gt;colour-picker&lt;/code&gt; directive.&lt;/p&gt;
&lt;h3 id=&quot;when-you-change-one-of-the-select-field-inputs-&quot;&gt;When you change one of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; field inputs…&lt;/h3&gt;
&lt;p&gt;So, when you change any of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; field values, that changes the scope value. Standard angular! This then kicks off a few things:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-1/on-select-change.png&quot; alt=&quot;On changing the select&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The scope value has been changed&lt;/li&gt;
&lt;li&gt;The watch function picks up that something has changed on the scope value&lt;/li&gt;
&lt;li&gt;Watch calls &lt;code&gt;$setViewValue&lt;/code&gt;, which sets the &lt;code&gt;$viewValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Change to &lt;code&gt;$viewValue&lt;/code&gt; sets kicks off the parser chain &lt;code&gt;$parsers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Parser chain updates the underlying &lt;code&gt;$modelValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Some kind of Angular magic happens!&lt;/li&gt;
&lt;li&gt;The real model is updated. Everything in synchronised!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;if-something-changes-the-underlying-value-&quot;&gt;If something changes the underlying value...&lt;/h3&gt;
&lt;p&gt;So what happens if something outside of the directive changes the real value? A chain of events is kicked off which synchronises everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/understanding-ngmodelcontroller-by-example-part-1/underlying-change.png&quot; alt=&quot;On changing the select&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;real model&lt;/strong&gt; is changed outside of &lt;code&gt;NGModelController&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Angular says &amp;quot;hey &lt;code&gt;NGModelController&lt;/code&gt;! The model has updated!&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NGModelController&lt;/code&gt; updates &lt;code&gt;$modelValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;$formatters&lt;/code&gt; chain is be triggered, and converts the &lt;code&gt;$modelValue&lt;/code&gt; to the &lt;code&gt;$viewValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;$viewValue&lt;/code&gt; has been updated by &lt;code&gt;$formatters&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Because the &lt;code&gt;$viewValue&lt;/code&gt; has been updated, the &lt;code&gt;$render&lt;/code&gt; function gets kicked off&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;$render&lt;/code&gt; function updates the &lt;strong&gt;scope values&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;watch&lt;/code&gt; function picks up that something has changed on the scope value&lt;/li&gt;
&lt;li&gt;Watch calls &lt;code&gt;$setViewValue&lt;/code&gt;, which sets the &lt;code&gt;$viewValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Change to &lt;code&gt;$viewValue&lt;/code&gt; sets kicks off the parser chain &lt;code&gt;$parsers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Parser chain updates the underlying &lt;code&gt;$modelValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Some kind of Angular magic happens!&lt;/li&gt;
&lt;li&gt;The real model is updated. Everything in synchronised!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can observe this by adding &lt;code&gt;&amp;lt;input ng-model=&amp;quot;background”&amp;gt;&lt;/code&gt; and changing the value in there and you can see that formatters is kicked off.&lt;/p&gt;
&lt;h2 id=&quot;more-on-the-topic&quot;&gt;More on the topic&lt;/h2&gt;
&lt;p&gt;There is more to NGModelController. In &lt;a href=&quot;http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-2/&quot;&gt;the next article in this series&lt;/a&gt;, we look at validation!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.chroder.com/2014/02/01/using-ngmodelcontroller-with-custom-directives/&quot;&gt;http://www.chroder.com/2014/02/01/using-ngmodelcontroller-with-custom-directives/&lt;/a&gt; - probably the most easy-to-follow article, although there are a few misleading typos to watch out for that had me scratching my head!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.angularjs.org/api/ng/type/ngModel.NgModelController&quot;&gt;https://docs.angularjs.org/api/ng/type/ngModel.NgModelController&lt;/a&gt; - the official docs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;We hope that this article has helped you to get your head around ngModelController! Please let us know if there are any inaccuracies in this article, or how we could make it better!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;/blog/understanding-ngmodelcontroller-by-example-part-2/&quot;&gt;Read part 2!&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>Testing ES6 with Karma, RequireJS, and Angular</title><link>http://radify.io/blog/announcing-karma-es6-shim/</link><pubDate>Wed, 22 Apr 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/announcing-karma-es6-shim/</guid><author></author><description>&lt;p&gt;Well, that’s a lot of tools to list in a blog post title! We have developed a simple plugin for Karma that adds shims for both ES6 and ES5. This allows you to use cutting edge language features, AND be able to unit test it, right now, even if you’re using AMD!&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://npmjs.com/package/karma-es6-shim&quot;&gt;karma-es6-shim on NPM&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can view it at &lt;a href=&quot;https://npmjs.com/package/karma-es6-shim&quot;&gt;npmjs.com/package/karma-es6-shim&lt;/a&gt;. We have also published a sample project that shows how it can be used &lt;a href=&quot;http://radify.io/blog/announcing-karma-es6-shim/github.com/radify/karma-es6-shim-example&quot;&gt;github.com/radify/karma-es6-shim-example&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;so-why-is-this-necessary-&quot;&gt;So why is this necessary?&lt;/h2&gt;
&lt;p&gt;I was recently assigned a small project that was written in ES6 and AngularJS that used AMD modules for module source code. It was a tiny proof of concept, which used &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel (AKA 6to5)&lt;/a&gt; to transpile the ES6 source code in the src directory into outputted ES5 compatible JavaScript in the build directory.&lt;/p&gt;
&lt;p&gt;Even though Babel was used, the code didn’t work in native Chrome without ES6 features switched on. I’d get problems like Object.assign not being a function.  Object.assign is not supplied by default with Babel/6to5 (see &lt;a href=&quot;https://github.com/babel/babel/issues/377&quot;&gt;this link&lt;/a&gt;); It’s part of ES6 that is not fully ratified yet - see &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign&quot;&gt;Mozilla&amp;#39;s Object.assign()&lt;/a&gt; page, which explains why it wasn’t transpiling in, Therefore, in the HTML, an ES6 shim was supplied:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-html&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attribute&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;value&quot;&gt;&quot;https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.22.1/es6-shim.min.js&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;undefined&quot;&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;title&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without this shim, errors would occur; with the shim included, the prototype worked smoothly.&lt;/p&gt;
&lt;p&gt;The first thing I wanted to do was to characterise it with a few unit tests before I started developing it further, so I could be confident I wasn’t breaking anything. I installed Karma with its PhantomJS plugin, but I started getting errors like:&lt;/p&gt;
&lt;p&gt;PhantomJS 1.9.8 (Mac OS X) ERROR
  TypeError: &amp;#39;undefined&amp;#39; is not a function (evaluating &amp;#39;Function.call.bind(String.prototype.indexOf)&amp;#39;)&lt;/p&gt;
&lt;p&gt;After quite a lot of googling, I realised that PhantomJS does not support the entire feature set of ES5 (let alone ES6!). Therefore, I included the &lt;a href=&quot;https://www.npmjs.com/package/karma-es5-shim&quot;&gt;Karma ES5 shim&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;npm install --save karma-es5-shim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in my karma.conf.js I added it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;    frameworks: [&lt;span class=&quot;string&quot;&gt;'jasmine'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'requirejs'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'es5-shim'&lt;/span&gt;],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I was getting the error message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    TypeError: &amp;#39;undefined&amp;#39; is not a function (evaluating &amp;#39;Object.assign(this,this._default)&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, I knew that this meant that I needed the same es6-shim - it was the same error as I got in browser if I removed the es6-shim.&lt;/p&gt;
&lt;p&gt;So, what I did is created my own version of karma-es5-shim that also included es6-shim, naming it &lt;a href=&quot;https://www.npmjs.com/package/karma-es6-shim&quot;&gt;karma-es6-shim&lt;/a&gt;. I installed it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;npm install karma-es6-shim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in my karma.conf.js I updated to the new shim:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;    frameworks: [&lt;span class=&quot;string&quot;&gt;'jasmine'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'requirejs'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'es6-shim'&lt;/span&gt;],
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, my tests started passing in Karma/PhantomJS, AND everything in browser is still working. Hooray!&lt;/p&gt;
&lt;h2 id=&quot;alternatives-to-karma-es6-shim&quot;&gt;Alternatives to karma-es6-shim&lt;/h2&gt;
&lt;p&gt;So, is this the right way to add support for incomplete ES6 features? It works for us with our particular combination of tools, but there are other options…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://babeljs.io/docs/usage/polyfill/&quot;&gt;Babel has a polyfill&lt;/a&gt;, which provides most of the non-finalised features of ES6, including Object.assign. Feeding Babel the optional: [“runtime”] engages these features. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; pipe = gulp.src(src).pipe(babel({ optional: [&lt;span class=&quot;string&quot;&gt;&quot;runtime&quot;&lt;/span&gt;] }));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems, though, that it doesn’t work with RequireJS. &lt;a href=&quot;https://babeljs.io/docs/usage/runtime/&quot;&gt;From the docs&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The package babel-runtime is required for this transformer. Run npm install babel-runtime --save to add it to your current node/webpack/browserify project. babel-runtime does not support AMD module loaders like RequireJS.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Possibly with some massaging, it could be made to work but I didn’t have any success.
Conclusions
ES6 is very much a moving target; as we have seen, even features like Object.assign are not yet set in stone. Our &lt;a href=&quot;https://www.npmjs.com/package/karma-es6-shim&quot;&gt;karma-es6-shim&lt;/a&gt; works for us, for now, to allow us to use same shim in the browser as we use in our unit tests. It’s not as neat as it would be to load the polyfill within Babel, but it’s “good enough” for now!&lt;/p&gt;
&lt;p&gt;Roll on widespread ES6 support!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/babel/babel/issues/377&quot;&gt;https://github.com/babel/babel/issues/377&lt;/a&gt; Why Babel/6to5 does not support Object.assign out of the box&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/michaelbromley/angular-es6&quot;&gt;https://github.com/michaelbromley/angular-es6&lt;/a&gt; - docs for doing Angular in ES6&lt;/li&gt;
&lt;/ul&gt;
</description></item><item><title>Navigating the Minefield of Metrics</title><link>http://radify.io/blog/navigating-the-minefield-of-metrics/</link><pubDate>Fri, 10 Apr 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/navigating-the-minefield-of-metrics/</guid><author></author><description>&lt;p&gt;Values first, numbers second! We need to steer our projects, and to do that we need data.&lt;/p&gt;
&lt;div class=&quot;videoContent&quot;&gt;
    &lt;iframe width=&quot;100%&quot; height=&quot;100%&quot; src=&quot;https://www.youtube.com/embed/mW6Rmo99Wi4&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Here is an &lt;a href=&quot;https://leanpub.com/dealwithit&quot;&gt;excerpt from Gavin&amp;#39;s book&lt;/a&gt; which talks about measurement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Measure things, don&amp;#39;t just use guesswork and &amp;quot;intuition&amp;quot;. If you say to a project manager &amp;quot;I spent 4 hours improving performance&amp;quot; and you don&amp;#39;t give any figures, then you might as well have been playing CounterStrike! … Get into the habit of providing figures whenever possible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This helps us to make rational, informed decisions about our projects. It can, however, be extremely difficult to pick what to measure and how much stock to place in those measurements. In this article, we look at things to bear in mind when defining metrics for software projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We are looking at project-level metrics here. We will consider organisation-level metrics in a future post.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;bad-metrics-the-danger-zone-&quot;&gt;Bad Metrics - The Danger Zone!&lt;/h2&gt;
&lt;p&gt;Ever been in this situation?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/navigating-the-minefield-of-metrics/conversation-cartoon.jpg&quot; alt=&quot;We’ve been in this meeting for 2 hours. What do we track it to?&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;ve ever heard something like this, where people are trying to game metrics, then you might be in the danger zone!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/navigating-the-minefield-of-metrics/dangerzone.jpg&quot; alt=&quot;The Danger Zone&quot;&gt;&lt;br&gt;
&lt;small&gt;&lt;em&gt;(source: quickmeme.com)&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Uh oh! Looks like a case of bad metrics!&lt;/p&gt;
&lt;p&gt;In this example, the budget for the project is tied to the time spent, but it is not being honestly reported. There are many reasons why this may be, but management cannot make informed decisions if the metrics are poorly chosen or inaccurately reported... How has this happened and what can we do to prevent this kind of misuse and gaming of metrics?&lt;/p&gt;
&lt;h2 id=&quot;avoiding-potential-metrics-pitfalls&quot;&gt;Avoiding potential metrics pitfalls&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s take a look at three potential pitfalls of poorly applied metrics and what we can do to avoid these dangers.&lt;/p&gt;
&lt;h3 id=&quot;danger-1-misunderstanding-what-a-metric-is&quot;&gt;Danger 1: misunderstanding what a metric is&lt;/h3&gt;
&lt;aside&gt;
&lt;blockquote&gt;
I would characterize the study of metrics as clues but never answers. If you study enough clues for long enough, you&amp;#39;ll become sensitive to what they&amp;#39;re telling you. There is no hard rule on how many or what they say; watching them and spending effort to understand them is key

- Mark Ovaska
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;Metrics may been seen to be &amp;quot;the thing itself&amp;quot; rather than a measure of something. A thermometer in water does not show the temperature of all the water, rather it shows the temperature at a single point.&lt;/p&gt;
&lt;p&gt;An example misunderstanding is common in agile development. &lt;em&gt;&amp;quot;Oh no, only 20 points got delivered this week, we normally do 40!&amp;quot;&lt;/em&gt;... This does not necessarily mean catastrophe; the estimates could have been off, or someone could have been sick. Points are very useful, but are not &amp;quot;real things&amp;quot;, they&amp;#39;re just used for sizing and planning.&lt;/p&gt;
&lt;h4 id=&quot;preventing-misunderstandings-understand-that-the-measurement-is-not-the-thing-&quot;&gt;Preventing misunderstandings - understand that the measurement is not the thing!&lt;/h4&gt;
&lt;p&gt;Metrics are helpful only so long as it is entirely grasped that a metric is, at best, a view of an aspect of a thing and is NEVER the thing in and of itself. For example, yes, it&amp;#39;s worth paying attention to story points (we pay VERY close attention to them!), but they are not bricks, they are not cement, they are very abstract and we see them for what they are.&lt;/p&gt;
&lt;h4 id=&quot;measurements-metrics-and-kpis&quot;&gt;Measurements, metrics and KPIs&lt;/h4&gt;
&lt;p&gt;Let’s have a look at how we can sensibly approach metrics and define our terms.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/navigating-the-minefield-of-metrics/pyramid-of-measurements.png&quot; alt=&quot;Pyramid of measurements, metrics and KPIs&quot;&gt;&lt;/p&gt;
&lt;p&gt;I want to draw a distinction between &amp;#39;metric&amp;#39; and &amp;#39;measurement&amp;#39;. A measurement is a value over time, and a metric is a measurement with an attached set of decision-making constraints. That is, we can measure stuff, but not all of what we are measuring should be used to guide the project. So, in this pyramid, not all measurements become metrics.&lt;/p&gt;
&lt;p&gt;To help us work out what measurements to use as metrics, one approach is to can measure and track absolutely everything we can, going back as far as possible, then explore the data. See what looks interesting, find unexpected correlations, then try to derive metrics from that.&lt;/p&gt;
&lt;p&gt;The most critical metrics, we can use as KPIs (Key Performance Indicators). These are the things that tell us whether our project is succeeding or failing. We have to pick these incredibly carefully, as we will see later, but when wisely chosen, they can give us a lot of insight into what is going on.&lt;/p&gt;
&lt;p&gt;Approaching it this way means that we don’t get overwhelmed, and we keep in sight what our project-guiding metrics are without getting bogged down in the ones we just record in case they become useful later.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/navigating-the-minefield-of-metrics/venn.png&quot; alt=&quot;A KPI is a metric which is a measurement&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;danger-2-poorly-chosen-metrics&quot;&gt;Danger 2: poorly chosen metrics&lt;/h3&gt;
&lt;aside&gt;
&lt;blockquote&gt;
When metrics are created simply because the data is available, they often bear little connection to organizational objectives
- &lt;a href=&quot;http://www.cutter.com/content-and-analysis/journals-and-reports/cutter-it-journal/sample/itj0604c.html&quot;&gt;Jonathan D. Becher&lt;/a&gt;
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;As we saw in the pyramid, not all measurements may actually be useful. It is important to continuously evaluate - is this metric telling us anything useful? The caution here is not to assume that just because something is recorded, it has value. With that said, something might prove to have value later, so it’s worth recording, just don’t sell the farm based on what a single measurement is telling you.&lt;/p&gt;
&lt;h3 id=&quot;choosing-good-metrics&quot;&gt;Choosing good metrics&lt;/h3&gt;
&lt;p&gt;The metrics should not be the focus of the project; rather they are a way of measuring what is going on and having telemetry into the project. Far more important are the values that drive us - what kind of project are we going to be? What matters to us? What matters to this project?&lt;/p&gt;
&lt;p&gt;For example, on one recent project, Radify worked with the client to define three values that were most important to them, We then implemented metrics against these values. Here are those values:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Predictability&lt;/li&gt;
&lt;li&gt;Continuous feedback&lt;/li&gt;
&lt;li&gt;Quality&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As stated before, we had been measuring everything we could against the application from the outset, and it was therefore quite easy to pick out representative measurements and turn them into metrics. We&amp;#39;re not going to go into huge detail here but here are some of the things we picked:&lt;/p&gt;
&lt;h4 id=&quot;metrics-for-predictability&quot;&gt;Metrics for Predictability&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Track progress against estimates and report back on every sprint&lt;/li&gt;
&lt;li&gt;Expected vs actual velocity&lt;/li&gt;
&lt;li&gt;Scope creep (changes to sprint after start)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;metrics-for-continuous-feedback&quot;&gt;Metrics for Continuous feedback&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Number and timing of deploys&lt;/li&gt;
&lt;li&gt;ApDex, error rate, uptime, CPU, memory and disk utilisation&lt;/li&gt;
&lt;li&gt;Application-specific metrics (e.g. number of orders placed today, number of abandoned orders)&lt;/li&gt;
&lt;li&gt;Continuous integration build results&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;metrics-for-quality&quot;&gt;Metrics for Quality&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Number of bugs in production&lt;/li&gt;
&lt;li&gt;Code coverage&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We then create project dashboards using &lt;a href=&quot;https://www.datadoghq.com/&quot;&gt;DataDog&lt;/a&gt; so we can see at-a-glance what our metrics are telling us. We iterate on these metrics in every sprint retrospective and are always fine-tuning what goes on the dashboard. Hopefully, you can see that we&amp;#39;ve picked metrics based on what is actually important to the project based on what is important to the client.&lt;/p&gt;
&lt;h3 id=&quot;danger-3-badly-applied-metrics-resulting-in-toxic-culture&quot;&gt;Danger 3: badly applied metrics resulting in toxic culture&lt;/h3&gt;
&lt;p&gt;An organisation or project that focuses on metrics with too narrow a gaze runs the risk of poisoning its own culture.&lt;/p&gt;
&lt;p&gt;Where metrics are used individually and narrowly or as a stick to beat people with, this results in people “gaming” the metrics to appear more productive. Humans being humans, we tend to reverse engineer management’s perceived desired outcomes.&lt;/p&gt;
&lt;p&gt;Worse still, toxic metrics can cause serious disenchantment. Toxic KPIs can be particularly harmful as they and can encourage people to focus narrowly on their KPIs to the exclusion of overall cohesion and cooperation (see &lt;a href=&quot;http://gellmannamnesia.blogspot.co.uk/2013/04/kpis-considered-harmful.html&quot;&gt;this article&lt;/a&gt;, for example) . This is why linking metrics to individual reparation and performance reviews is dangerous - many people will pull up the drawbridge and focus on only what is tied to their pay reviews, not what is best for the project as a whole. This might mean that they spend less time helping colleagues or thinking outside the box.&lt;/p&gt;
&lt;p&gt;One of Radify’s &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;main driving principles is &amp;quot;no silos&amp;quot;&lt;/a&gt;, because we want everyone to understand the project as a whole so we really want to avoid toxic metrics.&lt;/p&gt;
&lt;h4 id=&quot;preventing-toxic-culture-think-team-&quot;&gt;Preventing toxic culture - think team!&lt;/h4&gt;
&lt;p&gt;Metrics must NEVER be used as a stick to beat people with.&lt;/p&gt;
&lt;p&gt;Singling people out creates silos as each person looks to their own interests rather than thinking about the project or organisation holistically. Metrics should never be individualized; the project team as a whole improves together or falls behind together. This means that people will feel free to report non-technical metrics honestly and openly because they don’t feel like they will be persecuted for the results!&lt;/p&gt;
&lt;h2 id=&quot;characteristics-of-good-metrics&quot;&gt;Characteristics of good metrics&lt;/h2&gt;
&lt;p&gt;We have seen that bad metrics are poorly understood, badly chosen and toxically applied. Conversely, good metrics have three characteristics:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Well understood:&lt;/strong&gt; the team understands what the metric means and what it is and isn&amp;#39;t telling them. The team understands the relative importance of KPIs and other metrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Well chosen:&lt;/strong&gt; the metric reflects the values of the project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-toxic:&lt;/strong&gt; the metric is applied positively to guide the project, not as a stick to beat people with.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;benefits-of-good-metrics&quot;&gt;Benefits of good metrics&lt;/h2&gt;
&lt;p&gt;The whole company and everything that happens within it can be decomposed into a set of systems. Complex systems are easy to create and hard to understand. The more things we measure and the longer the timeline, the better we understand the system. Eventually, our understanding of the system(s) will be almost intuitive, as the impact of changes will be immediately observable (for varying values of &amp;#39;immediate&amp;#39;, depending on the system). This will allow us to steer our project with greater confidence.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; Well-designed KPIs provide quick insight into trends and summary information, while supporting drill-down into more detailed metrics. This allows an organization to see where it&amp;#39;s doing well and where it requires improvements and/or course adjustments.&lt;br&gt; - &lt;a href=&quot;http://www.cutter.com/content-and-analysis/journals-and-reports/cutter-it-journal/sample/itj0604c.html&quot;&gt;Jonathan D. Becher&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;when-to-use-your-metrics&quot;&gt;When to use your metrics&lt;/h2&gt;
&lt;p&gt;There are two main points at which we use our metrics in a project:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reactively:&lt;/strong&gt; if something goes bad, especially in production, we get notified right away! See &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;Four Principles Of DevOps&lt;/a&gt; and &lt;a href=&quot;http://radify.io/blog/bot-who-cried-wolf/&quot;&gt;The Bot Who Cried Wolf&lt;/a&gt; for details.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proactively:&lt;/strong&gt; we look at our dashboard in every sprint retrospective, and take time to interpret what it is telling us. This allows us to steer what we do. For example, if performance is bad, we may allocate some time in the next sprint to this as a non-functional requirement.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;We hope you’ve found our ideas on metrics thought-provoking. When properly chosen, metrics can be extremely valuable in guiding your project. When poorly chosen or applied, they can be toxic to morale and can give false confidence or misleading information.&lt;/p&gt;
&lt;p&gt;We’ve got a lot more to say on the subject, so if you want to talk, please get in touch! If your organisation needs help getting measurable results, we can help you!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What do you measure? Is it helpful? Have you ever been a victim of toxic metric culture? Were you able to fix it? Let us know in the comments box below!&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Refactoring Repositories</title><link>http://radify.io/blog/refactoring-repositories/</link><pubDate>Fri, 27 Mar 2015 00:00:00 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/refactoring-repositories/</guid><author></author><description>&lt;p&gt;Source code repositories using tools like Git, Subversion or Mercurial are essential to any modern software project and it is important that they are efficiently organised. We recently merged multiple repositories into a single codebase and found it gave us significant efficiency gains. In this article, we take a step back and look at how we should architect our repositories - when we should merge, and when we should draw apart.&lt;/p&gt;
&lt;div class=&quot;videoContent&quot;&gt;
    &lt;iframe width=&quot;100%&quot; height=&quot;100%&quot; src=&quot;https://www.youtube.com/embed/iv2xeWCA_Rw&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;h2 id=&quot;how-we-got-to-this&quot;&gt;How we got to this&lt;/h2&gt;
&lt;p&gt;On a recent project, we were working with four source code repositories:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UI&lt;/li&gt;
&lt;li&gt;API&lt;/li&gt;
&lt;li&gt;Ansible playbook&lt;/li&gt;
&lt;li&gt;Release tool&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Having them being separate was causing us three points of pain:&lt;/p&gt;
&lt;h3 id=&quot;pain-point-1-branch-management&quot;&gt;Pain point 1: branch management&lt;/h3&gt;
&lt;p&gt;We had to keep branches in check across repositories. So, if I created a branch for FEATURE-A, and it had UI and API changes, I had to have a branch in each repo named exactly the same.&lt;/p&gt;
&lt;h3 id=&quot;pain-point-2-difficulty-of-review&quot;&gt;Pain point 2: difficulty of review&lt;/h3&gt;
&lt;p&gt;Multiple &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;pull requests&lt;/a&gt; had to be raised for any user stories which touched more than one part of the system. This led to us having to list dependencies for any given pull request. Therefore, if one pull request for a feature was merged but its dependency was not, the system would be in an inconsistent state.&lt;/p&gt;
&lt;h3 id=&quot;pain-point-3-difficulty-of-automation&quot;&gt;Pain point 3: difficulty of automation&lt;/h3&gt;
&lt;p&gt;We had to do some gymnastics with our automated demo branch deployment. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;UI change detected in branch FEATURE-A
Is there a corresponding API branch FEATURE-A?
    YES
        Deploy UI FEATURE-A and API FEATURE-A
    NO
        Deploy UI FEATURE-A and API MASTER
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It meant, for example, that any changes to our Ansible playbook, which handles all our deployment/provisioning and &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;infrastructure&lt;/a&gt;, were not tied to the corresponding API or UI code, so if a given feature branch required a different package to be installed via Apt, for example, we had to switch the Ansible branch on Jenkins. Not an elegant solution!&lt;/p&gt;
&lt;p&gt;This also led to potential race conditions, whereby multiple builds could kick off together due to pushes to two repos just four seconds apart:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/refactoring-repositories/complexity.png&quot; alt=&quot;Potential race condition&quot;&gt;&lt;/p&gt;
&lt;p&gt;This was a problem because e2e was a single environment and we could not test it in parallel, so this meant we had to create a fairly complex build pipeline with dependencies, or to have some kind of quiet period:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/refactoring-repositories/workflow.png&quot; alt=&quot;Complex deployment pipeline&quot;&gt;&lt;/p&gt;
&lt;p&gt;Furthermore, our release tool was pretty baroque - it had to check out all the other 3 repositories, run some checks, prompt for a tag, merge to production and push. It was only 60 or so lines of node.js code, but it had to be maintained and tested regularly, just like anything else.&lt;/p&gt;
&lt;h2 id=&quot;tackling-it-head-on&quot;&gt;Tackling it head on&lt;/h2&gt;
&lt;p&gt;It was abundantly clear that these repositories were linearly related and that our workflow was being made overly complex by our repository layout. We figured that we could make some gains here.&lt;/p&gt;
&lt;p&gt;Our approach to process and tooling change loosely follows the scientific method - we only change a single process or tool per sprint, then we look into it in our retrospectives. We had identified these pain points and scheduled in some time to investigate merging the repository.&lt;/p&gt;
&lt;p&gt;Once we had merged the repositories into one, we observed three great benefits:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Easier branch management. One feature, one branch!&lt;/li&gt;
&lt;li&gt;Easier reviews. No dependencies! No need to track multiple pull requests against a single Pivotal Tracker story!&lt;/li&gt;
&lt;li&gt;Simpler, faster, more consistent demo environment deployments. We were able to ditch our release tool entirely and strip out dozens of lines from our Ansible playbooks and Jenkins jobs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, in this particular case, we believe we made a good decision to merge our repositories. When is the right time to merge, though? Is it always the answer? Let’s take a step back and look at the general case:&lt;/p&gt;
&lt;h2 id=&quot;to-merge-or-not-to-merge-that-is-the-clich-&quot;&gt;To merge or not to merge? That is the cliché...&lt;/h2&gt;
&lt;p&gt;It’s very tempting to separate an application into separate repositories, particularly if they are being worked upon by separate teams. By combining, however, we may run the risk of reducing our separation of concerns. What goes together and what goes apart is a really important consideration for software developers, and one that merits a great deal of careful consideration!&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;“Software designers win by separating things that can be considered separately, lose by separating things that must be considered together” — Kent Beck&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;h3 id=&quot;repository-smells&quot;&gt;Repository smells&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;http://c2.com/cgi/wiki?CodeSmell&quot;&gt;code smell&lt;/a&gt; is defined on c2.com as &amp;quot;a hint that something is wrong in your code&amp;quot;, and seems to have been coined by Kent Beck. There now exists a whole taxonomy of code smells, which I’d recommend all developers familiarise themselves with. In the light of this, I define a &amp;quot;repository smell&amp;quot; as a similar concept, whereby a repository or multiple repositories of code exhibit similar hints that something is awry.&lt;/p&gt;
&lt;p&gt;I define five repository smells. Two of them should lead us to consider merging code repositories, the other three should lead us to consider drawing code apart into separate repositories.&lt;/p&gt;
&lt;h3 id=&quot;smell-1-high-correlation-in-changes&quot;&gt;Smell 1: High correlation in changes&lt;/h3&gt;
&lt;p&gt;In our case, there was a linear relation between the number of pull requests in our UI and API libraries. In fact, most commits required PRs to both. It therefore made enormous sense to merge them. I’d define this as there being a strong correlation in changes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If components change together and a change to one implies a change to another, consider combining their repositories.&lt;/li&gt;
&lt;li&gt;If you find that you frequently have to make changes in groups across multiple repositories, then perhaps you have a good case for combining them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;smell-2-intellectual-property-dispersal&quot;&gt;Smell 2: Intellectual property dispersal&lt;/h3&gt;
&lt;p&gt;You may have a client that has an application with multiple facets, which may be in separate repositories. It is often easier to manage permissions for third party access in one repository. Also, you are grouping the intellectual property into one place. Having dispersed intellectual property may increase the likelihood of it ending up somewhere it shouldn&amp;#39;t!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If multiple repositories are the intellectual property of a given client and are closely related, consider combining them together.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;smell-3-feature-envy&quot;&gt;Smell 3: Feature envy&lt;/h3&gt;
&lt;p&gt;Much like the &lt;a href=&quot;http://c2.com/cgi/wiki?FeatureEnvySmell&quot;&gt;feature envy code smell&lt;/a&gt;, in OOP, repositories may seem to be overly interested in code from other repositories. This can result in importing a much larger amount of dependency code than is strictly necessary.&lt;/p&gt;
&lt;p&gt;Let’s say, for example, that you have a little tool that your repo uses but you also use it in other projects, and you’re checking out the whole project every time just for this one tool.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you find that an entire repository is checked out just for one small self-contained module, then you likely have a case for it being in its own repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a project is a standalone tool, for instance, I generally advocate having a separate repo with its own documentation, tests and so forth. That way, it’s much better in a “wood for the trees” sense. If a project is a compact, redistributable, standalone tool, then put it in its own repository (and consider open sourcing it as a &lt;a href=&quot;http://radify.io/blog/overachieving-software-projects/&quot;&gt;secondary deliverable&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;smell-4-too-many-eggs-in-one-basket&quot;&gt;Smell 4: Too many eggs in one basket&lt;/h3&gt;
&lt;p&gt;Closely related to code envy, but this is more about looking at the repository as a whole rather than a particular part of it. When areas of a repository are basically unrelated and change at different rates entirely, this may be considered as too many eggs in one basket. For example, you might have multiple tools in one library that aren’t actually related and perform unrelated tasks.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you find that one subtree of a repository changes in isolation to the rest of the repository, you may wish to break it out.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;smell-5-permissions-minefield&quot;&gt;Smell 5: Permissions minefield&lt;/h3&gt;
&lt;p&gt;I once worked for a large organisation that kept all their code in a single repository. This was really taking it too far in my opinion! What that can result in is security issues. You’re essentially either trusting everyone with your entire code tree, or nothing at all, which is not a great degree of granularity! Of course, many tools, such as Subversion, do permit subtree permissions, but this can get scrappy quickly!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you find that you are having to manage granular permissions, it might be a sign that you need to break out a repository into multiple different repositories.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/blog/refactoring-repositories/merge-or-draw-apart.png&quot; alt=&quot;Feature smells and whether they should lead us to considering merging together or drawing apart&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;merging-git-repos&quot;&gt;Merging git repos&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;d like to merge your repositories, a good place to start is &lt;a href=&quot;https://help.github.com/articles/about-git-subtree-merges/&quot;&gt;this article about Git subtree merges&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-word-of-caution&quot;&gt;A Word of Caution&lt;/h2&gt;
&lt;p&gt;Make sure that you don’t use merging to a single repo as a shortcut to making all your components as self-describing and self contained as possible and managing dependencies correctly. It may be a convenience in some cases, but it can also result in your repository becoming chaotic.&lt;/p&gt;
&lt;p&gt;Thanks to package managers like NPM, Composer or Bower, dependency management in 2015 is much less of a nightmare than it used to be. With powerful tools like Git, a bad repository architecture need not be something you need to live with forever.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;As our application was reasonably small, and functioned as a whole, it made a lot of sense to merge it. Sometimes, though, it’s far better to keep things separate, and the guidelines we’ve defined made here should help you to know when.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have you had success or pain from your repository organisation? Can you think of any repository smells we haven’t thought of? Let us know what you think in the comments section below! If you have an unwieldy software project, perhaps we can help you!&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Faster PHP code coverage</title><link>http://radify.io/blog/faster-php-code-coverage/</link><pubDate>Tue, 10 Feb 2015 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/faster-php-code-coverage/</guid><author></author><description>&lt;p&gt;Or how we switched to a powerful new test framework without rewriting any code!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Inspired by both Behaviour Driven Development (BDD) and fluent test libraries like JSpec or RSpec, Kahlan is an exciting new test framework for PHP which allows tight, expressive tests. &lt;a href=&quot;https://github.com/crysalead/kahlan&quot;&gt;Kahlan&lt;/a&gt; allows you to stub or monkey patch your code directly like in Ruby or JavaScript, without needing any PECL extensions!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://github.com/crysalead/kahlan&quot;&gt;Kahlan on Github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make testing faster, easier, and - let’s be honest - more enjoyable, we wanted to switch our &lt;a href=&quot;http://li3.me/&quot;&gt;Li3 (AKA Lithium)&lt;/a&gt; projects to use Kahlan rather than the &lt;a href=&quot;http://li3.me/docs/lithium/test/Unit&quot;&gt;native test utilities&lt;/a&gt;. Rewriting all our tests in a new framework would be crazy; no client is going to pay us to sit there doing that! We therefore decided to keep the existing tests as they were and simply write any new tests in Kahlan. Simple, right? Just one gotcha - how would we merge the code coverage statistics from both the Kahlan and Li3 tests? We needed to see our overall test coverage so that we could see where we needed to improve our testing. To that end, we needed to work out how to run our tests in one go and have the union of the coverage reported. Kahlan author Simon Jaillet got to work on implementing a wrapper!&lt;/p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;The first idea was to create a single spec in the Kahlan environment to encapsulate all existing Li3 legacy tests. The main drawback of this approach is that it would mix both the Li3 &amp;amp; Kahlan console reporting, which was not ideal. Thankfully, the Kahlan workflow is highly configurable and so we decided to run all of our Li3 legacy tests after the Kahlan specs had finished to keep console output clean and the two suites separate. To get coverage of our legacy tests, we needed only to enable the code coverage reporter again during Li3 test execution.&lt;/p&gt;
&lt;p&gt;Here’s how we did it, step by step!&lt;/p&gt;
&lt;h3 id=&quot;step-1-creating-a-custom-config-file&quot;&gt;Step 1: Creating a custom config file&lt;/h3&gt;
&lt;p&gt;Kahlan uses a simple PHP file as config file, so you don’t need to learn any new funky syntax to configure the workflow the way you want. By default, Kahlan looks for a file called kahlan-config.php, so let’s create one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;touch kahlan-config.php
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-2-registering-some-namespaces&quot;&gt;Step 2: Registering some namespaces&lt;/h3&gt;
&lt;p&gt;Kahlan works in tandem with Composer and uses its autoloading mechanism. Unfortunately, we were using a legacy installation of Li3 which uses a dedicated loader and some libraries that were not Composer compatible. So, the second step here was to dynamically add some namespaces and a class map to Composer so that all autoloading was done by Composer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**
 * Adding custom namespaces to Composer
 */&lt;/span&gt;
Filter::register(‘app.namespaces&lt;span class=&quot;string&quot;&gt;', function($chain) {
    // PSR-0
    $this-&amp;gt;_autoloader-&amp;gt;add('&lt;/span&gt;spec\\&lt;span class=&quot;string&quot;&gt;', __DIR__);
    $this-&amp;gt;_autoloader-&amp;gt;add('&lt;/span&gt;lithium\\&lt;span class=&quot;string&quot;&gt;', __DIR__ . '&lt;/span&gt;/libraries&lt;span class=&quot;string&quot;&gt;');

    // PSR-4
    $this-&amp;gt;_autoloader-&amp;gt;addPsr4(app\\'&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt;);

    &lt;span class=&quot;comment&quot;&gt;// PSR-0 Li3 Libraries&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;_autoloader-&amp;gt;add(&lt;span class=&quot;string&quot;&gt;'li3_access\\'&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/libraries'&lt;/span&gt;);
    &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;_autoloader-&amp;gt;add(&lt;span class=&quot;string&quot;&gt;'li3_mailer\\'&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/libraries'&lt;/span&gt;);
    &lt;span class=&quot;comment&quot;&gt;// etc .&lt;/span&gt;

    &lt;span class=&quot;comment&quot;&gt;// AWS class paths&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$awsPath&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/libraries/li3_aws/libraries/aws-sdk-for-php'&lt;/span&gt;;
    &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;_autoloader-&amp;gt;addClassMap([
        &lt;span class=&quot;string&quot;&gt;'AmazonAS'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;variable&quot;&gt;$awsPath&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/services/as.class.php'&lt;/span&gt;,
        &lt;span class=&quot;string&quot;&gt;'AmazonCloudFormation'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;variable&quot;&gt;$awsPath&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/services/cloudformation.class.php'&lt;/span&gt;,
        &lt;span class=&quot;string&quot;&gt;'AmazonCloudFront'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;variable&quot;&gt;$awsPath&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/services/cloudfront.class.php'&lt;/span&gt;,
        &lt;span class=&quot;string&quot;&gt;'AmazonCloudSearch'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;variable&quot;&gt;$awsPath&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/services/cloudsearch.class.php'&lt;/span&gt;,
        &lt;span class=&quot;comment&quot;&gt;// etc.&lt;/span&gt;
    ]);
});


Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'namespaces'&lt;/span&gt;, app.namespaces&lt;span class=&quot;string&quot;&gt;');&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Filter::register()&lt;/code&gt; &amp;amp; &lt;code&gt;Filter::apply()&lt;/code&gt; are the two necessary methods to customize the spec execution workflow. The first one aims to attach an name (in this case, &lt;code&gt;’app.namespaces’&lt;/code&gt;) to a piece of logic (i.e the closure). Once you have registered your logic, you only need to attach it to a workflow entry point (in this case, &lt;code&gt;’namespaces’&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Note: Kahlan doesn’t use an event based approach to customize the execution workflow; rather it uses an AOP (Aspect Oriented Programming) approach. For more information on AOP, check out &lt;a href=&quot;https://github.com/crysalead/filter&quot;&gt;https://github.com/crysalead/filter&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;step-3-configuring-the-coverage-reporter-to-only-scan-a-couple-of-directories&quot;&gt;Step 3: Configuring the coverage reporter to only scan a couple of directories&lt;/h3&gt;
&lt;p&gt;To generate accurate code coverage, we needed to exclude some parts of the tree from being parsed; for example, we don’t need coverage for the &lt;code&gt;tests&lt;/code&gt; folder. So in the same way as we did for namespaces, we provided a filter to customize how the code coverage reporter should be initialized:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;kahlan&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;reporter&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Coverage&lt;/span&gt;;
&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;kahlan&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;reporter&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;coverage&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;driver&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Xdebug&lt;/span&gt;;

&lt;span class=&quot;comment&quot;&gt;/**
 * Initializing a custom coverage reporter
 */&lt;/span&gt;
Filter::register(&lt;span class=&quot;string&quot;&gt;'app.coverage'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;variable&quot;&gt;$reporters&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;reporters();

    &lt;span class=&quot;comment&quot;&gt;// Limit the Coverage analysis to only a couple of directories only&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$coverage&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Coverage([
            &lt;span class=&quot;string&quot;&gt;'verbosity'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;args()-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;),
            &lt;span class=&quot;string&quot;&gt;'driver'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Xdebug(),
            &lt;span class=&quot;string&quot;&gt;'path'&lt;/span&gt; =&amp;gt; [
                &lt;span class=&quot;string&quot;&gt;'controllers'&lt;/span&gt;,
                &lt;span class=&quot;string&quot;&gt;'models'&lt;/span&gt;,
               &lt;span class=&quot;comment&quot;&gt;// etc..&lt;/span&gt;
            ]
    ]);
    &lt;span class=&quot;variable&quot;&gt;$reporters&lt;/span&gt;-&amp;gt;add(&lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$coverage&lt;/span&gt;);

    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$reporters&lt;/span&gt;;
});

Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'app.coverage'&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-4-creating-the-logic-to-run-li3-legacy-tests&quot;&gt;Step 4: Creating the logic to run Li3 legacy tests&lt;/h3&gt;
&lt;p&gt;Once the coverage reporter configured, we needed to reproduce how Li3 tests are executed inside the Li3 test layer. This specific task has been integrated in the &lt;code&gt;$runLi3Suite&lt;/code&gt; closure and &lt;code&gt;$runLegacyTests&lt;/code&gt; just adds some coverage logic around to encapsulate the whole execution of legacy tests to be able to retrieve some code coverage data for these tests:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;lithium&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;console&lt;/span&gt;\&lt;span class=&quot;title&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;ConsoleRequest&lt;/span&gt;;

&lt;span class=&quot;variable&quot;&gt;$runLegacyTests&lt;/span&gt; = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$kahlan&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{


    &lt;span class=&quot;comment&quot;&gt;// If the coverage option is enabled, manually enable it for Li3 tests&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;args()-&amp;gt;exists(&lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;)) {
        &lt;span class=&quot;variable&quot;&gt;$coverage&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;reporters()-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;);
        &lt;span class=&quot;variable&quot;&gt;$coverage&lt;/span&gt;-&amp;gt;before(); &lt;span class=&quot;comment&quot;&gt;// Starts to log coverage&lt;/span&gt;
    }

    &lt;span class=&quot;variable&quot;&gt;$runLi3Suite&lt;/span&gt; = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$path&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
        &lt;span class=&quot;variable&quot;&gt;$test&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Test([
            &lt;span class=&quot;string&quot;&gt;'request'&lt;/span&gt; =&amp;gt; &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; ConsoleRequest([&lt;span class=&quot;string&quot;&gt;'input'&lt;/span&gt; =&amp;gt; fopen(&lt;span class=&quot;string&quot;&gt;'php://temp'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'w+'&lt;/span&gt;)])
        ]);
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$test&lt;/span&gt;-&amp;gt;run(&lt;span class=&quot;variable&quot;&gt;$path&lt;/span&gt;);
    };


    &lt;span class=&quot;comment&quot;&gt;// Run the Li3 `’tests’` suite&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$success&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$runLi3Suite&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;'tests'&lt;/span&gt;);

    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;variable&quot;&gt;$success&lt;/span&gt;) {
        &lt;span class=&quot;keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;Lithium tests failed\n&quot;&lt;/span&gt;;
        &lt;span class=&quot;variable&quot;&gt;$kahlan&lt;/span&gt;-&amp;gt;suite()-&amp;gt;status(-&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;); &lt;span class=&quot;comment&quot;&gt;// Force Kahlan to fail (i.e. exit(-1))&lt;/span&gt;
    }


    &lt;span class=&quot;comment&quot;&gt;// Stop Legacy Code coverage&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;args()-&amp;gt;exists(&lt;span class=&quot;string&quot;&gt;'coverage'&lt;/span&gt;)) {
        &lt;span class=&quot;variable&quot;&gt;$coverage&lt;/span&gt;-&amp;gt;after(); &lt;span class=&quot;comment&quot;&gt;// Stops to log coverage&lt;/span&gt;
    }
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$success&lt;/span&gt;;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-5-creating-the-test-execution-workflow&quot;&gt;Step 5: Creating the test execution workflow&lt;/h3&gt;
&lt;p&gt;This is the final step and actually the most obvious. Here we simply added a filter around the &lt;code&gt;&amp;#39;run&amp;#39;&lt;/code&gt; endpoint which runs all the logic together. In this filter we also added a couple of initializations related to the Li3 framework and declaring a constant which will be checked in the li3 bootstrap file to disable the Li3 built-in autoloader:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**
 * Boostrapping &amp;amp; running the specs
 */&lt;/span&gt;
Filter::register(&lt;span class=&quot;string&quot;&gt;'app.run'&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;)&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$runLegacyTests&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;comment&quot;&gt;// Used to bail out the Li3 autoloader initialization in test environment.&lt;/span&gt;
    &lt;span class=&quot;comment&quot;&gt;// Indeed Composer will do all the job here.&lt;/span&gt;
    define(&lt;span class=&quot;string&quot;&gt;'KAHLAN_ENVIRONMENT'&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;'true'&lt;/span&gt;);

    &lt;span class=&quot;comment&quot;&gt;// Lithium bootstrap file&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;__DIR__&lt;/span&gt; . &lt;span class=&quot;string&quot;&gt;'/config/bootstrap.php'&lt;/span&gt;;

    &lt;span class=&quot;comment&quot;&gt;// Run Kahlan specs&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$result&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$chain&lt;/span&gt;-&amp;gt;next();

    &lt;span class=&quot;comment&quot;&gt;// Run li3 legacy tests&lt;/span&gt;
    &lt;span class=&quot;variable&quot;&gt;$runLegacyTests&lt;/span&gt;(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;);

    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$result&lt;/span&gt;;
});

Filter::apply(&lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;, run, app.run);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-6-adding-a-legacy-option-for-making-the-transition-easier-for-developers&quot;&gt;Step 6: Adding a --legacy option for making the transition easier for developers&lt;/h3&gt;
&lt;p&gt;During development, sometimes we want to run the legacy tests, and sometimes not. Thankfully, Kahlan makes adding custom CLI (Command Line Interface) arguments easy!&lt;/p&gt;
&lt;p&gt;We added a new option, &lt;code&gt;--legacy&lt;/code&gt;, to the command line. If this parameter is supplied, the li3 legacy tests are executed and if not they are simply ignored. We just needed to add at the top of the Kahlan config file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// Adding a, custom option for legacy tests&lt;/span&gt;
&lt;span class=&quot;variable&quot;&gt;$args&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;args();
&lt;span class=&quot;variable&quot;&gt;$args&lt;/span&gt;-&amp;gt;argument(&lt;span class=&quot;string&quot;&gt;'legacy'&lt;/span&gt;, [&lt;span class=&quot;string&quot;&gt;'type'&lt;/span&gt;  =&amp;gt; &lt;span class=&quot;string&quot;&gt;'boolean'&lt;/span&gt;]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then we simply added at the top of the &lt;code&gt;$runLegacyTests&lt;/code&gt; closure:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;variable&quot;&gt;$runLegacyTests&lt;/span&gt; = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$kahlan&lt;/span&gt;)&lt;/span&gt; &lt;/span&gt;{

    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;variable&quot;&gt;$kahlan&lt;/span&gt;-&amp;gt;args()-&amp;gt;get(&lt;span class=&quot;string&quot;&gt;'legacy'&lt;/span&gt;)) {
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;;
    }
    &lt;span class=&quot;comment&quot;&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;This article is not so much about the wrapper to Li3 tests itself, but more to demonstrate that no matter how complex your test setup, Kahlan can be integrated into your workflow.&lt;/p&gt;
&lt;p&gt;Switching to another test framework is not an harmless decision, but we started to use Kahlan a couple of months ago on one of our team’s projects and we already see huge benefits using it. We write specs a lot faster and easier and the created specs are a lot more reader friendly for the rest of the team. Furthermore, being able to focus the code coverage report right on a single class or method provide a new spec writing experience for better code coverage.&lt;/p&gt;
&lt;p&gt;Even though Kahlan requires some extra cycles for “Just In Time” code patching, it actually ends up making our test suite faster overall for 2 main reasons. Firstly, because we were able to rewrite time consuming integration tests to simple unit tests. Secondly, due to the Kahlan code coverage heuristic, we can make builds with code coverage stats an order of magnitude faster.&lt;/p&gt;
&lt;h2 id=&quot;benefits&quot;&gt;Benefits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GREAT SPEEEEEEEED! Both in writing and running tests.&lt;/li&gt;
&lt;li&gt;Coverage stats on every build - we saw 40 minutes come down to 2 minutes!&lt;/li&gt;
&lt;li&gt;No wastage - we didn’t have to throw away or rewrite our old tests!&lt;/li&gt;
&lt;li&gt;Easier test writing with Kahlan&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;get-involved&quot;&gt;Get involved&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/crysalead/kahlan&quot;&gt;Kahlan is open source and MIT licensed&lt;/a&gt;! Feel free to get involved by  using and contributing to this exciting PHP test framework!&lt;/p&gt;
&lt;p&gt;There’s also no reason that Kahlan couldn’t be integrated with tools like Behat or PHPUnit - the sky’s the limit!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have you come up against slow code coverage or test writing? What did you do about it? Let us know below!&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Three Myths of Software, part 3 - The Software Buyer Myth</title><link>http://radify.io/blog/the-three-myths-of-software-3/</link><pubDate>Mon, 02 Feb 2015 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/the-three-myths-of-software-3/</guid><author></author><description>&lt;p&gt;We aren&amp;#39;t a software business, we just rely completely on our custom application.
(This is the third installment of a series on the Three Myths of Software Projects. If you haven’t already, check out &lt;a href=&quot;http://radify.io/blog/the-three-myths-of-software-1/&quot;&gt;Myth #1: The Features are Everything&lt;/a&gt; and &lt;a href=&quot;http://radify.io/blog/the-three-myths-of-software-2/&quot;&gt;Myth #2: The Genius Geek&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;This myth is the most difficult to absorb because it&amp;#39;s easy to look at your software as just one more investment. A business leader might also have a strong perspective on the value of the software in the marketplace. (For example: A taxi company might think of taxi coordination software as being a matter of &lt;em&gt;logistics&lt;/em&gt; and not &lt;em&gt;customer service&lt;/em&gt;.)&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s explore the following scenario: Your custom application (aka software) is complete, and it&amp;#39;s helping your business grow. You find yourself in the middle of another busy day when, suddenly, the application stops working.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Are you still able to service your customers, even if it’s painfully inconvenient?&lt;/li&gt;
&lt;li&gt;Does the outage impact other businesses besides your own?&lt;/li&gt;
&lt;li&gt;Can you call an outside vendor who is completely responsible for restoring service?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you answered no to all these questions, then you are in the software business. This is because your application is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;proprietary&lt;/li&gt;
&lt;li&gt;mission-critical&lt;/li&gt;
&lt;li&gt;supported in-house&lt;/li&gt;
&lt;/ul&gt;
&lt;aside&gt;
&lt;blockquote&gt;being a software company will require an ongoing commitment to development
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;Recognizing that you are in the software business is the first step to becoming competent at managing the ongoing development of your company and software. Once you’ve begun thinking about your software as part of your business and not an expense, you can manage your investment more soundly. How you perceive ongoing expenses should also change because being a software company will require an ongoing commitment to development. As technology changes, you&amp;#39;ll need to constantly maintain your software to ensure compatibility and stability.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have you been affected by any of these myths? Got any of your own? Let us know in the comments below!&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Three Myths of Software, part 2 - The Genius Geek</title><link>http://radify.io/blog/the-three-myths-of-software-2/</link><pubDate>Mon, 26 Jan 2015 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/the-three-myths-of-software-2/</guid><author></author><description>&lt;p&gt;We just need a skilled code-slinger to wrestle this ornery application into shape. Enough talent and this will be easy, right? &lt;/p&gt;
&lt;p&gt;&lt;em&gt;(This is the second installment of a three post series on the Three Myths of Software Projects. If you haven’t already, check out &lt;a href=&quot;http://radify.io/blog/the-three-myths-of-software-1/&quot;&gt;Myth #1: The Features are Everything&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hollywood often projects the stereotype of a genius programmer working alone to create a highly-sophisticated and successful application. That’s a myth, but it&amp;#39;s still attractive: you have a great idea, and you know how it needs to work or work better.  All you really need now is a skilled geek who knows all the technical stuff. Maybe.&lt;/p&gt;
&lt;p&gt;Here are four questions to consider:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Who&amp;#39;s going to manage the project?&lt;/em&gt; Programming and project management are completely different skills. The ability to assess priorities and unexpected developments while ensuring accountability is critical to moving a project forward. A project manager also provides a direct line of communication that won&amp;#39;t interrupt the development work.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;But can&amp;#39;t I manage the project myself?&lt;/em&gt; Unless you or someone in your group is a project manager with technology experience, there is a chance that the most important technical decisions will be made unilaterally by the developer without any input from you. Even the most transparent developer will naturally lean towards familiar technologies and won’t consider the impact to the overall project.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How broad is the technical scope?&lt;/em&gt; There are an increasingly diverse number of options and methodologies available nowadays, each with distinct advantages and disadvantages. A lone developer isn&amp;#39;t as likely to have the breadth of perspective necessary to weigh all of the options. Similarly, a lone developer will have a limited area of specialization. Work made outside his specialty may be of lower quality or more costly due to his learning curve. The larger the project, the more dramatically these issues will impact the project’s success.&lt;br/&gt;&lt;br/&gt;
This applies similarly to architecting the project. It&amp;#39;s very difficult to maintain focus on the architecture while building features. (See &lt;a href=&quot;http://radify.io/blog/the-three-myths-of-software-1/&quot;&gt;Myth #1: The Features are Everything&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How will you find the right developer?&lt;/em&gt; Finding a developer is difficult. It&amp;#39;s even more difficult to find a lone developer who can be trusted with the success of your project. The larger your budget, the more experienced (and independent) your candidates are likely to be.  The opposite is also true: small budgets rarely engage top talent. Even if you&amp;#39;ve answered the previous three questions, striking the right balance of budget, skill and independence is key to ensuring the right developer on the right project.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside&gt;
&lt;blockquote&gt;The reality is that the best innovations are rarely, if ever, created outside of a team dynamic.&lt;/blockquote&gt;&lt;/aside&gt;

&lt;p&gt;Sharing and challenging each other with multiple perspectives, backgrounds, and skills is invaluable to ensuring a strong outcome.&lt;/p&gt;
&lt;p&gt;An interesting resource that documents how this is the case is Walter Isaacson’s &lt;a href=&quot;http://www.amazon.com/dp/147670869X/&quot;&gt;The Innovators&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next up is Myth #3: The Software Buyer Myth.&lt;/strong&gt;&lt;/p&gt;
</description></item><item><title>Three Myths of Software Projects</title><link>http://radify.io/blog/the-three-myths-of-software-1/</link><pubDate>Mon, 19 Jan 2015 00:00:00 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/the-three-myths-of-software-1/</guid><author></author><description>&lt;p&gt;The backstory for most software projects is predictable: A business opportunity is identified, and features are listed that will exploit that opportunity. At some point the list of items starts to take shape as a tool or application. Suddenly you&amp;#39;re staring at a full-blown software project full of ideas and promise but without a clear path to accomplish any of it.&lt;/p&gt;
&lt;p&gt;But first a little background. This is about managing successful development projects, not how to write a program. The difference is that a successful development project will be managed toward a defined and non-technical goal. To be successful at writing a program requires more than the delivery of something technical, which ignores the business goals that prompted the effort in the first place.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;Describing our effort as “managing a successful development project” helps us maintain sight of real success.
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;To look at it differently: If every application is born out of a goal to achieve something, the success or failure of the application should be measured against that initial goal, not simply the delivery of a computer program. Describing our effort as “managing a successful development project” helps us maintain sight of real success.&lt;/p&gt;
&lt;p&gt;We bring this perspective to every conversation, and it helps us recognize when the conversation becomes application-centric instead of success-centric. We&amp;#39;ve identified three of the most common reasons this happens; here is the first of &lt;strong&gt;Three Myths of Software Projects&lt;/strong&gt;:&lt;/p&gt;
&lt;h2 id=&quot;myth-1-the-features-are-everything&quot;&gt;Myth #1: The Features Are Everything&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;If we build all these cool features, we&amp;#39;ll have the best application ever.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Most people can most easily articulate their application as a list of features. At its simplest, this list includes some functions that produce some results.&lt;/p&gt;
&lt;p&gt;A common (and cliché, at this point) example would be a blogging application. We could write that the following features would make a basic blogging application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Admin authentication&lt;/li&gt;
&lt;li&gt;Text editing &amp;amp; styling&lt;/li&gt;
&lt;li&gt;Ability to publish text&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Seems pretty good, right?  If you have these things, you&amp;#39;ll have a blogging application. If you rewrite this list in sentences, then you&amp;#39;ll have what we call stories. (This is part of the &lt;a href=&quot;http://agilemethodology.org/&quot;&gt;Agile&lt;/a&gt; approach to managing software.) These same features rewritten in natural language might look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An admin should be able to log in and change credentials.&lt;/li&gt;
&lt;li&gt;An admin should be able to create, edit, and delete essays.&lt;/li&gt;
&lt;li&gt;An admin should be able to publish essays.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can see how the second list fills in some of the details assumed, but left undescribed, in the first list.   In fact, the first list now seems a bit oversimplified compared to the second list. But this second list isn’t accurate or comprehensive either. This is the trap of The Features Are Everything Myth: A successful application is simply a
 combination of features. No matter how detailed your stories or feature lists are written, your custom application is inherently more complicated.&lt;/p&gt;
&lt;aside&gt;
&lt;blockquote&gt;No matter how detailed your stories or feature lists are written, your custom application is inherently more complicated.
&lt;/blockquote&gt;
&lt;/aside&gt;

&lt;p&gt;The trap of the features list is that they always seem accurate and comprehensive but always turn out later to be vague and oversimplified.&lt;/p&gt;
&lt;p&gt;Before you launch any serious investment, be sure to document the initial goals you were seeking before you began. Those are your success factors and should be compared with the delivered features at regular intervals. If you do this, you’ll have a steady target and will be more likely to achieve measurable success.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://radify.io/blog/the-three-myths-of-software-2/&quot;&gt;Next up is Myth #2: The Genius Geek.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
</description></item><item><title>A Note From The Editor</title><link>http://radify.io/blog/a-note-from-the-editor/</link><pubDate>Thu, 01 Jan 2015 07:47:04 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/a-note-from-the-editor/</guid><author></author><description>&lt;p&gt;I am not much of a relationship expert. My usual advice? That imagined afternoon where you see true love become reality? That’s probably going to stay imagined. I guess that’s not advice, that’s just me playing the odds. If I were to imagine the same scene with just a bit more self-applied cynicism it might turn out closer to a tawdry episode from &amp;quot;&lt;em&gt;Girls&lt;/em&gt;&amp;quot; or &amp;quot;&lt;em&gt;Eastbound and Down&lt;/em&gt;&amp;quot;.  Which would be a lot messier and a lot more sad.&lt;/p&gt;
&lt;p&gt;But like every drama with exposed flesh hanging on end-of-episode hooks, there are promises and triumphs. It is entertainment, after all. Still, even with all the excitement, these tropes eventually fall a little flat. Excitement morphs into morbid curiosity or even loyalty to fictional characters in a stubborn wait for meaningful resolution.   Even that gift of meaningful resolution is eventually reformed into a search for something new. Or, if a promise isn’t completely crushed, maybe it’s a search for an &lt;em&gt;even better triumph&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Searching&lt;/em&gt; is probably the wrong word here, because searching involves finding and finding is actually pretty boring.  It’s presumptuous anyway: the idea that one actually knows exactly what one is looking for.&lt;/p&gt;
&lt;p&gt;To be clear, I’m not talking about that recent &lt;em&gt;Amazon&lt;/em&gt; search for spicy pumpkin seeds. I’m talking about important stuff like: What is it exactly that you do?  Why should it matter? That sort of stuff.&lt;/p&gt;
&lt;p&gt;These are tough questions that everyone knows how to ask but are unprepared to answer for themselves. They are, however, exactly the sort of questions that have dominated the past year here at Radify.  Among the answers? A new logo (Thanks, &lt;a href=&quot;http://joshking.me&quot;&gt;Josh&lt;/a&gt;!), a few shakeups, and so... much... work.&lt;/p&gt;
&lt;p&gt;This web site is really just a small, but pretty accurate taste. I think it represents well our triumphs and our struggles: it’s a beautiful veil of colored pixels concealing so many gray conversations about direction and priorities and strategies.  Tough questions and answers, now artfully represented by flashes of light and color. Thanks to our newest team member, &lt;a href=&quot;http://andrewcanham.com/&quot;&gt;Andrew&lt;/a&gt;, it’s all looking pretty good.&lt;/p&gt;
&lt;p&gt;More than anything, I hope that the website gives a sense of how Radify is different. All of us share a deep excitement for technology and the web and experiences and all the &lt;em&gt;stuff&lt;/em&gt; that allows us to do great work. But these things are the boring and more methodical parts of our work. These are the procedural searches. The fact is, our passion is discovering, and understanding this has been a big part of 2014 for us. Today, at the beginning of a new year, we join together stronger than ever with a common vision of a world where technology grows into a silent servant to human imagination.&lt;/p&gt;
&lt;p&gt;Happy 2015 from Radify.&lt;/p&gt;
</description></item><item><title>Forward-Only Deployments</title><link>http://radify.io/blog/forward-only-deployments/</link><pubDate>Fri, 28 Nov 2014 09:16:01 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/forward-only-deployments/</guid><author></author><description>&lt;p&gt;Any update to a production system is a potential disaster. No matter how hard we try to make things absolutely perfect, errors in production can occur. So, when a problem does occur, what should we do?&lt;/p&gt;
&lt;p&gt;In this document, I define a regression as “a bug that was introduced by a commit” and we will use this term for any problem in production that was caused by a code change.&lt;/p&gt;
&lt;h2 id=&quot;it-s-all-gone-wrong-&quot;&gt;It’s all gone wrong!&lt;/h2&gt;
&lt;p&gt;So you’re maintaining a system for a client. You’re doing &lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;continuous deployment&lt;/a&gt;. You’re using &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;immutable infrastructure&lt;/a&gt;. You’re using &lt;a href=&quot;http://radify.io/blog/immutable-demo-nodes/&quot;&gt;feature branches to demo features&lt;/a&gt; and it’s all going well. Until one day, your &lt;a href=&quot;http://radify.io/blog/bot-who-cried-wolf/&quot;&gt;monitoring system&lt;/a&gt; (or, worse still, your client! See our post &amp;quot;&lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;4 Principles of DevOps&lt;/a&gt;&amp;quot; for info on avoiding your clients being the ones to report bugs) sends you a message “production is down!” Your blood runs cold — what do you do?&lt;/p&gt;
&lt;p&gt;A cursory examination suggests that the problem corresponds to a recent deployment (New Relic, for example, allows you to mark deployments, which is very useful for diagnosing bugs in production). We need to pull the latest code off, and &lt;em&gt;fast&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;We can basically do one of two things when such a regression occurs:&lt;/p&gt;
&lt;h2 id=&quot;option-1-rolling-back&quot;&gt;Option 1: Rolling back&lt;/h2&gt;
&lt;p&gt;When the dreaded production bug occurs, you can simply tell your Continuous Deployment system to push out an old version. Therefore, you’re pushing out the last known good tag.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/forward-only-deployments/option1.png&quot; alt=&quot;Option 1&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-s-wrong-with-option-1-&quot;&gt;What’s wrong with option 1?&lt;/h3&gt;
&lt;p&gt;It might seem good at first, but pushing out an old version creates several problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The system state is &lt;strong&gt;not&lt;/strong&gt; the same as HEAD.&lt;/li&gt;
&lt;li&gt;People can come along and deploy by committing to production, thereby re-breaking it without realising.&lt;/li&gt;
&lt;li&gt;There is a reliance upon person-to-person communication, and everyone is busy and it’s easy to miss things even if we are diligent.&lt;/li&gt;
&lt;li&gt;Requires additional automation - you would require some kind of “deploy old tag” functionality outside your existing deployment mechanism.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;option-2-forward-only&quot;&gt;Option 2: Forward-only&lt;/h2&gt;
&lt;p&gt;Create a reverse merge, commit it, tag it and push it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/forward-only-deployments/option2.png&quot; alt=&quot;Option 2&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, instead of putting an old tag onto production, we have created an additional commit (dd3a) which reverts the breaking commit (998b). This means that we are only ever going forwards. We are only ever using the release tool to push releases. Nothing “magic” is happening.&lt;/p&gt;
&lt;h3 id=&quot;why-am-i-recommending-option-2-&quot;&gt;Why am I recommending option 2?&lt;/h3&gt;
&lt;p&gt;Forward-only means that you’re only deploying whatever is the latest version. It can’t get out of sync. Advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HEAD and deployed code are not out of sync.&lt;/li&gt;
&lt;li&gt;Lower risk of rolling out bad code accidentally. In option 1, you could end up continuing to develop against a broken HEAD.&lt;/li&gt;
&lt;li&gt;Code is in a working state in the repo as well as on the production environment.&lt;/li&gt;
&lt;li&gt;Does not break your existing automation - you don’t need a “special case” to push old tags.&lt;/li&gt;
&lt;li&gt;Works particularly well with &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;immutable infrastructure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;We advocate forward-only deployments for the reasons mentioned above. Obviously, this is for critical production problems only. It’s the simplest, fastest way of getting production back into a working state without compromising repository, automation and development integrity. Of course, you still have to find and fix your problem and re-integrate the changes from the breaking commit, but that’s a separate issue! The purpose of this article is simply to define a strategy to buy you some time while you get things sorted properly.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Do you agree or disagree with our strategy? How do you manage production bugs?&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Immutable Demo Nodes</title><link>http://radify.io/blog/immutable-demo-nodes/</link><pubDate>Fri, 14 Nov 2014 07:42:45 -0500</pubDate><guid isPermaLink="true">http://radify.io/blog/immutable-demo-nodes/</guid><author></author><description>&lt;p&gt;In our recent post “&lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;Reducing Infrustration&lt;/a&gt;”, we described how Radify adopted immutable infrastructure and what the benefits have been. In this post, we talk about how we integrated immutable infrastructure with our &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;feature branch workflow&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;automatically-deploying-feature-branches&quot;&gt;Automatically deploying feature branches&lt;/h2&gt;
&lt;p&gt;A commit to a feature branch are automatically picked up by our Continuous Integration server, Jenkins. If the build passes, then it is automatically deployed via Ansible to a brand new EC2 node and given a CNAME so that it is reachable at {branch}.demo.{client}.{tld}:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/immutable-demo-nodes/workflow.png&quot; alt=&quot;Automated workflow for standing up demo nodes&quot;&gt;&lt;/p&gt;
&lt;p&gt;A developer pushes code to a branch. If it passes the build on Jenkins, an Ansible playbook is kicked off, which:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;stands up a new micro instance based on our &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;Radify base box&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;installs the application&lt;/li&gt;
&lt;li&gt;creates a CNAME&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://radify.io/blog/bot-who-cried-wolf/&quot;&gt;notifies the team&lt;/a&gt; that fresh code is available for testing&lt;/li&gt;
&lt;li&gt;finally, updates our minimalist open source branch manager, &lt;a href=&quot;https://github.com/radify/stationmaster&quot;&gt;StationMaster&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If a commit is made to an existing feature branch, this means that the existing micro node is thrown away and a new one is stood up in its stead with the latest code on it and that all the team know when a feature branch has been successfully updated and deployed.&lt;/p&gt;
&lt;h2 id=&quot;automatically-removing-expired-feature-branches&quot;&gt;Automatically removing expired feature branches&lt;/h2&gt;
&lt;p&gt;It’s important to keep the branch count in check - after all, every node costs money! Therefore, on every commit to any project, we run a script that goes through and checks for any expired branches. If it finds any, it deletes the CNAME,  burns the node, and removes it from StationMaster. Here it is in pseudocode:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FOR EACH branch on demo
    DOES IT still have an active branch?
        YES
            leave it alone
        NO
            delete CNAME {branch}.demo.{client}.{tld}
            terminate node
            remove from StationMaster
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;why-do-this-&quot;&gt;Why do this?&lt;/h2&gt;
&lt;p&gt;For us, this replaced the way we used to work, which was having a medium instance with multiple workspaces on there with an Nginx configuration for each one. This meant that the branches performed well, but there were several problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We couldn’t throw away the node. Because the node was shared, we couldn’t just bin it in the same way as we do with the rest of our infrastructure. This meant we had to keep on top of manual patching.&lt;/li&gt;
&lt;li&gt;Deployment method was not identical to production. See our post, &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;4 Principles of DevOps&lt;/a&gt;, on why this doesn’t match our principles.&lt;/li&gt;
&lt;li&gt;The Nginx config was SLIGHTLY different to accommodate multiple workspaces. Only ever so slightly, but in my experience, we want to be absolutely as close as humanly possible to production.&lt;/li&gt;
&lt;li&gt;Multiple workspaces on the same box makes environment variable configuration impractical, which was restricting us and overcomplicated our Ansible playbook.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So now, we have demo nodes that are handled exactly the same way as production. Great! There are, of course, at least four drawbacks.&lt;/p&gt;
&lt;p&gt;Firstly, performance: micro instances do not perform nearly as well as the others. That said, it’s actually quite good to test your application on smaller hardware than it is targeting, it’s sometimes a useful way of getting an idea of where bottlenecks may be.&lt;/p&gt;
&lt;p&gt;Secondly, they are not behind load balancers in the same way as production nodes are.&lt;/p&gt;
&lt;p&gt;Thirdly, the cost. Micro instances are as cheap as it gets in AWS, but if you have a lot of branches that are long-running, it can mount up. To mitigate this, being disciplined about closing any unused branches is essential.&lt;/p&gt;
&lt;p&gt;Finally, having demo nodes does obviously slightly increase the surface area of your application.&lt;/p&gt;
&lt;h2 id=&quot;benefits-to-the-client&quot;&gt;Benefits to the client&lt;/h2&gt;
&lt;p&gt;All the tools we’ve built to do this are fairly generic, extended slightly per-client. It means that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Features can be tested before integration, meaning the dev team can &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;check one another’s work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Integrations can be tested in an integration branch&lt;/li&gt;
&lt;li&gt;Greater confidence that testing on demo is representative of production&lt;/li&gt;
&lt;li&gt;Full automation - no need for dev team to spend time poking about on boxes&lt;/li&gt;
&lt;li&gt;Ability to quickly push out alternative branches for client A/B testing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-do-you-think-&quot;&gt;What do you think?&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve found that for demonstrating features, these small, cheap, disposable environments are ideal for us. Do you automatically push out feature branches for testing? Would you like to? Not sure where to start? Think it’s a daft idea? Let us know in the comments below or feel free to get in touch with us directly if you&amp;#39;d like some help setting this up!&lt;/p&gt;
</description></item><item><title>Announcing Angular-G11n</title><link>http://radify.io/blog/announcing-angular-g11n/</link><pubDate>Fri, 24 Oct 2014 13:13:07 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/announcing-angular-g11n/</guid><author></author><description>&lt;p&gt;A recent project required powerful yet simple &lt;a href=&quot;https://en.wikipedia.org/wiki/G11n&quot;&gt;G11n&lt;/a&gt; support in AngularJS. It had to be lightweight, easy to use, and to support switching locale on the fly. We also needed to be able to export to and import from CSV so that our client’s translators could quickly and easily add new languages and update existing ones.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;callButton&quot; href=&quot;https://github.com/uor/angular-g11n&quot;&gt;angular-g11n on github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;angular-g11n has the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set up in minutes&lt;/li&gt;
&lt;li&gt;Extremely simple JSON format&lt;/li&gt;
&lt;li&gt;AngularJS service accessible from JavaScript code&lt;/li&gt;
&lt;li&gt;Filter accessible from templates&lt;/li&gt;
&lt;li&gt;Interpolation (e.g. “Hello {{ name }}” can output “Hello Dave”&lt;/li&gt;
&lt;li&gt;Can respond to empty, singular and plural cases (e.g. “no messages”, “one message”, “40 messages”)&lt;/li&gt;
&lt;li&gt;Export to and import from CSV&lt;/li&gt;
&lt;li&gt;On-the-fly language switching&lt;/li&gt;
&lt;li&gt;Complete sample implementation&lt;/li&gt;
&lt;li&gt;You can access G11n from code as well as from the template. So, if you needed to translate something in a service or controller, that&amp;#39;s no problem  - with angular-g11n!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounds good? Head on over to &lt;a href=&quot;https://github.com/uor/angular-g11n&quot;&gt;github.com/uor/angular-g11n&lt;/a&gt; and check it out!&lt;/p&gt;
</description></item><item><title>The Bot Who Cried Wolf</title><link>http://radify.io/blog/bot-who-cried-wolf/</link><pubDate>Fri, 24 Oct 2014 13:13:07 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/bot-who-cried-wolf/</guid><author></author><description>&lt;p&gt;At Radify, we practise Continuous Delivery and have all sorts of tools and processes that support us in this. Many of these tools have notification abilities, and it’s tempting to turn on ALL THE NOTIFICATIONS! Unfortunately, this led to a case of “the Bot who cried wolf”, in that they grew to be ignored, and viewed merely as annoying noise. It’s not so much about crying “wolf” when there is no wolf, rather the bot could be seen as as essentially going to a zoo, standing by the wolf cage, and screaming WOLF! WOLF! THERE’S A WOLF! LOOK! RIGHT THERE IN THE WOLF CAGE! IT’S A WOLF!&lt;/p&gt;
&lt;p&gt;Now, if you were in your local store shopping for carrots, you’d want to know if there was a wolf. At the wolf enclosure in a zoo, not so much. The bot is dumb, though, and by default it just screams at every wolf it sees. How can we make this bot smarter without discouraging it and making it cry? After all, it exists to alert us of wolves...&lt;/p&gt;
&lt;h2 id=&quot;it-was-getting-crazy-up-in-here&quot;&gt;It was getting crazy up in here&lt;/h2&gt;
&lt;p&gt;Before we started addressing our notification strategy, a typical merge to master could trigger the following barrage notifications in our IRC channel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Github: HEY I GOT A COMMIT, U JELLY?&lt;/li&gt;
&lt;li&gt;Pivotal Tracker: THIS IS RELEVANT TO MY INTERESTS, AH YES, THIS IS SOMETHING ON THIS HERE TICKET, IS IT NOT?&lt;/li&gt;
&lt;li&gt;Jenkins: I’m starting a build!&lt;/li&gt;
&lt;li&gt;Jenkins: AWWW YIS this commit is now all UP IN MY PIPELINE… I’m starting a build!&lt;/li&gt;
&lt;li&gt;Jenkins: OK it’s fixed now, good work, and now I’m pushing it out to dev via Ansible! Bet you can’t wait!&lt;/li&gt;
&lt;li&gt;Jenkins: I’ve deployed code to dev!&lt;/li&gt;
&lt;li&gt;Github: This has been merged!&lt;/li&gt;
&lt;li&gt;Pivotal: I am updated as well!&lt;/li&gt;
&lt;li&gt;Jenkins: RIGHT! Time to deploy to staging!&lt;/li&gt;
&lt;li&gt;Jenkins: … OK it’s deployed to staging!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Noise annoys and this was way too much! This meant that important messages were getting lost amongst the chatter of the bots. It’s pretty tempting to simply turn on ALL THE MESSAGES, but is that really a good idea? This made us think; what’s actually a USEFUL notification?&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-best-policy-&quot;&gt;What is the best policy?&lt;/h2&gt;
&lt;p&gt;One thing we realized is that, quite often, notifications became a proxy for things that we wanted to know the status of; information that our other tools did not readily present us with. One example: the build status of in-development branches. Notifications are a transient medium, which makes them a poor fit for persistent information, like the status of something. Resolving this was one of the driving forces behind the creation of &lt;a href=&quot;https://github.com/radify/stationmaster&quot;&gt;StationMaster&lt;/a&gt;, our branch status tool (as promised, we’ll talk more about StationMaster in an upcoming post).&lt;/p&gt;
&lt;p&gt;After some consideration, our notification policy came to be; “if you receive a notification, it should be for (a) something that you need to do something about, OR (b) it should be letting you know that something important has happened that, if questioned upon, you should be aware of”. Otherwise, we have too much wolf-crying!&lt;/p&gt;
&lt;p&gt;Once we’d discussed our strategy, we centralised our notifications into Leeroy (which is what I, and probably a thousand other devs, named our Jenkins IRC bot). Only Leeroy (and occasionally Pivotal) speaks in the channel now. Other notifications come via email or pull request build statuses in Github fed back from Jenkins - that way, only the people involved have to see them, others are not distracted, and the channels become less noisy. Here are the notifications that we commonly use:&lt;/p&gt;
&lt;h2 id=&quot;team-notifications&quot;&gt;Team notifications&lt;/h2&gt;
&lt;p&gt;These are notifications that go to the entire team. These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New code on demo! We auto-deploy each feature branch so that it can be tested by manual QA (see our post “&lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;Four Principles of DevOps&lt;/a&gt;” for more on our workflow).&lt;/li&gt;
&lt;li&gt;Something has been merged to staging and deployed!&lt;/li&gt;
&lt;li&gt;A release to production is about to happen! Everyone pay attention! When we do a release to a customer, everyone in that project’s channel should be aware.&lt;/li&gt;
&lt;li&gt;Build failure of releases. No release should be partial or incomplete due to our policy of &lt;a href=&quot;http://radify.io/blog/reducing-infrustration/&quot;&gt;immutable infrastructure&lt;/a&gt; for our API and UI nodes.&lt;/li&gt;
&lt;li&gt;A new release went out. Phew!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these are of relevance to two or more members of each project team.&lt;/p&gt;
&lt;h2 id=&quot;direct-to-user-notifications&quot;&gt;Direct to user notifications&lt;/h2&gt;
&lt;p&gt;These are notifications that only go to the person who they are of interest to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Email of build failure/fixed. We generally use feature branches for development - Alice doesn’t need to know if Bob broke the build. Therefore, only Bob gets broken build notifications for builds that Bob broke. Alice (and the rest of the team) don’t need to know about what’s going on with that feature branch until Bob is ready to merge it.&lt;/li&gt;
&lt;li&gt;Pull request builder. So, if a pull request build fails, only the people involved need to know about it. If, however, a release is in progress and fails, everyone on the team needs to know, because that’s headline news (due to our immutable infrastructure policy, if it does fail, nothing will happen from the client’s perspective, but the dev team definitely need to jump to attention!).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;notify-us-&quot;&gt;Notify us!&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;What is your organisation’s notification strategy? How do you balance signal and noise? What are the weaknesses in our approach? Let us know in the box below!&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Reducing Infrustration</title><link>http://radify.io/blog/reducing-infrustration/</link><pubDate>Fri, 03 Oct 2014 09:22:54 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/reducing-infrustration/</guid><author></author><description>&lt;p&gt;Radify recently adopted an immutable infrastructure approach for our web and API nodes. In this article, we talk about what it is, why we did it, and what the costs and benefits have been.&lt;/p&gt;
&lt;h2 id=&quot;what-is-immutable-infrastructure-&quot;&gt;What is immutable infrastructure?&lt;/h2&gt;
&lt;p&gt;Immutable infrastructure, or an immutable deployment, is where infrastructure never changes - it is simply completely replaced wholesale when a deployment happens. It is an attempt to control the amount and location of state in a system. Instead of the historical pattern of having a group of servers and maintaining them over time, with immutable infrastructure you stand up new servers on every deploy. You then install your application on them, add them to the load balancer, then remove the old ones and destroy them. You can achieve rapid results by having a custom base box, which you provision in advance, so  that only your code needs to be deployed.&lt;/p&gt;
&lt;h2 id=&quot;why-use-immutable-infrastructure-&quot;&gt;Why use immutable infrastructure?&lt;/h2&gt;
&lt;p&gt;I’ll be honest, part of the initial impetus was to be part of the &amp;quot;cool gang&amp;quot;. All the other kids are doing it, why not us? Initially, several objections raised themselves. Foremost amongst these was, and I could be wrong, but it seems to me that a lot of the people who talk about immutable infrastructure are fairly large, high traffic, product-based organisations. Was immutable infrastructure out of our reach as a relatively lean agile software consultancy? And is it necessary? Most of our projects are B2B client projects — we’re certainly some way from “Netflix traffic”!&lt;/p&gt;
&lt;p&gt;The more we discussed it, however, the more sense it made. We had a strong build pipeline already (described briefly in &lt;a href=&quot;http://radify.io/blog/four-principles-of-devops/&quot;&gt;4 Principles of DevOps&lt;/a&gt;), but we were finding that the packages on our servers were getting out of date. Our projects have at least 5 stages (local development, test/demo, end to end testing, staging and production) and each stage has 1..n nodes – so although we’re not exactly talking Facebook numbers, updating these servers could be a pain. Small example: updating them via apt over Ansible worked okay most of the time, but occasionally servers would require reboots, and we would have had to stagger those… it just became a lot of hassle. Heartbleed was a couple of hours spent patching and testing that we didn’t want to go through again.&lt;/p&gt;
&lt;p&gt;There were other issues with having to maintain running nodes. They could get out of sync – if, for example, we stood up a new node and added it to a cluster, perhaps the new node may have a newer version of a given library? This never caused us any problems, but potentially, it could have done. It’s best to have every node in a cluster be utterly identical, otherwise debugging can become non-deterministic.&lt;/p&gt;
&lt;p&gt;Immutable infrastructure means that we can simply stand up a new set of nodes every time, and these will be provisioned with the latest packages from the get-go and to have each environment be in a known state, so it seemed to us that it was worth investigating!&lt;/p&gt;
&lt;h2 id=&quot;telling-the-story&quot;&gt;Telling the story&lt;/h2&gt;
&lt;p&gt;I ran some tests and initially a full provisioning of one node for a particular client from a bare bones Ubuntu LTS AMI (Amazon Machine Image) took nearly 15 minutes. This diagram shows a greatly simplified version of this (I haven’t listed everything we install, just some examples):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/reducing-infrustration/before.png&quot; alt=&quot;Old, single-playbook solution&quot;&gt;&lt;/p&gt;
&lt;p&gt;We initially evaluated &lt;a href=&quot;http://www.packer.io/&quot;&gt;Packer&lt;/a&gt; for this project, but it didn’t really seem to give us anything that our existing tooling wasn’t already giving us. I didn’t like that it used a local Ansible, which installed rather more dependencies than I would have liked. So, we decided to refactor our existing playbook to take out the common stuff that is the same or similar between clients and create a radify-base-box playbook which builds an AMI. We update this AMI nightly to make sure that it’s always ready to go with the latest security fixes and so forth. Then, applying the client’s playbook took only two or three minutes per node. The diagram below shows this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/reducing-infrustration/after.png&quot; alt=&quot;New custom base-box solution&quot;&gt;&lt;/p&gt;
&lt;p&gt;This solved our issue of slow deployments, and also allowed us to have a common base image across similar projects which is consistently configured. If we make some key change, we can even do that cross-project. We are also able to use this base playbook with our Jenkins cluster, which is also provisioned by Ansible, so that we have the very same infrastructure across the board. Pretty nifty!&lt;/p&gt;
&lt;h2 id=&quot;benefits-and-challenges&quot;&gt;Benefits and challenges&lt;/h2&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Encourages you to log &amp;quot;off box&amp;quot; - we use &lt;a href=&quot;https://papertrailapp.com/&quot;&gt;PaperTrail&lt;/a&gt; for this&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Far less time spent babysitting servers. This is the &amp;quot;treat servers like cattle, not like pets&amp;quot; approach. If a server goes nuts, we have its logs, and we can simply burn and replace it immediately with zero downtime.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Insulated from the risk of an external dependency being down. For example, if we install some node modules on our base box, this protects us from NPM having issues. Updating our base box periodically means that even if it’s down for some time, we are not far behind the latest patches.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevents the temptation to &amp;quot;hand hack&amp;quot; servers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Boxes are in a known state and have the latest security patches&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disks can’t fill up with logs etc&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistent infrastructure cross-project&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No real change to the cost - unused nodes are destroyed shortly after they are removed from the load balancers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Massive reduction in the amount of playbook code. Lots of red lines in the &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;pull request&lt;/a&gt;! A couple of examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The playbook that updated the code but not the environment? Gone!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The playbook that updated the dependencies? Gone!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;challenges&quot;&gt;Challenges&lt;/h3&gt;
&lt;p&gt;There are various challenges with immutable infrastructure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Time spent working on automation. I think that this work has great value to Radify as a business, and to our clients, but nothing comes for free. I spent perhaps 3 days setting this up, plus our team’s time reviewing it and several meetings discussing it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some people may be uncomfortable with the concept of disposability in services.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;http://12factor.net/&quot;&gt;12 Factor&lt;/a&gt; approach isn’t for everyone - it certainly has its critics - but for us we have found it makes things clean and the moving parts don’t grind together and throw springs all over the place. Adopting immutable infrastructure has been a big step along this road for us.&lt;/p&gt;
&lt;p&gt;Not having to worry maintaining nodes has been something of an administrative weight off our collective shoulders. What’s really quite encouraging is that we have been able to do this despite being a fairly small team.&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;p&gt;To get two very different perspectives on immutable infrastructure, I recommend these three articles:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For:&lt;/strong&gt; &amp;quot;Trash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Components&amp;quot; - &lt;a href=&quot;http://chadfowler.com/blog/2013/06/23/immutable-deployments/&quot;&gt;Chad Fowler&lt;/a&gt; makes the case for Immutable Infrastructure. &lt;a href=&quot;http://blog.codeship.io/2014/07/22/immutable-infrastructure.html&quot;&gt;Flo from CodeShip&lt;/a&gt; also puts the case forward very clearly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Against:&lt;/strong&gt; &amp;quot;Immutable Infrastructure: Practical or Not?&amp;quot; - the counter argument from the folks at &lt;a href=&quot;http://www.getchef.com/blog/2014/06/23/immutable-infrastructure-practical-or-not/&quot;&gt;Chef&lt;/a&gt;. It’s always worth trying to understand the other opposing perspective.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So, what do you think? Do you use immutable infrastructure? Would you like to? Do you think it’s a good thing?&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>4 Principles of DevOps</title><link>http://radify.io/blog/four-principles-of-devops/</link><pubDate>Wed, 02 Jul 2014 12:02:47 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/four-principles-of-devops/</guid><author></author><description>&lt;p&gt;There are lots of misconceptions about “DevOps”. Some people think it’s a set of tools (e.g. “Puppet is our DevOps tool”). Others think it’s a role in the organisation (e.g. “Charlie does our DevOps”). It’s neither of those things - I suppose I’d describe DevOps as a way of thinking. At Radify, we work from 4 principles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Holistic system thinking&lt;/li&gt;
&lt;li&gt;No silos&lt;/li&gt;
&lt;li&gt;Rapid, useful feedback&lt;/li&gt;
&lt;li&gt;Automate drudgery away&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this article, we look at these principles one at a time, demonstrating how they drive our process, tooling and workflow.&lt;/p&gt;
&lt;h2 id=&quot;principle-1-of-4-holistic-system-thinking&quot;&gt;Principle 1 of 4: Holistic system thinking&lt;/h2&gt;
&lt;p&gt;Holistic system thinking simply means thinking about the whole system – in fact, the whole project and the ecosystem around it. It is the opposite of thinking just about “my little bit”.&lt;/p&gt;
&lt;p&gt;As a coder, it is often tempting to try to solve all problems with code. Got a problem? Throw code at it until it goes away! For a long time as a developer, my only tool was the sledgehammer of code, even when the nails were actually screws. Or rawl plugs, whatever they are – you get the picture. As I matured and learned from the people around me, I realised that many problems were not, in fact, code problems at all.&lt;/p&gt;
&lt;h3 id=&quot;defining-the-problem-space&quot;&gt;Defining the problem space&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/blog/four-principles-of-devops/problem-space.png&quot; alt=&quot;Problem space&quot;&gt;&lt;/p&gt;
&lt;p&gt;This Venn diagram shows the total space of problems that we encounter day-to-day (orange). The green is the ones that code is the right answer to. The red is problems that you can solve with code but you really shouldn’t. As Lemmy put it - &lt;em&gt;”just ‘cos you got the power, that don’t mean you got the right”&lt;/em&gt;! The rest of the space is problems that must be solved by non-code means.&lt;/p&gt;
&lt;p&gt;There are all sorts of ways of solving our problems. Here are a few examples:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In code&lt;/li&gt;
&lt;li&gt;At the database layer&lt;/li&gt;
&lt;li&gt;In operations - e.g. adding more hardware, switching our service providers&lt;/li&gt;
&lt;li&gt;Communication - some problems can be solved simply by talking&lt;/li&gt;
&lt;li&gt;Writing a quick and dirty one-off script&lt;/li&gt;
&lt;li&gt;Outsourcing to a dedicated service or company&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Holistic system thinking is about, as a member of an organisation, being able to think about how that problem can be solved in as many ways as possible, and taking into consideration every aspect of the product, the customer, the infrastructure and so forth.&lt;/p&gt;
&lt;h3 id=&quot;how-we-apply-holistic-system-thinking&quot;&gt;How we apply holistic system thinking&lt;/h3&gt;
&lt;h4 id=&quot;thinking-outside-of-code&quot;&gt;Thinking outside of code&lt;/h4&gt;
&lt;p&gt;A lot of problems can be solved without “doing any work”. For example, if a customer comes to us with a requirement, we don’t immediately go into “heads down, writing code” mode. There are often other solutions - as a tech company, you are hired for your expertise. Sometimes, it’s simply a training issue, or perhaps there is a workaround that can save months of work. The temptation to write code for everything is one that plagues all of us, but it’s rarely the only solution.&lt;/p&gt;
&lt;p&gt;Holistic system thinking allows us to say things like “we don’t necessarily need to fix this performance issue in code. That could take us days. We can simply add more nodes in EC2 for the time being for a few dollars a day”. That’s not to say that is always the right approach, but it’s important to look at each problem and try to assess the approximate cost of addressing it head-on and whether there are other ways of resolving it.&lt;/p&gt;
&lt;p&gt;Some problems can be solved with a quick-and-dirty one off script. Others need a carefully architected system. Knowing the difference is very difficult, there are no hard and fast rules, but at least having the option to think about the whole system, the hardware it runs on, and the client you are serving gives you a lot more options! This can make you faster, leaner and more profitable.&lt;/p&gt;
&lt;h4 id=&quot;asking-for-help-&quot;&gt;Asking for ... help?!&lt;/h4&gt;
&lt;p&gt;Never be too proud to ask for help. That is in no way a weakness! In this age of service oriented architectures, outsourcing to specialist services can be a massive time saver, and can result in more secure and stable solutions. Furthermore, it is often prudent to bring in a consultant for short periods. A long period with a consultant can create unhealthy dependencies, but in the short term, it can give a project a great boost.&lt;/p&gt;
&lt;h2 id=&quot;principle-2-no-silos&quot;&gt;Principle 2: No Silos&lt;/h2&gt;
&lt;p&gt;A silo is the way of thinking that says “this is my little bit, I’m responsible for just this little bit”. Silos are destructive; they lead to territorial behaviour, break down team cohesion, and in extreme cases, can slow development to an absolute crawl. One of the main concepts of DevOps is to break down the “wall” between devs and operations - so it’s no longer about developers “throwing code over the wall” to be deployed by systems administrators. We take it further than that - for us, it’s also about breaking down walls between dev, marketing and graphic design - as many roles as possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;KPIs (Key Performance Indicators) are one of the very worst causes of silos, be very careful if you’re using them. They can cause people to focus on a narrow objective to the huge detriment of the organisation at large. In fact, my personal opinion is that they are utterly poisonous, although perhaps I go too far in this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;how-we-apply-no-silos&quot;&gt;How we apply no silos&lt;/h3&gt;
&lt;p&gt;There are a few facets of our workflow that I will highlight to show how we use the principle of no silos.&lt;/p&gt;
&lt;h4 id=&quot;pull-request-workflow&quot;&gt;Pull request workflow&lt;/h4&gt;
&lt;p&gt;Our &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;pull request workflow&lt;/a&gt; helps us to share information. It gives the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A second set of eyes.&lt;/strong&gt; I’ve lost count of the number of times I’ve solved a problem, and somebody has reviewed it and pointed out a subtle flaw, or perhaps a way I could solve it more elegantly. This results in a much cleaner codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowledge sharing.&lt;/strong&gt; Say Alice writes a feature, and Bob reviews it. This means that Bob has at least SOME idea of what Alice’s feature does and how it works. Should Alice be vapourised by marauding space pirates, the cost to the business is slightly less.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Less ego in programming.&lt;/strong&gt; I have to be egoless, and accept the feedback of my peers. One’s natural inclination to take feedback as criticism can be set aside, and this is healthy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;anyone-can-deploy&quot;&gt;Anyone can deploy&lt;/h4&gt;
&lt;p&gt;One of the main silos can be a “release person” who has to do the release every time. This can cause changes to stack up. We prefer to have the approach that no-one should be afraid to trigger a deployment and it should be easy. We should have confidence in our code as it has gone through so many feedback loops before it can get near production (tying in to &lt;strong&gt;automate away the drudgery&lt;/strong&gt; and &lt;strong&gt;rapid, useful feedback&lt;/strong&gt;).&lt;/p&gt;
&lt;h4 id=&quot;regular-communication&quot;&gt;Regular communication&lt;/h4&gt;
&lt;p&gt;We want everyone on our team to &lt;a href=&quot;http://radify.io/blog/overachieving-software-projects/&quot;&gt;share knowledge&lt;/a&gt;. We hold daily standup meetings and exchange ideas and questions.&lt;/p&gt;
&lt;h4 id=&quot;writing-documentation&quot;&gt;Writing documentation&lt;/h4&gt;
&lt;p&gt;Documentation is absolutely a deliverable. This comes in the form of working code and tests first and foremost, but a “runbook” style README.md that tells you how to, for example, install, start, and stop an application, and where the logs are, is incredibly useful. Common gotchas should be listed in there also. Any time anyone asks me a question, that’s generally a prompt for me to document something.&lt;/p&gt;
&lt;h2 id=&quot;principle-3-rapid-useful-feedback&quot;&gt;Principle 3: Rapid, useful feedback&lt;/h2&gt;
&lt;p&gt;We want to know about problems before our customer does. We want as few problems as possible to make it into production, and if a problem DOES reach production, we want to have the right telemetry in place to be able to diagnose it rapidly.&lt;/p&gt;
&lt;p&gt;We adopt a ‘defense in depth’ approach - each phase of our workflow has feedback built into it.&lt;/p&gt;
&lt;h3 id=&quot;how-we-apply-rapid-useful-feedback&quot;&gt;How we apply rapid, useful feedback&lt;/h3&gt;
&lt;h4 id=&quot;automated-feedback&quot;&gt;Automated feedback&lt;/h4&gt;
&lt;p&gt;On our local workspaces, we write code and tests and implement features. This is the tight feedback loop that Kent Beck describes in his book “Test-Driven Development”. Once we’re happy with our work, we push it up to a feature branch.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/four-principles-of-devops/auto-workflow.png&quot; alt=&quot;Automation workflow&quot;&gt;&lt;/p&gt;
&lt;p&gt;The feature branch is automatically tested with all the unit and integration tests, plus static analysis and whatever other tools we are using. If all that passes, then end to end (e2e) tests are run. If these are OK, then a deployment is triggered to a shared dev workspace that can be tested. We have an in-house tool called StationMaster which provides a list of these workspaces and when they were updated, as well as allowing us to remove stale branches.&lt;/p&gt;
&lt;p&gt;At this point, it’s been tested by all our automation (tying into &lt;strong&gt;automate away drudgery&lt;/strong&gt;) and it’s ready for manual testing!&lt;/p&gt;
&lt;h4 id=&quot;manual-feedback&quot;&gt;Manual feedback&lt;/h4&gt;
&lt;p&gt;Here is our manual feedback loop:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/perfect-pull-requests/pull-request-workflow.png&quot; alt=&quot;Manual workflow&quot;&gt;&lt;/p&gt;
&lt;p&gt;This loop only kicks in if all the automation has passed; we don’t waste our time reviewing anything that hasn’t passed our tests already. The shared branch that is deployed via StationMaster can be clicked through to straight away by the person reviewing the pull request. This ties closely into no silos as it shares knowledge and improves our confidence in our work. See my &lt;a href=&quot;http://radify.io/blog/perfect-pull-requests/&quot;&gt;blog post about how we do pull requests&lt;/a&gt; for more information on this.&lt;/p&gt;
&lt;p&gt;The merge to master operation is simply clicking the pull request merge button once the reviewer is happy. This automatically deploys to staging. At this point, the features are shown to the customer, giving us even more useful feedback! If it’s OK in staging, the feature can be merged to production and out it goes into the wild!&lt;/p&gt;
&lt;h4 id=&quot;feedback-from-beyond-production&quot;&gt;Feedback from beyond production&lt;/h4&gt;
&lt;p&gt;So that takes us up to production - however, once our code is “in the wild”, we still need to know what’s going on! We need to know things like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How is the application performing?&lt;/li&gt;
&lt;li&gt;Are errors being thrown?&lt;/li&gt;
&lt;li&gt;Are any nodes down?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The idea is that we get rapid and useful feedback beyond our development cycle.  We use all sorts of tools to gain telemetry on our applications, including:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Log aggregation.&lt;/strong&gt; If you’ve ever had to go log diving, you’ll know what a nightmare it can be if your app scales across multiple nodes. We use Papertrail to aggregate logs from multiple web servers in a nice, searchable web interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server monitoring.&lt;/strong&gt; You never want your customer to be the one telling you there are performance problems! We have monitoring running on all our nodes. We use Pingdom, NewRelic and the AWS alerting service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack trace reporting.&lt;/strong&gt; If there is a code level bug, you want to know about it before your customer does. We use NewRelic for this.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The tools you use may be different; we re-evaluate our tools all the time. It’s the principle of getting rapid, useful feedback that is important!&lt;/p&gt;
&lt;h4 id=&quot;non-technical-feedback&quot;&gt;Non-technical feedback&lt;/h4&gt;
&lt;p&gt;How are we working as a team? Is our strategy effective? Are we making good use of our time? These are all useful questions to ask. We hold regular sprint planning and retrospectives as well as discussion meetings on company strategy.&lt;/p&gt;
&lt;h2 id=&quot;principle-4-automate-drudgery-away&quot;&gt;Principle 4: Automate drudgery away&lt;/h2&gt;
&lt;p&gt;I often describe this as “constructive laziness”, which is a cheeky way of saying that our time is precious - it’s vital that we do not squander it! Humans are very good at innovation, problem solving and creativity. Conversely, we are utterly dreadful at drudging, repetitive, tedious tasks. Therefore, automation is key!&lt;/p&gt;
&lt;p&gt;We’ve talked about getting &lt;strong&gt;rapid useful feedback&lt;/strong&gt; and you may have noticed that there is a lot of automation. Tools are great, but the important thing is that we are not doing anything manually that we can automate - our brains are amazing things but they are not machines. It’s best to use our time to solve interesting problems and be creative, rather than grinding through things like deployments.&lt;/p&gt;
&lt;h3 id=&quot;how-we-automate-drudgery-away&quot;&gt;How we automate drudgery away&lt;/h3&gt;
&lt;h4 id=&quot;representative-environments-throughout-our-pipeline&quot;&gt;Representative environments throughout our pipeline&lt;/h4&gt;
&lt;p&gt;It’s really important that, when developing a system, our development environments are as representative of the production environment as possible. Therefore, we provision all our development environments using the very same Ansible playbook that provisions our test, feature demo, staging and production environments. Therefore, at every stage of the pipeline, there’s one less thing that can go wrong - one less chance for the the “it works on my machine!” bomb to go off!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/four-principles-of-devops/environments.png&quot; alt=&quot;5 environments configured by the same playbook&quot;&gt;&lt;/p&gt;
&lt;p&gt;This diagram shows some of the environments we would typically use on a project, and shows that they are all provisioned identically. This allows us to have confidence that the application we produce will behave the same on production as on our local dev environment. This ties closely into &lt;strong&gt;holistic system thinking&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;workflow&quot;&gt;Workflow&lt;/h4&gt;
&lt;p&gt;Here is a diagram summarizing some of our automation:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/four-principles-of-devops/tech-flow.png&quot; alt=&quot;Flow of technology&quot;&gt;&lt;/p&gt;
&lt;p&gt;Notice that CodeShip uses Ansible to automatically provision environments and run tests, static analysis and run deployments. It’s all set up so that we use the most standard tools that we can, to try to keep it as open and transparent as possible (tying into &lt;strong&gt;no silos&lt;/strong&gt;). Much of the &lt;strong&gt;feedback&lt;/strong&gt; we talked about earlier comes to us through automation. Our process for standing up new nodes is automated. This frees us up to work on more interesting problems!&lt;/p&gt;
&lt;h2 id=&quot;our-advice&quot;&gt;Our advice&lt;/h2&gt;
&lt;p&gt;You may have noticed that all our principles relate to one another; there’s a huge amount of overlap:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/four-principles-of-devops/venn.png&quot; alt=&quot;Example pull request&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s all part of one picture; whilst we love technology, we are not “technology driven”, in that it’s not about the tools - the tools are an implementation detail. It’s about what you want to achieve, and what your values are. Figure out what’s important to your organisation - we suggest you work from principles rather than “we need to use Ansible” or whatever. This way, you can always improve, always move forward, and you don’t become narrow and entrenched.&lt;/p&gt;
&lt;p&gt;Once you’ve got your principles - in effect, your vision for the organisation - implement goals step-by-step; you don’t have to do it all overnight. If you’re operating from principles, rather than strictly defined regiments, you can be flexible and try things, see what works. It’s about reducing the cost of failure, and more than that, it’s about failing as fast as possible, identifying what isn’t working, and improving.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Want help with your organisation’s operations? Got a vision that you don’t know how to carry out? Get in touch with us!&lt;/p&gt;
&lt;/blockquote&gt;
</description></item><item><title>Perfect Pull Requests</title><link>http://radify.io/blog/perfect-pull-requests/</link><pubDate>Mon, 23 Jun 2014 08:40:22 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/perfect-pull-requests/</guid><author></author><description>&lt;h2 id=&quot;what-would-you-want-to-read-&quot;&gt;What would you want to read?&lt;/h2&gt;
&lt;p&gt;At Radify, we use a whole battery of automation to test our work. This is great and it helps us to keep our quality high. It’s not the whole story, though - manual feedback is just as vital as automated feedback! As such, pull requests are a really useful part of our workflow.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/blog/perfect-pull-requests/pull-request-workflow.png&quot; alt=&quot;Example pull request&quot;&gt;&lt;/p&gt;
&lt;p&gt;This diagram shows how we operate. A developer writes a feature, and pushes it to a feature branch, which is automatically deployed to a dev URL for testing (more on this in a subsequent post). Another developer reviews and merges this code.&lt;/p&gt;
&lt;p&gt;This is nothing new, of course, and lots of companies adopt this paradigm, because it gives the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A second set of eyes. I’ve lost count of the number of times I’ve solved a problem, and somebody has reviewed it and pointed out a subtle flaw, or perhaps a way I could solve it more elegantly. This results in a much cleaner codebase.&lt;/li&gt;
&lt;li&gt;Knowledge sharing. Say Alice writes a feature, and Bob reviews it. This means that Bob has at least SOME idea of what Alice’s feature does and how it works. Should Alice be vapourised by marauding space pirates, the cost to the business is slightly less.&lt;/li&gt;
&lt;li&gt;Less ego in programming. I have to be egoless, and accept the feedback of my peers. One’s natural inclination to take feedback as criticism can be set aside, and this is healthy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;writing-a-good-pull-request&quot;&gt;Writing a good pull request&lt;/h2&gt;
&lt;p&gt;So, what makes a GOOD pull request? Well, the way I think about it is; “what would I want to know if I were reviewing someone else’s pull request?”. Here are what I think the characteristics of a good pull request are:&lt;/p&gt;
&lt;h3 id=&quot;1-includes-unit-integration-tests&quot;&gt;1. Includes unit/integration tests&lt;/h3&gt;
&lt;p&gt;Tests show the code executing. Submitting a pull request with no unit tests does not demonstrate how the code has been used, or how the developer is thinking. Unit tests are a whole&lt;/p&gt;
&lt;h3 id=&quot;2-references-a-ticket&quot;&gt;2. References a ticket&lt;/h3&gt;
&lt;p&gt;A pull request must, in some way, link to your issue tracker. There should pretty much always be a ticket that you attach your work to. This gives you increased visibility in your workflow. You should use a commit message format like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[#187412] Implement the flux capacitor

* Add the Y shaped shiny thing
* Tests demonstrating hooking the shiny thing into the drivey thing
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this instance, [#187412] is our issue tracker number. Most issue trackers like Pivotal or Jira can hook into Github to update tickets automatically, so your work is visible to your team and even to your customers; they can see “hey, Amy has finished the flux capacitor story and it’s ready for review”.&lt;/p&gt;
&lt;p&gt;You might also wish to use &lt;a href=&quot;http://radify.io/blog/git-microformats-metrics/&quot;&gt;microformats in your commit message&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id=&quot;3-is-neatly-squashed-into-a-single-commit&quot;&gt;3. Is neatly squashed into a single commit&lt;/h3&gt;
&lt;p&gt;If it’s only you working on branch by yourself, then consider squashing before committing. A tidy history is much easier to work with than sporadic features, it has the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All the changes for a single feature are grouped together&lt;/li&gt;
&lt;li&gt;A commit can be reverted wholesale if there’s a problem, rather than piecemeal&lt;/li&gt;
&lt;li&gt;Much easier to search history&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s seldom a good idea to rebase a shared branch, but on your own branches, be hygienic and &lt;a href=&quot;https://help.github.com/articles/about-git-rebase&quot;&gt;squash things&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id=&quot;4-is-not-created-until-all-automated-tests-pass&quot;&gt;4. Is not created until all automated tests pass&lt;/h3&gt;
&lt;p&gt;A pull request should only be submitted once a feature has passed your static analysis, unit tests, end to end tests and whatever else you have in your pipeline.&lt;/p&gt;
&lt;h3 id=&quot;5-has-a-comprehensive-description&quot;&gt;5. Has a comprehensive description&lt;/h3&gt;
&lt;p&gt;As well as having automated tests, a good pull request should list the steps to test a feature. I generally use the following format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Title: [#4321521] Implement the territories interface

# Description

* Add an interface for maintaining territories
* Tests for territories interface and model updates

# Dependencies

* Relies upon myotherproject/pulls/42

# Screenshots

(screenshots go here)

# Test script

* Log into http://4321521-territories-interface.dev.ourcompany.com using admin credentials
* Click on ‘admin’
* Click on ‘territories’
* Make sure you can remove a territory, and that this causes an XHR that deletes the territory from the API
* Make sure you can add a new territory, verify in the database
* Make sure you can edit a territory, verify in the database
* Check that you can’t create a blank territory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Firstly, we have a &lt;strong&gt;description&lt;/strong&gt;. This is likely to be taken from your commit that you’ve squashed down to.&lt;/p&gt;
&lt;p&gt;Then, &lt;strong&gt;dependencies&lt;/strong&gt; is a list of any other pull requests this one relies upon - for example, you may have separate projects for your API, UI and provisioning scripts, so cross- reference them here to prevent things from getting out of sync.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Screenshots&lt;/strong&gt; are optional but they give people an at-a-glance visual - often, if things look dreadful, or something is clearly wrong, it saves a lot of time if the reviewer can see that from a screenshot.&lt;/p&gt;
&lt;p&gt;Finally, I include a &lt;strong&gt;test script&lt;/strong&gt;. You might have user stories that already have acceptance criteria; if that’s the case, then simply link to them. Sometimes, though, you don’t have that, so it’s really helpful if you show your test script here. Think of it this way - if you’re trying to review someone else’s work in a part of the system that you know nothing about, would you even know how to test it? It can save time and confusion to list steps here.&lt;/p&gt;
&lt;h2 id=&quot;for-example-&quot;&gt;For example...&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/blog/perfect-pull-requests/pull-request-example.png&quot; alt=&quot;Example pull request&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;get-your-coat-&quot;&gt;Get your coat...&lt;/h2&gt;
&lt;p&gt;So, that’s how I think when I construct a pull request - “in the reviewer’s shoes, what would I want to know?”. Sometimes this can be a bit over the top but generally it takes me less than two minutes to craft my pull request. I think that it can save my colleagues a lot of time if I structure it in this way.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So, what do you think? Do you use a pull request workflow? What kind of information do you include in yours?&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Git, Microformats and Metrics</title><link>http://radify.io/blog/git-microformats-metrics/</link><pubDate>Tue, 10 Jun 2014 10:05:05 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/git-microformats-metrics/</guid><author></author><description>&lt;p&gt;Wouldn’t it be useful to know, project-by-project and over time, how much time your team is spending on finding and fixing bugs? It could sure make for some pretty graphs and visualisations!&lt;/p&gt;
&lt;p&gt;This article shows you how to use microformats in your Git commit messages to gather useful and interesting metrics on your software projects.&lt;/p&gt;
&lt;h2 id=&quot;why-gather-metrics-&quot;&gt;Why gather metrics?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Determine how much time spent finding and fixing bugs.&lt;/strong&gt; You may think your team are working on features most of the time, only to be shown that actually they are spending most of their hours firefighting! If this is the case, it’s better to know rather than carry on regardless.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Track differential over time.&lt;/strong&gt;  Do bugs get quicker to find as the team grow more familiar with the client’s business aims and codebase? Are things taking longer and longer to diagnose and fix? This could be a sign that you need to stop and address technical debt. In our particular case, we have developed some hypotheses about tooling and methodologies to support isolating and identifying defects, and we want to test their effectiveness over time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatable&lt;/strong&gt; — it’s not a great deal of effort. If this information could be useful in the future, then now is a good time to start at least recording it!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;defining-a-microformat&quot;&gt;Defining a microformat&lt;/h2&gt;
&lt;p&gt;Many tools already support a commit message format you’re likely familiar with: using &lt;code&gt;[#Numeric ID]&lt;/code&gt; to reference a ticket or issue, as employed by Trac, GitHub, PivotalTracker and others.&lt;/p&gt;
&lt;p&gt;When tracking your own data, you should use a format that’s easily parseable by humans and machines, and is easily distinguishable from normal commit message content.&lt;/p&gt;
&lt;p&gt;For ease of use and consistency, we decided on the following format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Fix pagination bug

Pagination was causing a buffer overflow by repeatedly hammering the server for every page in parallel rather than requesting a page at once.

Added test that verifies that this no longer occurs and counts the number of requests made.

ttc:2
ttf:1.5
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, all we have is &lt;code&gt;ttc:{number of hours to the nearest 0.5}{newline}ttf:{number of hours to the nearest 0.5}&lt;/code&gt;. Very short and simple! There are just two fields: &lt;code&gt;ttc&lt;/code&gt; is Time To Cause and &lt;code&gt;ttf&lt;/code&gt; is Time To Fix. So, TTC is how long it took to work out exactly what the problem was, and TTF how long it took to fix. TTF may include things like writing a test to prevent regressions.&lt;/p&gt;
&lt;p&gt;Of course, these things are not hard and fast. There’s little point setting a stopwatch - we’re not pretending that this is a precise science. That’s why we’re only going to a half hour level of precision. It it’s less than 15 minutes, then just put 0, it will all average out.&lt;/p&gt;
&lt;p&gt;TTC and TTF are exclusive periods of time - so in this example, the engineer spent 2 hours finding and 1.5 hours fixing, for a total of 3.5 hours spent.&lt;/p&gt;
&lt;h2 id=&quot;collating-the-results&quot;&gt;Collating the results&lt;/h2&gt;
&lt;p&gt;Now that your commit messages are being properly annotated, it’s time to extract the raw data. Fortunately, GitHub makes this very easy by allowing web hooks to be attached to a repository and receive commit data on every push. If you’ve ever tinkered with GitHub’s hooks system, you know the structure of that data looks something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;ref&amp;quot;: &amp;quot;refs/heads/master&amp;quot;,
  /* ... */
  &amp;quot;commits&amp;quot;: [
    {
      &amp;quot;id&amp;quot;: &amp;quot;33eb08ab524a6b8dc962aa3a4be62a313730b34f&amp;quot;,
      &amp;quot;distinct&amp;quot;: true,
      &amp;quot;Fix pagination bug\n\nPagination was causing a buffer...&amp;quot; // ...
      &amp;quot;timestamp&amp;quot;: &amp;quot;2014-05-27T18:40:37-04:00&amp;quot;,
      &amp;quot;author&amp;quot;: {
        &amp;quot;name&amp;quot;: &amp;quot;Nate Abele&amp;quot;,
        &amp;quot;email&amp;quot;: &amp;quot;nate@radify.io&amp;quot;,
        &amp;quot;username&amp;quot;: &amp;quot;nateabele&amp;quot;
      },
      /* ... */
    }
  ],
  /* ... */
  &amp;quot;repository&amp;quot;: {
    /* ... */
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the hook is set up, it can iterate through each push’s commit data, pattern-matching on the &lt;code&gt;message&lt;/code&gt; field, like so: &lt;code&gt;/^TT[CF]:?\s*([0-9]*\.?[0-9]+?)$/img&lt;/code&gt;. Once parsed, the results may be stored in a database for later analysis.&lt;/p&gt;
&lt;h2 id=&quot;difficulties&quot;&gt;Difficulties&lt;/h2&gt;
&lt;p&gt;While straightforward, this technique is not without some caveats. For example, if you’re working out an issue across disparate components in a multi-repository system, it may be difficult to analyse the problem in aggregate.&lt;/p&gt;
&lt;p&gt;Further, critical bugs may require immediate fixes, even if only partial, with a final fix to be implemented at a later date. Other bugs, even after identifying the supposed root cause and adding regression tests accordingly, simply refuse to die.&lt;/p&gt;
&lt;p&gt;Accurately measuring the impact of these issues, while possible, requires higher-level analysis, involving integration with, and careful tending of an issue-tracking system.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;I always get a bit suspicious of code metrics. Whilst you can have categories of bugs, every problem is very much it’s own thing. It’s vital to understand that any trends and patterns that you observe are in the broadest of strokes only — take every case on its own merits. Be aware that in comparing projects you may well be comparing apples and oranges. And, more critically, if you start using metrics as a tool to beat engineers over the head, then you fail management in the worst way!&lt;/p&gt;
&lt;p&gt;Dire warnings against their abuse aside, metrics are the thing that stands between your team and &amp;quot;blind&amp;quot; development. “Gut feel” will only take you so far; if you don’t have any insight into what you’re doing and whether it’s being successful, how do you know if you’re improving?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Do you use metrics in your software projects? Have they been helpful? How do you measure technical debt?&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>Interfaces - the misunderstood concept</title><link>http://radify.io/blog/interfaces-the-misunderstood-concept/</link><pubDate>Wed, 28 May 2014 05:05:32 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/interfaces-the-misunderstood-concept/</guid><author></author><description>&lt;p&gt;In a &lt;a href=&quot;http://radify.io/blog/type-hinting-in-php-good-or-bad-practice/&quot;&gt;previous post&lt;/a&gt;, we talked about the existing relationship between type hinting and interfaces, and the fact that type hinting can lead to overuse of interfaces.&lt;/p&gt;
&lt;p&gt;In this post, we&amp;#39;re are going to explain where and when interfaces can be useful (outside of the type hinting concerns) in PHP.&lt;/p&gt;
&lt;p&gt;In statically typed languages, interfaces are first used to make different classes interchangeable without breaking type safety. But this is not the property we are concerned about because PHP is a dynamically typed language so this issue doesn&amp;#39;t apply (well expect if you are using type hinting).&lt;/p&gt;
&lt;p&gt;But interfaces are also an alternative to multiple inheritance because, in general, multiple inheritance creates more problems than it solves (e.g the &lt;a href=&quot;http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem&quot;&gt;diamond problem&lt;/a&gt;). Moreover, when you are looking to multiple inheritance to solve a problem, most of the time the solution is to not use multiple inheritance at all! Indeed, you should always consider composition of features before you think about inheritance. For example, a &lt;code&gt;Car&lt;/code&gt; doesn&amp;#39;t need to extend &lt;code&gt;Engine&lt;/code&gt; and &lt;code&gt;Wheels&lt;/code&gt; classes! In this case, having a &lt;code&gt;Car&lt;/code&gt; which &lt;em&gt;contains&lt;/em&gt; an &lt;code&gt;Engine&lt;/code&gt; instance and 4 &lt;code&gt;Wheel&lt;/code&gt; instances makes a far more sense.&lt;/p&gt;
&lt;p&gt;Languages like Java or C# preferred to use the interface concept instead of multiple inheritance and this is also the way chosen by PHP.&lt;/p&gt;
&lt;h2 id=&quot;are-interfaces-are-equivalent-to-multiple-inheritance-&quot;&gt;Are interfaces are &amp;quot;equivalent&amp;quot; to multiple inheritance ?&lt;/h2&gt;
&lt;p&gt;No. They&amp;#39;re two different concepts, although both allow attaching &amp;quot;things&amp;quot; to classes, where &amp;quot;things&amp;quot; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multiple parent classes (for multiple inheritance)&lt;/li&gt;
&lt;li&gt;contracts (for interfaces)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To simplify: an interface is a kind of type (like an integer, a float or whatever) but if it&amp;#39;s too abstract for you, just see interfaces as a way to attach &amp;quot;contracts&amp;quot; to classes.&lt;/p&gt;
&lt;p&gt;For example if a &lt;code&gt;Car&lt;/code&gt; class implements a &lt;code&gt;Vehicle&lt;/code&gt; interface, it only means that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Car&lt;/code&gt; is assured to have implemented all &lt;code&gt;Vehicle&lt;/code&gt;&amp;#39;s methods&lt;/li&gt;
&lt;li&gt;you can use &lt;code&gt;instanceof&lt;/code&gt; to verify that an instance implements the &lt;code&gt;Vehicle&lt;/code&gt; &amp;quot;contract&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-interfaces-and-multiple-inheritance-both-solves-&quot;&gt;What interfaces and multiple inheritance both solves ?&lt;/h2&gt;
&lt;p&gt;When you are writing business logic, you may need be able to manage some conditional behavior based on the type of an instance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;variable&quot;&gt;$instance&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;instanceof&lt;/span&gt; Countable) {
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;variable&quot;&gt;$instance&lt;/span&gt;-&amp;gt;count();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above example, if &lt;code&gt;Countable&lt;/code&gt; is a class name it can be problematic. Indeed if &lt;code&gt;$instance&lt;/code&gt; is an instance of a class &lt;code&gt;A&lt;/code&gt; which extends a class &lt;code&gt;B&lt;/code&gt;, &lt;code&gt;$instance&lt;/code&gt; won&amp;#39;t be able to also extend a &lt;code&gt;Countable&lt;/code&gt; class. However if &lt;code&gt;Countable&lt;/code&gt; is an interface, the problem disappear.&lt;/p&gt;
&lt;h2 id=&quot;when-should-i-use-interfaces-&quot;&gt;When should I use interfaces?&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ll explain this on piece of code found in the &lt;a href=&quot;https://github.com/zendframework/zf2/blob/6af0efa9555024b0416fef7d67910a829f968f72/library/Zend/Db/Sql/Select.php#L599-608&quot;&gt;Zend Framework 2&lt;/a&gt; (apologies to the author).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;comment&quot;&gt;/**
 * Process the select part
 *
 * &lt;span class=&quot;doctag&quot;&gt;@param&lt;/span&gt; PlatformInterface $platform
 * &lt;span class=&quot;doctag&quot;&gt;@param&lt;/span&gt; DriverInterface $driver
 * &lt;span class=&quot;doctag&quot;&gt;@param&lt;/span&gt; ParameterContainer $parameterContainer
 * &lt;span class=&quot;doctag&quot;&gt;@return&lt;/span&gt; null|array
 */&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;processSelect&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(PlatformInterface &lt;span class=&quot;variable&quot;&gt;$platform&lt;/span&gt;, DriverInterface &lt;span class=&quot;variable&quot;&gt;$driver&lt;/span&gt; = null, ParameterContainer &lt;span class=&quot;variable&quot;&gt;$parameterContainer&lt;/span&gt; = null)&lt;/span&gt;
&lt;/span&gt;{
    ...
        &lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;table;
    ...
        &lt;span class=&quot;comment&quot;&gt;// create quoted table name to use in columns processinga        if ($table instanceof TableIdentifier) {&lt;/span&gt;
            &lt;span class=&quot;keyword&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$schema&lt;/span&gt;) = &lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt;-&amp;gt;getTableAndSchema();
        }

        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;instanceof&lt;/span&gt; Select) {
            &lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt; = &lt;span class=&quot;string&quot;&gt;'('&lt;/span&gt; . &lt;span class=&quot;variable&quot;&gt;$this&lt;/span&gt;-&amp;gt;processSubselect(&lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$platform&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$driver&lt;/span&gt;, &lt;span class=&quot;variable&quot;&gt;$parameterContainer&lt;/span&gt;) . &lt;span class=&quot;string&quot;&gt;')'&lt;/span&gt;;
        } &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; {
            &lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt; = &lt;span class=&quot;variable&quot;&gt;$platform&lt;/span&gt;-&amp;gt;quoteIdentifier(&lt;span class=&quot;variable&quot;&gt;$table&lt;/span&gt;);
        }
    ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;People often use interfaces in method declarations (where they can be of little value), but miss the opportunity to use them in strategic places! In the above piece of code, all &lt;code&gt;instanceof&lt;/code&gt; statements should have been applied on interfaces instead of a class name. Indeed, if your class already extends another parent class, you won&amp;#39;t be able to use your class implementation with the above piece of code!&lt;/p&gt;
&lt;p&gt;In conclusion, interfaces in dynamic languages should not be thrown around indiscriminately. The fact that &amp;quot;type hinting&amp;quot; seems to be a practice adopted by many frameworks and libraries tends to lead to interface abuse, and creates problems which never needed to exist!&lt;/p&gt;
&lt;p&gt;So, if you want to make you life easier, just avoid type hinting and use interfaces only when they really add value!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PS&lt;/strong&gt;: For those who are using some dependency injection system based on a DI container which introspects the code using the PHP reflection layer to extract the &amp;quot;type hint&amp;quot; of methods parameters to automatically inject instances of the correct type, I think simpler approaches need to be considered here.&lt;/p&gt;
</description></item><item><title>Type Hinting in PHP - Good or Bad Practice?</title><link>http://radify.io/blog/type-hinting-in-php-good-or-bad-practice/</link><pubDate>Thu, 22 May 2014 03:18:46 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/type-hinting-in-php-good-or-bad-practice/</guid><author></author><description>&lt;p&gt;PHP 5 introduced a way to write method declarations which has become somewhat en-vogue. You may have noticed the following syntax in a number of open source projects:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;myFunction&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(SomeClass &lt;span class=&quot;variable&quot;&gt;$instance&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This declaration forces the passed parameter to be an instance of &lt;code&gt;SomeClass&lt;/code&gt;, and is called type hinting.&lt;/p&gt;
&lt;p&gt;The fact that PHP only supports single inheritance can be problematic since with such type hinting, you won&amp;#39;t be able to use your own class implementation if it already inherits from another parent class.&lt;/p&gt;
&lt;p&gt;A solution to this issue is to apply type hinting on interfaces instead, like the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;myfunction&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(SomeInterface &lt;span class=&quot;variable&quot;&gt;$instance&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now your class only needs to implements the required interface and you are good to go. However, there&amp;#39;s still a drawback. If you want to override a type hinted method, you won&amp;#39;t be able to change the type hint definition, which limits the overriding capabilities. Worst since polymorphism (a.k.a overloading) is not available for PHP things generaly leads to a proliferation of method names for a same task (e.g. &lt;code&gt;stuffWithCollectionInterface()/stuffWithArray()&lt;/code&gt; instead of a unique &lt;code&gt;stuff()&lt;/code&gt; method). And since &lt;code&gt;array&lt;/code&gt; doesn&amp;#39;t implement the &lt;code&gt;Traversable&lt;/code&gt; interface, using &lt;code&gt;array&lt;/code&gt; as a type hint is like type hinting using a class name instead of an interface.&lt;/p&gt;
&lt;p&gt;But PHP is a dynamic language, so you can avoid all this issues by simply writing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-php&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;myfunction&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;variable&quot;&gt;$instance&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty confusing, right?&lt;/p&gt;
&lt;h2 id=&quot;so-what-does-that-really-mean-&quot;&gt;So what does that really mean?&lt;/h2&gt;
&lt;p&gt;The above example only demonstrates that instead of adding some flexibility to the code, type hinting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;forces developers to create interfaces for almost everything to keep a correct level of interoperability with other developers&lt;/li&gt;
&lt;li&gt;limits overriding capabilities&lt;/li&gt;
&lt;li&gt;tends to complexify API by introducing a lot of irrevelant method names&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main point to understand here is that type hinting is not really a feature like traits (PHP 5.4) or generators (PHP 5.5) but more like a &lt;strong&gt;property of statically-typed languages&lt;/strong&gt;. Since PHP is a dynamic language, using type hinting makes it less &amp;quot;dynamic&amp;quot;. So, to &amp;#39;neutralize&amp;#39; the type hinting issue, interfaces are mandatory almost everywhere.&lt;/p&gt;
&lt;h2 id=&quot;why-do-so-many-people-use-type-hinting-in-php-&quot;&gt;Why do so many people use type hinting in PHP?&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve no clear answer to this question but I guess it&amp;#39;s probably the result of some Java developpers influence who tends to code in PHP like they did in Java. In Java for example some Dependency Injection techniques are based on code introspection.  So the &amp;quot;type hint&amp;quot; is used for being able to automatically inject some instances of the correct type in the called method. But the fact that a technique works for a statically typed languages doesn&amp;#39;t means it&amp;#39;s the best option for a dynamically typed language too.&lt;/p&gt;
&lt;p&gt;Some people using type hinting often argue that it enhances the &amp;quot;degree of confidence that your code works&amp;quot; because  a method will only accept parameters which respect a &amp;quot;contract&amp;quot;. So type hinting somehow produces some &amp;quot;better&amp;quot; code with &amp;quot;fewer&amp;quot; bugs.&lt;/p&gt;
&lt;p&gt;This reminds me of an &lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=4639&quot;&gt;old post&lt;/a&gt;, where the author eventually found that static type checking was redundant with TDD. Please take a moment to read it. Personally, I had a similar life experience on statically-based language so I couldn&amp;#39;t agree more with the conclusions of the author.&lt;/p&gt;
&lt;p&gt;In my opinion, if you really want to deal with bugs, you&amp;#39;ll need to test your application. Type hinting is at the same time limited,  inadequate and insufficient for testing an application. And although &lt;a href=&quot;http://evanfarrer.blogspot.ca/2012/06/unit-testing-isnt-enough-you-need.html&quot;&gt;some claim that both tests &amp;amp; types are required&lt;/a&gt;, I can&amp;#39;t concur since I&amp;#39;m developing using dynamic languages for the past 10 years and I only encountered type issues a couple of times during this whole period.&lt;/p&gt;
&lt;h2 id=&quot;does-that-mean-statically-typed-languages-are-bad-&quot;&gt;Does that mean statically typed languages are bad?&lt;/h2&gt;
&lt;p&gt;Not at all, Static &amp;amp; Dynamic languages are both valid paradigms but you can&amp;#39;t just mix random concepts from both lands and expect to obtain a better paradigm.
Dynamic languages helped me to write significantly easier &amp;amp; less cluttered code, and enhanced my productivity. Adding type hinting at this step doesn&amp;#39;t make sense for me since it doesn&amp;#39;t :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exempt you from writing tests&lt;/li&gt;
&lt;li&gt;produce better performance (like static types did in statically typed languages)&lt;/li&gt;
&lt;li&gt;make your code easier to play with and share (it&amp;#39;s quite the opposite)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have absolutely no doubt that this affirmation will be largely disagreed with by many in the PHP community. AFAIK, PHP is the only dynamic language who introduced this concept. Ruby, Python or JavaScript just assume than when an object acts like a duck, quacks like a duck, then it&amp;#39;s a duck. For the time being I didn&amp;#39;t see yet any valid use case for which it would worth the effort of using type hinting in any of my projects. That&amp;#39;s why duck typing was the option I choosed for PHP.&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;http://radify.io/blog/interfaces-the-misunderstood-concept/&quot;&gt;follow-up post&lt;/a&gt;, we will talk about interfaces and why to use them (outside the scope of making type hinting more flexible, of course).&lt;/p&gt;
</description></item><item><title>Overachieving Software Projects</title><link>http://radify.io/blog/overachieving-software-projects/</link><pubDate>Fri, 16 May 2014 11:17:20 -0400</pubDate><guid isPermaLink="true">http://radify.io/blog/overachieving-software-projects/</guid><author></author><description>&lt;p&gt;On software projects, we often have clearly defined deliverables. That’s very useful for staying focused, but it can make us a little narrow in our perspective. This post defines the concept of &lt;strong&gt;secondary deliverables&lt;/strong&gt; as a tool for broadening our thinking, sharing knowledge, and raising the profile of an organization within their specific discipline.&lt;/p&gt;
&lt;h2 id=&quot;what-are-secondary-deliverables-&quot;&gt;What are secondary deliverables?&lt;/h2&gt;
&lt;p&gt;Secondary deliverables are artifacts produced in the course of your &amp;quot;main work&amp;quot; that can be made to be of value in a broader context – lessons learned from a specific task distilled into a generic, publishable form, or a workflow tool extracted from its original project. To formalise the term, a secondary deliverable is &lt;strong&gt;any content (documentation, code, workflow, etc.) that can be derived in a generic form from a specific task&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Secondary deliverables may include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Blog posts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Podcasts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Video tutorials&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tweets&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A talk given at a meetup or conference (which should be video recorded to maximise ROI)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open source contributions&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s take a look at some examples.&lt;/p&gt;
&lt;h2 id=&quot;three-tales-of-secondary-deliverables&quot;&gt;Three tales of secondary deliverables&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tale 1&lt;/strong&gt;: Developer Alex is working on a ticket for a client and writes an end-to-end (E2E) test to verify that the client’s acceptance criteria have been met. In doing so, Alex has to make several decisions about how often to reset the test database from fixtures, and when to roll on to the next test with the same data. In doing so, Alex is making a tradeoff between test execution time and isolation. Alex decides that this is worth doing a blog post about. Alex’s marketing department promote the post and, if the organisation is fortunate, it ends up being featured prominently on an aggregator such as Reddit or Hacker News.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tale 2&lt;/strong&gt;: Project manager Charlie trials running sprints from Wednesday to Tuesday rather than Monday to Friday. Charlie keeps a close eye on burndown and velocity and sees if any measurable gains are made. Charlie presents his finding at a local meetup and gets into a conversation with another project manager afterwards, comparing the strengths and weaknesses of various approaches. Charlie capitalises even further on this by recording and releasing a podcast with these PMs discussing the idea.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tale 3&lt;/strong&gt;: Operations engineer George has automated deployment of a system’s infrastructure on EC2 using Ansible. George thinks &amp;quot;hey, that wasn’t so hard as I thought&amp;quot; and produces a video tutorial for upload to Youtube. The organization feature the Youtube video on the company’s blog. The video gets spotted by a conference organiser, who invites George to give a talk.&lt;/p&gt;
&lt;p&gt;These are just some examples of how adopting this mindset can work. Be creative!&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-secondary-deliverables&quot;&gt;Benefits of secondary deliverables&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Enhanced knowledge base&lt;/strong&gt;. It’s very tempting to solve a problem and simply move on, only to have the issue recur and not to be able to remember how you solved it. If you blogged about it, there’s a much stronger chance that you’ll be able to solve it quickly, and that if you’re not around, your colleagues at least know where to start! Blogging can help an organisation maintain a sense of progression.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Knowledge sharing&lt;/strong&gt;. A private knowledgebase is one thing, but a public one is even better, as there is more impetus for it to be correct! The entire open source world is built on this ethos. More importantly, software development is a very young industry in the scheme of history, and best practices, such as they are, are in their infancy. Sharing discoveries allows us to coalesce on common patterns and ideas, and your contribution may trigger further insights in others who may be working on similar or parallel tracks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Organisational perception&lt;/strong&gt;. If you’ve solved a problem, or done something clever, why not shout about it? Let the world know that you’re smart people! Things like podcasts and tutorial videos can give an organisation an authoritative voice. Conversely, without blog content, technical articles and so forth, an organisation will struggle to position itself as thought leaders. If I’m looking at a tech company website, and there is no tech content on there, I am likely to dismiss that company pretty quickly!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recruitment&lt;/strong&gt;. A tech company with strong open source and blogging output, for example, is very attractive to many in the industry. Thought leaders like ThoughtWorks are considered desirable employers partly for this reason.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Greater variety&lt;/strong&gt;. Frank Herbert may have called fear the mindkiller, but surely boredom is just as dangerous! Spending an afternoon or a week working on writing, blogging and video content derived from one’s primary tasks can be a fantastic way of recovering energy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reduction of siloization&lt;/strong&gt;. Bearing secondary deliverables in mind as a team works on a project can encourage broader thinking. No disrespect intended, but if you leave your company’s profile solely to your marketing team, you can end up looking generic. Without technical blogging and technical content, how are you going to position your organisation in your industry? With secondary deliverables, you are actively supporting your marketing department’s efforts to show your organisation in a positive light. It’s taking your eyes off small, tight &amp;quot;KPIs&amp;quot; (which, in my opinion, are utterly poisonous) and giving an organisation-wide perspective.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Increased ROI&lt;/strong&gt;. All of the benefits we’ve seen in this list can be summarised as Return On Investment - the secondary deliverables mindset is about getting the most you possibly can out of the hard work that you put in.&lt;/p&gt;
&lt;h2 id=&quot;risk-mitigation&quot;&gt;Risk mitigation&lt;/h2&gt;
&lt;p&gt;Secondary deliverables certainly aren’t &amp;quot;free&amp;quot; and do have some risks which should be considered. We’ll take a look at the top three.&lt;/p&gt;
&lt;p&gt;Firstly, producing secondary deliverables inevitably exerts a drag on productivity. After all, if you’re producing a video, you’re likely not getting paid directly for it. I would contest, however, that you could consider this time to be coming out of the marketing and R&amp;amp;D budgets.&lt;/p&gt;
&lt;p&gt;Secondly, secondary deliverables are the first things to go by the wayside when pressure is on as it’s difficult to justify their value in direct terms. When this happens, it can be frustrating to have a whole list of ideas and no time to implement them. This can be mitigated by planning in some slack time into everyone’s schedule. It won’t always work out, but if you start with some slack, then you stand a fighting chance!&lt;/p&gt;
&lt;p&gt;Finally, there is the risk of accidentally leaking sensitive information. Much like code, all secondary deliverables should go through some form of peer review before being released into the wild!&lt;/p&gt;
&lt;h2 id=&quot;introducing-secondary-deliverables-to-your-organisation&quot;&gt;Introducing secondary deliverables to your organisation&lt;/h2&gt;
&lt;p&gt;Although I’ve not really codified secondary deliverables before, on reflection, it’s long been part of my mindset, and that’s where it has to start. It is &lt;em&gt;not&lt;/em&gt; about adding pressure to people to produce things outside of their remit: sometimes, an organisation can get hold of the concept of secondary deliverables and pressure its staff to produce more; that’s a total misrepresentation of what we’re advocating. A secondary deliverable should happen as a byproduct of somebody’s work, &lt;em&gt;not &lt;/em&gt;as an additional pressure. Rather, it’s about taking time to maximise the benefits of the work that’s already being done rather than letting that value simply evaporate.&lt;/p&gt;
&lt;p&gt;So, with that caution in place, what I recommend is to simply get people thinking about their roles more broadly. Lead by example, whether you are in a position of authority or not. In my experience, that is the most reliable way of effecting change. Start small, and be consistent. An internal podcast or team training lunch is a great place to start!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;The perception of your organisation is &lt;em&gt;everyone’s&lt;/em&gt; responsibility, and adopting a mindset of considering &amp;quot;what can I take from this experience and how can I present it?&amp;quot; is a really good way of improving that. The examples I’ve talked about in this post certainly aren’t the only secondary deliverables; it’s much more about thinking “hey, this is a really interesting problem I’ve just solved, is there some way I can share that information with people in my organisation and in the wider community?”&lt;/p&gt;
&lt;p&gt;I hope this post has given you some ideas. Why not get in touch and let us know what you think, or share some of your own ideas and post a link below?&lt;/p&gt;
</description></item></channel></rss>