<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2022-06-27T21:51:16+00:00</updated><id>/feed.xml</id><title type="html">Todd Way</title><subtitle>I post about things I've learned as a software engineer</subtitle><entry><title type="html">Using Feature Flags To Fake The State Of External Systems</title><link href="/2022/05/20/using-feature-flags-to-fake-the-state-of-external-systems.html" rel="alternate" type="text/html" title="Using Feature Flags To Fake The State Of External Systems" /><published>2022-05-20T00:00:00+00:00</published><updated>2022-05-20T00:00:00+00:00</updated><id>/2022/05/20/using-feature-flags-to-fake-the-state-of-external-systems</id><content type="html" xml:base="/2022/05/20/using-feature-flags-to-fake-the-state-of-external-systems.html">&lt;p&gt;Most applications include code details to interact with external systems.  Testing these interactions, especially in non-production systems, can be unpredictable.  Feature flags provide a way to swap the real integration details with code that fakes different states of an external system.  This avoids interruptions when those systems are offline, not responding as expected, or just hard to change.&lt;/p&gt;

&lt;p&gt;Let’s imagine a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thermostat&lt;/code&gt; application that, among other things, determines if the outside temperature is between two values:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;temperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBetween&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;currentTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxTemp&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We could implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TemperatureService&lt;/code&gt; with a version that calls a weather.gov URL and parses the response data:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WeatherGovTemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;HourlyForecast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://api.weather.gov/gridpoints/TOP/31,80/forecast/hourly&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;currentTemperature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createBasicThermostatApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;WeatherGovTemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;center&gt; &lt;figure&gt; &lt;img src=&quot;https://raw.githubusercontent.com/toddway/feature-fakes/main/img/com.example.sandbox.BasicThermostatApp.png&quot; style=&quot;width:auto&quot; /&gt; &lt;figcaption&gt;&lt;i&gt;Arrows indicate creational dependencies.  They point from an object to the objects used to create it&lt;/i&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;/center&gt;

&lt;p&gt;Or we could create a version that fakes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TemperatureService&lt;/code&gt; and always returns 70 degrees:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Always70TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createFakeThermostatAppWithFakes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Always70TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/toddway/feature-fakes/main/img/com.example.sandbox.FakeThermostatApp.png&quot; data-align=&quot;center&quot; style=&quot;width:auto&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In either case, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thermostat&lt;/code&gt; only depends on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TemperatureService&lt;/code&gt; interface and does not need to be changed to use different implementations. This concept is called &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_inversion_principle&quot;&gt;dependency inversion&lt;/a&gt; and helps loosen the coupling between related objects in an application.&lt;/p&gt;

&lt;p&gt;With two versions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TemperatureService&lt;/code&gt;, we can use a &lt;a href=&quot;https://martinfowler.com/articles/feature-toggles.html&quot;&gt;feature flag&lt;/a&gt; to control which version the app will use:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FakeTemperatureFeature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;isEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Boolean&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createThermostatAppWithFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;feature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FakeTemperatureFeature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;isEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEnabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Always70TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WeatherGovTemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/toddway/feature-fakes/main/img/com.example.sandbox.ThermostatAppWithFlags.png&quot; data-align=&quot;center&quot; style=&quot;width:auto&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Switching the state of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FakeTemperatureFeature.isEnabled&lt;/code&gt; is now the only change needed to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thermostat&lt;/code&gt; with either version of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TemperatureService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So far we have used simple &lt;a href=&quot;https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)&quot;&gt;factory&lt;/a&gt; functions to isolate the dependencies needed to &lt;em&gt;create&lt;/em&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Thermostat&lt;/code&gt;. But as the application grows in complexity, so can the the effort to manage these relationships. A dependency injection framework, like &lt;a href=&quot;https://dagger.dev/&quot;&gt;Dagger&lt;/a&gt;, can greatly reduce factory boilerplate and validate the object graph each time it is compiled:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Module&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ThermostatModule&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Provides&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Provides&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nationalWeatherTempService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WeatherGovTemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Provides&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;always70TempService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Always70TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Provides&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@Singleton&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fakeTemperatureFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FakeTemperatureFeature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;isEnabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Provides&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;temperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FakeTemperatureFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;real&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;WeatherGovTemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Always70TemperatureService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEnabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;real&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modules&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ThermostatModule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@Singleton&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ThermostatApp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createThermostatApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DaggerThermostatApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;center&gt; &lt;figure&gt; &lt;img src=&quot;https://raw.githubusercontent.com/toddway/feature-fakes/main/img/com.example.sandbox.ThermostatApp.png&quot; style=&quot;width:auto&quot; /&gt; &lt;figcaption&gt;&lt;i&gt;The @Singleton annotation binds created objects to the scope of the @Component so the same instance can be reused&lt;/i&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;/center&gt;

&lt;p&gt;A future version of the dependency graph, with additional feature and flags, might look like this:&lt;/p&gt;

&lt;center&gt; &lt;img src=&quot;https://raw.githubusercontent.com/toddway/feature-fakes/main/img/com.example.sandbox.BigThermostatApp.png&quot; style=&quot;width:auto&quot; /&gt; &lt;/center&gt;

&lt;p&gt;Finally, making features easy to switch can be useful in development, but we don’t want those changes to be accidentally released. We can prevent this with basic automated tests:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testThatFakeTemperatureFeatureIsFalse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;feature&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ThermostatModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fakeTemperatureFeature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEnabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;$feature.isEnabled should be false but was ${feature.isEnabled}&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To keep this example simple, the actual value of the flag is hardcoded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object: FakeTemperatureFeature { override val isEnabled = true }&lt;/code&gt;.  In certain situations it may be more useful to control the value from user interface so it can be switched without code changes.  Still it’s unlikely you would want a feature that fakes external systems to be released to real users.  Even if the flag is mutable in test builds, it should still be possible to write deterministic tests that prevent it’s release.&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Invert dependencies on external details&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Write a fake version (or use an existing test double) of the external details&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use a feature flag to declare which version to use&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Isolate feature decisions in factories&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use injection to minimize creational boilerplate&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add automated tests to prevent releasing features accidentally&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;additional-notes&quot;&gt;Additional Notes&lt;/h3&gt;

&lt;p&gt;This example focuses on how to make feature flag implementations safe and easy to maintain, but it leaves the actual value of the flag hardcoded in a factory function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object: FakeTemperatureFeature { override val isEnabled = true }&lt;/code&gt;.  In reality it may be more useful to control this from a user interface and store the value&lt;/p&gt;

&lt;p&gt;Creating fake versions may seem like extra work, but if you’re writing unit tests, you may be able to feed two birds with one seed.  In the example below, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always60&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always70&lt;/code&gt; could be repurposed in a fake temperature feature flag.&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testThatIsBetweenReturnsExpectedValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;always60&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;always70&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TemperatureService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;minTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;68&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;maxTemp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;always60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isBetween&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Thermostat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;always70&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isBetween&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxTemp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You don’t need to make all integrations flaggable from the start.  The next time you’re blocked by problems with an outside system, try applying a flag for just the calls needed to unblock your current task.  It should be possible to get part of an application working with object fakes even if the rest is not.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FakeTemperatureFlag.isEnabled&lt;/code&gt; has a boolean type because only two value states were necessary: true &amp;amp; false (feature flags with only two states are often called feature toggles).  But there are situations where flags with more than two states may be suitable.  We might want to test with a set of fakes that all throw errors and a set of fakes that all return stubbed values.  A flag for this might have three states: real, stubs, and errors.&lt;/p&gt;</content><author><name></name></author><summary type="html">Most applications include code details to interact with external systems. Testing these interactions, especially in non-production systems, can be unpredictable. Feature flags provide a way to swap the real integration details with code that fakes different states of an external system. This avoids interruptions when those systems are offline, not responding as expected, or just hard to change.</summary></entry><entry><title type="html">Share Artifacts With An Orphan Branch</title><link href="/2020/04/18/share-artifacts-with-an-orphan-branch.html" rel="alternate" type="text/html" title="Share Artifacts With An Orphan Branch" /><published>2020-04-18T00:00:00+00:00</published><updated>2020-04-18T00:00:00+00:00</updated><id>/2020/04/18/share-artifacts-with-an-orphan-branch</id><content type="html" xml:base="/2020/04/18/share-artifacts-with-an-orphan-branch.html">&lt;p&gt;Over the last several years I’ve worked with a variety of great hosted services for team code integration:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;For build automation - Jenkins, Bitrise, CircleCi, BuddyBuild, TeamCity.&lt;/li&gt;
  &lt;li&gt;For code analysis - SonarQube, Codacy, Code Climate, Veracode.&lt;/li&gt;
  &lt;li&gt;For peer review - Github, Bitbucket, GitLab, Gerrit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When everything works in harmony (checking out files, compiling, running tests, analyzing code structure, assembling artifacts, posting clear results) the whole team sees steady feedback, early in the development cycle, that helps prevent defects, educate new team members, and nudge us all to better design habits.&lt;/p&gt;

&lt;p&gt;But for various reasons we can’t always set up the perfect recipe of hosted services for every project. If information that we’ve counted on in the past is missing, unreliable, or hard to access, the impact quickly fades. In the worst cases, the &lt;a href=&quot;https://youtu.be/ddPQAJSm2cQ&quot;&gt;lack of feedback makes us falsely confident&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are fancy ways to connect build automation services and code analysis services to deployment services and code review services. If these options are available, if you can quickly troubleshoot interruptions, and if your whole team can access the results, then do this.  If not, here is a relatively independent alternative:&lt;/p&gt;

&lt;p&gt;Most software platforms have standalone tools for code analysis (test execution, test coverage, linting, docgen, etc.) that can generate standalone reports (probably HTML). If you get familiar with how to generate these, you can port them to future projects without relying on an external hosted service or special IDE features. Make a one-step script that generates all of these artifacts.&lt;/p&gt;

&lt;p&gt;Make another one-step script that does this: check out an &lt;a href=&quot;https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt---orphanltnewbranchgt&quot;&gt;orphan branch&lt;/a&gt; from your code repository into a temporary folder. Remove existing files. Copy in the generated files from your previous script. Commit and push. Print a download link for the commit.&lt;/p&gt;

&lt;p&gt;Finally copy/paste the download link into your pull request description.  Your team can use this link to easily download and browse results.  One additional file I include is a root index.html with short descriptions and relative links for each report.  This helps everyone know why each report is there and gives a single entry point for everything in the download.&lt;/p&gt;

&lt;p&gt;For reference, I’ve set this up on one of my small, public Github projects.  You can see an example &lt;a href=&quot;https://github.com/toddway/Shelf/pull/6&quot;&gt;pull request&lt;/a&gt; that includes a direct link to &lt;a href=&quot;https://github.com/toddway/Shelf/archive/07e990cb8840e83782d28f9135a25cf75e040ad3.zip&quot;&gt;download reports&lt;/a&gt;.  You can also see the &lt;a href=&quot;https://github.com/toddway/Shelf/blob/multiplatform/shelf/push-artifacts.sh&quot;&gt;shell script for pushing artifacts&lt;/a&gt; and the &lt;a href=&quot;https://github.com/toddway/Shelf/blob/multiplatform/shelf/push-artifacts-init.sh&quot;&gt;shell script for initializing the branch with an index.html&lt;/a&gt;.  The goal for these scripts is to be relatively generic and portable so they can quickly be applied to future projects.  The same goal applies to scripts that generate report artifacts, but this is inherently more platform-dependent.  In this example, &lt;a href=&quot;https://github.com/toddway/Shelf/blob/multiplatform/shelf/checks.gradle&quot;&gt;the script to generate artifacts is Gradle-based&lt;/a&gt; and the code analysis tools include JaCoCo, CPD, Detekt, BuildChecks, and JUnit.&lt;/p&gt;</content><author><name></name></author><summary type="html">Over the last several years I’ve worked with a variety of great hosted services for team code integration:</summary></entry><entry><title type="html">Checklist Yourself</title><link href="/2018/08/15/checklist-yourself.html" rel="alternate" type="text/html" title="Checklist Yourself" /><published>2018-08-15T00:00:00+00:00</published><updated>2018-08-15T00:00:00+00:00</updated><id>/2018/08/15/checklist-yourself</id><content type="html" xml:base="/2018/08/15/checklist-yourself.html">&lt;p&gt;In 1935, Boeing introduced a heavy bomber that outperformed any other aircraft of it’s kind. It crashed tragically in exhibition because a routine step was missed by the well-trained and experienced flight crew.  As a result, pilots everywhere began to adopt preflight checklists and failures decreased significantly.&lt;/p&gt;

&lt;p&gt;Today, checklists for complex responsibilities are used in many professions. A surgeon named Adul Gawande wrote an entire book called &lt;a href=&quot;http://atulgawande.com/book/the-checklist-manifesto/&quot;&gt;The Checklist Manifesto&lt;/a&gt;.   I think one reason the idea has spread so successfully is because a checklist is an incredibly easy tool to make and to use.
[[MORE]]&lt;/p&gt;

&lt;p&gt;I’ve written previously about how we do &lt;a href=&quot;http://toddway.com/post/175477173505/put-a-motor-on-your-code-cycle&quot;&gt;continuous&lt;/a&gt; &lt;a href=&quot;http://toddway.com/post/165735557485/continuous-integration-for-firebase-cloud-code&quot;&gt;integration&lt;/a&gt;, which is essentially an automated checklist verified by a machine. CI provides a level of safety, consistency, and efficiency that’s hard to match in any other way.  The problem is some details are prohibitively hard to automate and too important to ignore.  Our current solution for this is to manually review all code before it “takes flight”.  We use pull requests for this.  What we’ve been missing, tho, is a preflight checklist.&lt;/p&gt;

&lt;p&gt;Gawande sees ineptitude (not making use of what we already know) as a greater problem than ignorance (what we don’t know).  So our development group did a retrospective on code reviews.  We made a list of &lt;em&gt;what we already know&lt;/em&gt; we’re looking for when reviewing code.  The things we don’t want to forget about in the future.   Based on input from that discussion and this handy &lt;a href=&quot;http://www.projectcheck.org/uploads/1/0/9/0/1090835/checklist_for_checklists_final_10.3.pdf&quot;&gt;checklist for creating checklists&lt;/a&gt;, I started one:&lt;/p&gt;

&lt;h2 id=&quot;a-checklist-for-reviewing-code&quot;&gt;A checklist for reviewing code&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Integration  
- [ ] Will merging this code create source conflicts?  
- [ ] Is there a clear and concise description of the changes?
- [ ] Did all automated checks (build, test, lint) run and pass?  
- [ ] Are there supporting metrics or reports (e.g. test coverage, fitness functions) that measure the impact?
- [ ] Are there obvious logic errors or incorrect behaviors that might break the software?

Readability
- [ ] Is the code self-documenting? Do we need secondary sources to understand it?  
- [ ] Do the names of folders, objects, functions, and variables intuitively represent their responsibilities?  
- [ ] Could comments be replaced by descriptive functions?  
- [ ] Is there an excessively long object, method, function, pull request, parameter list, or property list? Would decomposing make it better? .  

Anti-patterns
- [ ] Does the code introduce any of the following anti-patterns?
- [ ] Sequential coupling - a class that requires its methods to be called in order  
- [ ] Circular dependency - mutual dependencies between objects or software modules  
- [ ] Shotgun surgery - a change needs to be applied to multiple classes at the same time  
- [ ] Magic numbers - unexplained numbers in algorithms  
- [ ] Hard code - embedding assumptions about the environment in the implementation  
- [ ] Error hiding - catching an error and doing nothing or showing a meaningless message  
- [ ] Feature envy - a class that uses methods of another class excessively  
- [ ] Duplicate code - identical or very similar code exists in more than one location.  
- [ ] Boat anchor - retaining a part of a system that no longer has any use  
- [ ] Cyclomatic complexity - a function contains too many branches or loops 
- [ ] Famous volatility - a class or module that many others depend on and is likely to change 
  
Design principles
- [ ] Does the code align with the following principles?
- [ ] Single Responsibility - an object should have only one reason to change  
- [ ] Open/Closed - objects should be open for extension, closed for modification  
- [ ] Liskov Substitution - subtypes should not alter the correctness of code that depends on a supertype  
- [ ] Interface Segregation - many client specific interfaces are better than one general purpose interface  
- [ ] Dependency Inversion - dependencies should run in the direction of abstraction; high level policy should be immune to low level details

Last updated: 8/15/2018

Note: This is not a checklist for *approving* or *merging* code, it is a checklist for *reviewing* code.  It's a list of questions a reviewer should ask themselves as they review.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">In 1935, Boeing introduced a heavy bomber that outperformed any other aircraft of it’s kind. It crashed tragically in exhibition because a routine step was missed by the well-trained and experienced flight crew. As a result, pilots everywhere began to adopt preflight checklists and failures decreased significantly.</summary></entry><entry><title type="html">Put A Motor On Your Code Cycle</title><link href="/2018/07/02/put-a-motor-on-your-code-cycle.html" rel="alternate" type="text/html" title="Put A Motor On Your Code Cycle" /><published>2018-07-02T00:00:00+00:00</published><updated>2018-07-02T00:00:00+00:00</updated><id>/2018/07/02/put-a-motor-on-your-code-cycle</id><content type="html" xml:base="/2018/07/02/put-a-motor-on-your-code-cycle.html">&lt;p&gt;There’s an old programmer joke:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Show me a line of code and I’ll tell you what’s wrong with it,
Show me five hundred lines of code and I’ll say “looks ok to me”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Where I work, we use pair programming and pull requests in our development process.  No code is committed to the main branch without peer review.&lt;/p&gt;

&lt;p&gt;I’m convinced the investment in extra eyes can pay off for a project of any size.  Human brains are uniquely capable of solving hard problems even when objectives are vaguely defined.  When we do this together it increases ownership, cohesion, velocity and resilience across the team.   This is magical.&lt;/p&gt;

&lt;p&gt;But even the collective brainpower of a long-lived, high-functioning team isn’t always reliable.  The complexities, pressures, and context-switching of a typical day can wear us down.  When we add the eye-glazing drudgery of a long pull request at 4pm in the afternoon, we’re in trouble.&lt;/p&gt;

&lt;p&gt;Here’s how we’re using automation to optimize our review process:&lt;/p&gt;

&lt;h2 id=&quot;build-checks&quot;&gt;Build checks&lt;/h2&gt;
&lt;p&gt;Before anyone reviews source code, a machine should do it first.  It won’t catch everything a human could see, but it’s more consistent and much faster.  Source control systems (e.g. Github, Bitbucket) usually have an API so build results can be tracked for each code commit.  These are commonly called “status checks” or “build checks”.  As shown below, a green icon indicates a check posted from a build server was successful.&lt;/p&gt;

&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;137&quot; data-orig-width=&quot;856&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/passing-check.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/3af19c4b589c74f4825c2f263c8bd66e/tumblr_inline_pk09lmqzym1r4ik0y_540.png&quot; data-orig-height=&quot;137&quot; data-orig-width=&quot;856&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/passing-check.png&quot; /&gt;&lt;/figure&gt;

&lt;p&gt;Reviewers see a green or red icon immediately and can avoid wasting time reading code with known problems.  Even better, we can make these checks required for merging any code into our main code branch. Now the entire team, whether they review code or not, has confidence that the main branch is &lt;em&gt;always&lt;/em&gt; protected.&lt;/p&gt;

&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;702&quot; data-orig-width=&quot;894&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/protect-branch.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/743da068a6066528fc1f0fa7a7925fc6/tumblr_inline_pk09lnuJZB1r4ik0y_540.png&quot; data-orig-height=&quot;702&quot; data-orig-width=&quot;894&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/protect-branch.png&quot; /&gt;&lt;/figure&gt;

&lt;p&gt;We currently use 3 build checks: build, test, and lint. These can work for almost any project.&lt;/p&gt;

&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;235&quot; data-orig-width=&quot;472&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/build-checks.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/9e92e39acb0f9bf617fb103499168990/tumblr_inline_pk09loz9uw1r4ik0y_540.png&quot; data-orig-height=&quot;235&quot; data-orig-width=&quot;472&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/build-checks.png&quot; /&gt;&lt;/figure&gt;

&lt;p&gt;To process and post the checks, we use a Gradle plugin called &lt;a href=&quot;https://github.com/toddway/BuildChecks&quot;&gt;BuildChecks&lt;/a&gt;.  We use Gradle because it’s free, fast, configurable, testable, well-supported, and portable.  From one project to the next, we don’t aways get to use the same development languages, source control system, or build servers, but we want to preserve key processes.  BuildChecks can work across multiple languages and source control systems.  It can run anywhere Java 7+ is installed.  In situations where we aren’t able to use a dedicated build server, it can be run from a developer’s workstation.  We can have the same automated integration protection even on shoestring budgets and timelines.&lt;/p&gt;

&lt;h2 id=&quot;build&quot;&gt;Build&lt;/h2&gt;
&lt;p&gt;The “build” check tells us if a build finished successfully and how long it took.  The process may be different for each project but is typically some variation of: compile source code, assemble artifacts, run tests, run lint, and deploy artifacts.  Having this feedback alone for a pull request review will save considerable time and effort.&lt;/p&gt;

&lt;h2 id=&quot;test&quot;&gt;Test&lt;/h2&gt;
&lt;p&gt;The “test” check show us the percentage of code that is covered by tests.  BuildChecks parses output from coverage tools like JaCoCo, Cobertura, Istanbul, Slather, and OpenCover. A minimum threshold for coverage can be set that will cause the check to fail.  This is optional.  Even without a threshold, the check clarifies that tests are running and if they’ve changed between commits.&lt;/p&gt;

&lt;h2 id=&quot;lint&quot;&gt;Lint&lt;/h2&gt;
&lt;p&gt;The “lint” check tells us if the code violates any predefined standards.  BuildChecks parses output from linters like ESLint, TSLint, Detekt, Checkstyle, PMD, SwiftLint, and Android Lint.  Each linter has different rule sets that span categories like correctness, security, performance, accessibility, formatting style, internationalization, etc.  The lists can be overwhelming at first.  Many are language or platform-specific, but one category that has some pretty universal rules is maintainability.  If you don’t know where to start, this is a good place.&lt;/p&gt;

&lt;p&gt;Here’s list of maintainability rules from a multi-language code analysis platform called &lt;a href=&quot;https://docs.codeclimate.com/docs/maintainability&quot;&gt;CodeClimate&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Argument count - Methods or functions defined with a high number of arguments&lt;/li&gt;
  &lt;li&gt;Complex logic - Boolean logic that may be hard to understand&lt;/li&gt;
  &lt;li&gt;Method complexity - Functions or methods that may be hard to understand&lt;/li&gt;
  &lt;li&gt;File length - Excessive lines of code within a single file&lt;/li&gt;
  &lt;li&gt;Method count - Classes defined with a high number of functions or methods&lt;/li&gt;
  &lt;li&gt;Method length - Excessive lines of code within a single function or method&lt;/li&gt;
  &lt;li&gt;Nested control flow - Deeply nested control structures like if or case&lt;/li&gt;
  &lt;li&gt;Return statements - Functions or methods with a high number of return statements&lt;/li&gt;
  &lt;li&gt;Similar blocks of code - Duplicate code which is not identical but shares the same structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enable any of these that your lint tool supports.  Then use pull request conversations to discuss and identify additional patterns you want to add.  If the pattern isn’t already available, you can write your own custom rule.&lt;/p&gt;

&lt;h2 id=&quot;details&quot;&gt;Details&lt;/h2&gt;
&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;235&quot; data-orig-width=&quot;472&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/build-checks.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/9e92e39acb0f9bf617fb103499168990/tumblr_inline_pk09loz9uw1r4ik0y_540.png&quot; data-orig-height=&quot;235&quot; data-orig-width=&quot;472&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/build-checks.png&quot; /&gt;&lt;/figure&gt;

&lt;p&gt;In the image above, each check has a hyperlink labelled “Details”.  This links back to detail on the build server.  It’s a great way to give reviewers access to the full generated reports from lint and coverage tools as well as build logs and other artifacts.  The more context we can provide, the easier it will be for others to give real feedback.&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Automated checks help code reviews scale with consistency. Getting started is as easy as enabling the requirement in your source control system and using a tool like BuildChecks to report it.  If you’re not already, this puts you on a path to a several important development practices: automated builds, unit tests, frequent integration, maintainability standards, and protected branches.  Don’t worry if you start with low test coverage and high lint violations.  You will immediately have a better understanding of your current situation and a way track your progress.&lt;/p&gt;

&lt;p&gt;What automation tricks have you found for improving code review and integration?&lt;/p&gt;</content><author><name></name></author><summary type="html">There’s an old programmer joke:</summary></entry><entry><title type="html">Continuous Integration For Firebase Cloud Code</title><link href="/2017/09/25/continuous-integration-for-firebase-cloud-code.html" rel="alternate" type="text/html" title="Continuous Integration For Firebase Cloud Code" /><published>2017-09-25T00:00:00+00:00</published><updated>2017-09-25T00:00:00+00:00</updated><id>/2017/09/25/continuous-integration-for-firebase-cloud-code</id><content type="html" xml:base="/2017/09/25/continuous-integration-for-firebase-cloud-code.html">&lt;p&gt;In a &lt;a href=&quot;http://toddway.com/post/165619029205/types-and-tests-for-firebase-cloud-code&quot;&gt;previous post&lt;/a&gt; I showed how to add type-checking and unit tests to Firebase cloud code (cloud functions &lt;em&gt;and&lt;/em&gt; database rules).  Those tests are independent from any Firebase environment and independent from each other.   We should be able to run them all quickly and consistently in a clean Node.js environment with a single command.  We should also be able to chain that command with others so that we can build, test, and deploy each code commit directly into a live Firebase environment.&lt;/p&gt;

&lt;h4 id=&quot;here-are-the-steps-we-want-to-automate&quot;&gt;Here are the steps we want to automate:&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Download project source&lt;/li&gt;
  &lt;li&gt;Download project dependencies&lt;/li&gt;
  &lt;li&gt;Compile project&lt;/li&gt;
  &lt;li&gt;Run all tests&lt;/li&gt;
  &lt;li&gt;Stop if any test fails, otherwise continue&lt;/li&gt;
  &lt;li&gt;Deploy (cloud functions and database rules) to a Firebase environment&lt;/li&gt;
  &lt;li&gt;Write a deployment summary to our Firebase environment (Git info, date, test results)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll assume we have a machine with Node.js and Git installed.  This could be a developer machine or a dedicated continuous integration server (I try to make the execution identical for either if I can).  The first three steps are pretty straightforward from the command line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git@github.com:whatever folder-name
npm install
tsc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that we have a compiled project environment, we can use Typescript/Javascript to handle the rest of our steps.  From the command line, node can execute a function from a local file like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node -e 'require(&quot;./build.js&quot;).runAllTests()'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let’s implement a function to run all our tests:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export async function runAllTests() : Promise&amp;lt;testresultsentity&amp;gt; {
    const Mocha = require('mocha');
    const mocha = new Mocha();
    mocha.addFile('./test/tests.functions.js');
    mocha.addFile('./test/tests.database.js');
    const results = new TestResultsEntity();
    return await new Promise&amp;lt;testresultsentity&amp;gt;((resolve, reject) =&amp;gt; {
        mocha.run()
            .on('pass', (test) =&amp;gt; { results.passed++; })
            .on('fail', (test, err) =&amp;gt; { results.failed++; })
            .on('end',  () =&amp;gt; { resolve(results) });
    });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here I’m use the Mocha API to point to our test files, run them, and keep track of how many pass and fail.  Let’s write a deploy function that grabs the test results and handles our last three steps:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export async function deploy()  {
    const testResults = await runAllTests();
    const gitSummary = await getGitSummary();
    const summary = `${testResults.getSummary()} on ${getDateSummary()} from ${gitSummary}`;

    if (testResults.hasFailures()) {
        console.log('Deploy failed');
    } else {
        await asyncCommand(`firebase deploy --only functions,database`);
        await asyncCommand(`firebase database:set /lastDeploy -d '&quot;${summary}&quot;' -y`);
        console.log('Deploy succeeded');
    }

    console.log(summary);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the else clause above we run two &lt;a href=&quot;https://firebase.google.com/docs/cli/&quot;&gt;Firebase CLI&lt;/a&gt; commands.  The first command deploys our code to the currently configured Firebase environment.  The second command writes a record to the database of that environment with a summary of our deployment.  This makes it easy for anyone on the team to see:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;what code is deployed,&lt;/li&gt;
  &lt;li&gt;when it happened,&lt;/li&gt;
  &lt;li&gt;and the results of the tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To pull all of this together into a single command, we’ll use the package.json file to set up an npm script:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;scripts&quot;: {
   &quot;deploy&quot;: &quot;npm install &amp;amp;&amp;amp; tsc &amp;amp;&amp;amp; node -e 'require(\&quot;./build.js\&quot;).deploy()'&quot;
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can run all steps with these two commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git@github.com:whatever folder-name
npm run deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, here’s the ancillary code referenced by the deploy() and runAllTests() functions above:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export async function getGitSummary() : Promise&amp;lt;string&amp;gt; {
    const gitSha = await asyncCommand(&quot;git rev-parse --short HEAD&quot;);
    const gitBranch = await asyncCommand(&quot;git rev-parse --abbrev-ref HEAD&quot;);
    return Promise.resolve(`${gitSha.trim()}-${gitBranch.trim()}`);
}

function getDateSummary() : string {
    return new Date().toLocaleString(&quot;en-US&quot;, { timeZone: 'America/Chicago' }).trim();
}


const exec = require('child_process').exec;
function asyncCommand(command : string) : Promise&amp;lt;string&amp;gt; {
    return new Promise&amp;lt;string&amp;gt;((resolve, reject) =&amp;gt; {
        exec(command, function(error, stdout, stderr){ resolve(stdout); });
    })
}

export class TestResultsEntity {
    passed : number = 0;
    failed : number = 0;

    getSummary() : string {
        return `${this.passed}/${this.failed+this.passed} tests passed`
    }

    hasFailures() : boolean { return this.failed != 0 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&amp;lt;/string&amp;gt;&amp;lt;/string&amp;gt;&amp;lt;/string&amp;gt;&amp;lt;/testresultsentity&amp;gt;&amp;lt;/testresultsentity&amp;gt;&lt;/p&gt;</content><author><name></name></author><summary type="html">In a previous post I showed how to add type-checking and unit tests to Firebase cloud code (cloud functions and database rules). Those tests are independent from any Firebase environment and independent from each other. We should be able to run them all quickly and consistently in a clean Node.js environment with a single command. We should also be able to chain that command with others so that we can build, test, and deploy each code commit directly into a live Firebase environment.</summary></entry><entry><title type="html">Types And Tests For Firebase Cloud Code</title><link href="/2017/09/22/types-and-tests-for-firebase-cloud-code.html" rel="alternate" type="text/html" title="Types And Tests For Firebase Cloud Code" /><published>2017-09-22T00:00:00+00:00</published><updated>2017-09-22T00:00:00+00:00</updated><id>/2017/09/22/types-and-tests-for-firebase-cloud-code</id><content type="html" xml:base="/2017/09/22/types-and-tests-for-firebase-cloud-code.html">&lt;p&gt;Firebase makes it cheap and easy to code custom functions and database access rules that run in the cloud along with their standard services.  This is great because you can try things out very quickly in a real, shared environment that performs at scale.  This simplicity make it tempting just to verify each change manually in the cloud environment.  I think static type-checking and independent unit tests are an even more appealing way to verify our code with confidence.  Here’s a recipe for eliminating dependencies on Firebase so we can run fast, automated tests before deploying code to the cloud.&lt;/p&gt;

&lt;h2 id=&quot;typescript--ide&quot;&gt;Typescript + IDE&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;Typescript&lt;/a&gt; is a superset of Javascript that compiles to plain Javascript.  It adds many useful language features like type annotations, interfaces, classes, and generics to Javascript.  All features are optional, so you can always ignore types and interop with plain Javascript when you want.&lt;/p&gt;

&lt;p&gt;Image we want have an app where we want to archive posts if they’ve been flagged too many times.  Let’s use a Typescript interface to decouple the Firebase dependency from as much of our code as we can.&lt;/p&gt;

&lt;p&gt;Say we have a PostEntity class like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class PostEntity {
    id : string;
    flags : number;
    maxFlags = 5;

    hasTooManyFlags() : boolean {
        return this.flags &amp;gt;= this.maxFlags
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and a function that fetches a post by id, determines if it has too many flags, and archives it if so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function archiveIfTooManyFlags(postId : string, datasource : PostDatasource) : Promise&amp;lt;void&amp;gt; {
    return datasource.getPost(postId)
        .then(post =&amp;gt; {
            if (post.hasTooManyFlags())
                return datasource.archivePost(post.id);
            else
                return Promise.resolve();
        })
}

interface PostDatasource {
    getPost(postId : string) : Promise&amp;lt;postentity&amp;gt;
    archivePost(postId : string) : Promise&amp;lt;void&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that we defined a PostDatasource &lt;em&gt;interface&lt;/em&gt; with methods getPost and archivePost.  We can write an implementation of that interface that uses Firebase as our datasource or we could write an implementation that uses something completely different.  All of the code we’ve written so far is independent of that implementation.&lt;/p&gt;

&lt;p&gt;Here’s what that implementation might look like using Firebase:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class PostDatasourceFb implements PostDatasource {
	db = require('firebase-admin').database();

    getPost(postId: string) : Promise&amp;lt;postentity&amp;gt; {
        return this.db.ref(`/posts/${postId}`).once('value')
	        .then(snap =&amp;gt; snap.val());
    }

    archivePost(postId: string): Promise&amp;lt;void&amp;gt; {
        return this.db.ref(`/posts/${postId}/isArchived`).set(true);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To execute this as a cloud function when a post is flagged in our Firebase Database we do this :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;exports.onFlaged = functions.database.ref('/posts/{postId}/flags')
	.onWrite(event =&amp;gt; {
	    return archiveIfTooManyFlags(
		    event.params.postId, 
		    new PostDatasourceFb()
		);
	});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In addition you can use a Typescript-aware IDE to make discovering the properties of your objects, language features and other javascript dependencies automatic as you write code.  If you’ve used any other OO language with a good IDE you’ll know what this means.  &lt;a href=&quot;https://www.jetbrains.com/webstorm/&quot;&gt;WebStorm&lt;/a&gt; is my choice because I’m already familiar with the shortcuts and organization of JetBrains tools, but there are &lt;a href=&quot;https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support&quot;&gt;many others&lt;/a&gt;.   They all support features like: instant type checking, code assist, inline refactoring, breakpoint debugging, object navigation, source control tracking, etc.&lt;/p&gt;

&lt;h2 id=&quot;mocha--chai--sinon&quot;&gt;Mocha + Chai + Sinon&lt;/h2&gt;
&lt;p&gt;Now that we have the language tools to decouple our application code from dependencies, we can set up unit tests that run locally outside of the Firebase cloud environment.  Our test libraries are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://mochajs.org/&quot;&gt;Mocha&lt;/a&gt; -  lets you describe and execute a set of unit tests.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://chaijs.com/&quot;&gt;Chai&lt;/a&gt; - lets you make assertions within each of those tests.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://sinonjs.org/&quot;&gt;Sinon&lt;/a&gt; - lets you create spies, stubs, and mocks for your test dependencies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s what a test for our archiveIfTooManyFlags function might look like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;describe('archiveIfTooManyFlags', () =&amp;gt; {
    it('should call archivePost when there are too many flags', async () =&amp;gt; {
        const sinon = require('sinon');
        const post = new PostEntity();
        post.flags = 7;
        const postDatasource = &amp;lt;postdatasource&amp;gt;{};
        postDatasource.getPost = sinon.stub().resolves(post);
        postDatasource.archivePost = sinon.stub().resolves(null);

        await archiveIfTooManyFlags(&quot;123&quot;, postDatasource);

        sinon.assert.calledWith(&amp;lt;sinonstub&amp;gt;postDatasource.archivePost, post.id);
        sinon.assert.calledWith(&amp;lt;sinonstub&amp;gt;postDatasource.getPost, &quot;123&quot;);
    });
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First we set up Sinon, and declare a PostDatasource and a PostEntity.  Since PostDatasource is an interface, we have to implement at least the methods we plan to use in our test.  We don’t want to use the PostDatasourceFb class from earlier, because it requires a Firebase environment.  We could write a second implementation from scratch that returns some mock values and keeps track of method calls, or we could let Sinon do most of that work for us.  Creating our PostDatasource as {} means it exists, but none of the methods have been implemented yet.  We use sinon.stub() to stub the behavior of the methods we plan to use: getPost and archivePost.  Finally we call archiveIfTooManyFlags and verify that getPost and archivePost were called with the expected arguments.&lt;/p&gt;

&lt;p&gt;Now we can run this test and others like it locally without connecting to Firebase.  This covers our cloud functions, but what about our database rules?&lt;/p&gt;

&lt;h2 id=&quot;targaryen&quot;&gt;Targaryen&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/goldibex/targaryen&quot;&gt;Targaryen&lt;/a&gt; lets us write the same kind of Mocha-based unit tests for our Firebase database rules.&lt;/p&gt;

&lt;p&gt;Here’s a rule for reading &amp;amp; writing to a post:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;rules&quot;: {
    &quot;.read&quot;: &quot;false&quot;,
    &quot;.write&quot;: &quot;false&quot;,
    &quot;posts&quot; :  {
      &quot;.read&quot;: &quot;true&quot;,
      &quot;$post&quot; : {
        &quot;.read&quot; : &quot;true&quot;,
        &quot;.write&quot;: &quot;auth != null &amp;amp;&amp;amp; (data.child('userID').val() == auth.uid || root.child('users/' + auth.uid + '/isAdmin').val() == true)&quot;,
        &quot;views&quot;:{
          &quot;.write&quot;:&quot;true&quot;
        }
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only admins and authors should be able to write to (edit) a post.  Targaryen lets us test this rule locally like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;describe('posts/aPostId', () =&amp;gt; {
    it(`can write if admin or author`, () =&amp;gt; {
        targaryen.setFirebaseData({
            users: {
                adminUser: {
                    isAdmin:true
                }
            },
            posts: {
                aPostId: {
                    userID:&quot;authorUser&quot;
                }
            }
        });

        expect({uid: 'adminUser'}).can.write.path('posts/aPostId');
        expect({uid: 'authorUser'}).can.write.path('posts/aPostId');
        expect({uid: 'randomUser'}).cannot.write.path('posts/aPostId');
        expect(null).cannot.write.path('posts/aPostId');
    });
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can cover all our cloud functions and all our database rules with fast, automated tests! Wouldn’t it be great if we had a single command that could confirm all our tests are passing, then deploy the code and results to our Firebase environment? I’ll write up my solution to this in a future post.&lt;/p&gt;</content><author><name></name></author><summary type="html">Firebase makes it cheap and easy to code custom functions and database access rules that run in the cloud along with their standard services. This is great because you can try things out very quickly in a real, shared environment that performs at scale. This simplicity make it tempting just to verify each change manually in the cloud environment. I think static type-checking and independent unit tests are an even more appealing way to verify our code with confidence. Here’s a recipe for eliminating dependencies on Firebase so we can run fast, automated tests before deploying code to the cloud.</summary></entry><entry><title type="html">Api Acceptance Tests With Cucumber And Rest Assured</title><link href="/2017/04/11/api-acceptance-tests-with-cucumber-and-rest-assured.html" rel="alternate" type="text/html" title="Api Acceptance Tests With Cucumber And Rest Assured" /><published>2017-04-11T00:00:00+00:00</published><updated>2017-04-11T00:00:00+00:00</updated><id>/2017/04/11/api-acceptance-tests-with-cucumber-and-rest-assured</id><content type="html" xml:base="/2017/04/11/api-acceptance-tests-with-cucumber-and-rest-assured.html">&lt;p&gt;On projects where multiple systems undergo development at the same time, it’s crucial to maintain a clear picture of how they should interact.  We commonly have a backend system providing a REST API to multiple frontends (browsers, mobile apps, chatbots, IoT, etc.).  Because it will likely change over time, keeping the API picture clear and up to date can be a significant challenge.  How can we efficiently describe the currently expected behavior and know if it’s working as expected so teams don’t spin their wheels due to miscommunication?&lt;/p&gt;

&lt;h2 id=&quot;cucumber&quot;&gt;Cucumber&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://cucumber.io&quot;&gt;Cucumber&lt;/a&gt; helps us write readable requirements upfront that can be tied directly to executable tests.  Here’s an example for a guestbook REST API:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Scenario: Read a list of guestbook entries

  Given I'm using the staging API environment
  And the guestbook has at least &quot;2&quot; entries
  When I make a GET request to &quot;/guestbook/entries&quot;
  Then I get a response code of &quot;200&quot;
  And I get a response with at least &quot;2&quot; entries
  And each entry has a &quot;name&quot;
  And each entry has a &quot;date&quot; formatted as a Unix timestamp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each line in the scenario above represents a discrete Cucumber step.  A developer can now write a short block of code to fulfill each step.&lt;/p&gt;

&lt;p&gt;There are options in various languages for fulfilling Cucumber step definitions (e.g. Ruby, Javascript, Python, .NET, Java).  I chose the Java implementation, &lt;a href=&quot;https://github.com/cucumber/cucumber-jvm&quot;&gt;Cucumber-JVM&lt;/a&gt;, for these reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Works with many out-of-the-box &lt;strong&gt;reporting and automation tools&lt;/strong&gt; - because it’s JUnit-based&lt;/li&gt;
  &lt;li&gt;Intuitive &lt;strong&gt;IDE support&lt;/strong&gt; for code assist, breakpoints, debugging, output formatting, etc. (Intellij and Eclipse)&lt;/li&gt;
  &lt;li&gt;Easy-to-build &lt;strong&gt;HTTP request and response assertions&lt;/strong&gt; using the &lt;a href=&quot;http://rest-assured.io/&quot;&gt;Rest-assured&lt;/a&gt; library&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;cucumber-on-java&quot;&gt;Cucumber on Java&lt;/h2&gt;
&lt;p&gt;Using Cucumber-JVM and the Intellij IDE, I get automatically generated step definitions like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public GuestbookStepDefinitions() {
	Given(&quot;^I'm using the staging API environment$&quot;, () -&amp;gt; {
		//short block of code goes here
	});
	
	When(&quot;^I make a GET request to \&quot;([^\&quot;]*)\&quot;$&quot;, (String path) -&amp;gt; {
		//another block here
	});
	
	Then(&quot;^I get a response code of \&quot;([^\&quot;]*)\&quot;$&quot;, (Integer code) -&amp;gt; {
		//and another
    });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next we fill in the implementations using Rest-assured…&lt;/p&gt;

&lt;h2 id=&quot;rest-assured&quot;&gt;Rest-assured&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public GuestbookStepDefinitions() {

    private RequestSpecification request;
    private ValidatableResponse response;
    
    @Before
    public void before(Scenario scenario) {
        request = RestAssured.with();
    }

	Given(&quot;^I'm using the staging API environment$&quot;, () -&amp;gt; {
		request.given()
	        .contentType(ContentType.JSON)
	        .baseUri(&quot;https://staging.mycompany.com&quot;);
	});
	
	When(&quot;^I make a GET request to \&quot;([^\&quot;]*)\&quot;$&quot;, (String path) -&amp;gt; {
		response = request.get(path + &quot;.json&quot;).then();
	});
	
	Then(&quot;^I get a response code of \&quot;([^\&quot;]*)\&quot;$&quot;, (Integer code) -&amp;gt; {
		response.statusCode(code);
    });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Given&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;When&lt;/code&gt; steps are building a request with details for our REST API.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Then&lt;/code&gt; step calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;response.statusCode(...)&lt;/code&gt; which is an assertion of the status code returned by the REST API.  If any step fails we get targeted feedback like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;java.lang.AssertionError: 1 expectation failed.
Expected status code  but was .


...
io.restassured.internal.ValidatableResponseOptionsImpl.statusCode(ValidatableResponseOptionsImpl.java:117)
	at GuestbookStepDefinitions.lambda$new$8(GuestbookStepDefinitions.java:66)
	at ✽.Then I get a response code of &quot;100&quot;(guestbook-entries-read.feature:12)

Failed scenarios:
guestbook-entries-read.feature:9 # Scenario: Read a list of guestbook entries

1 Scenarios (1 failed)
3 Steps (1 failed, 2 passed)
0m1.370s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This output is a bit verbose (we’ll worry about report formatting later), but contains important information about the failure.&lt;/p&gt;

&lt;p&gt;The step: we see that the “Then I get a response code of 100” step of our “Read a list of guestbook entries” scenario is where we’re failing.  That means the previous two steps passed successfully.&lt;/p&gt;

&lt;p&gt;The expectation:  we see that we got a  response code but expected a  response code.  If we change the expected status code back to 200, we should get a passing test:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Scenario: Read all guestbook entries          # guestbook-entries-read.feature:9
  Given I'm using the staging API environment # GuestbookStepDefinitions.java:89
  When I make a GET request to &quot;/guestbook&quot;   # GuestbookStepDefinitions.java:59
  Then I get a response code of &quot;200&quot;         # GuestbookStepDefinitions.java:65

1 Scenarios (1 passed)
3 Steps (3 passed)
0m1.937s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since we’re making HTTP calls it’d be nice to see the request and response details too.  We can tell Rest-assured to print those along with our test results:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Request method:	GET
Request URI:	https://staging.mycompany.com/guestbook/entries.json
Proxy:			&amp;lt;none&amp;gt;
Request params:	&amp;lt;none&amp;gt;
Query params:	&amp;lt;none&amp;gt;
Form params:	&amp;lt;none&amp;gt;
Path params:	&amp;lt;none&amp;gt;
Multiparts:		&amp;lt;none&amp;gt;
Headers:		Accept=*/*
				Content-Type=application/json; charset=UTF-8
Cookies:		&amp;lt;none&amp;gt;
Body:			&amp;lt;none&amp;gt;
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Apr 2017 19:09:16 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 4830
Connection: keep-alive
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Strict-Transport-Security: max-age=31556926; includeSubDomains; preload
{
    &quot;-KgBbHUcv2NWn2M6tzGp&quot;: {
        &quot;comment&quot;: &quot;Hello Guestbook&quot;,
        &quot;name&quot;: &quot;Test User&quot;,
        &quot;timestamp&quot;: 1490565277672
    },
    &quot;-KgBbzZE2WtRD9wz1t-D&quot;: {
        &quot;comment&quot;: &quot;Hello Guestbook&quot;,
        &quot;name&quot;: &quot;Test User&quot;,
        &quot;timestamp&quot;: 1490565462287
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reporting&quot;&gt;Reporting&lt;/h2&gt;
&lt;p&gt;Now when we run this test we immediately know three things:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;What we expect to happen&lt;/strong&gt; (the Given-When-Then statement)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;How to make it happen&lt;/strong&gt; (the printed request and response)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Is it currently working as expected&lt;/strong&gt; (Pass or Fail)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Having this feedback continuously throughout development mitigates communication issues early before teams waste time heading in different directions.  The easy-to-read Cucumber steps that everyone can read tie directly to the gritty HTTP definitions that developers need and we can drop it on a CI server to generate formatted reports visible to the whole team.&lt;/p&gt;

&lt;p&gt;Here’s an example of formatted results from the Intellij IDE:&lt;/p&gt;
&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;728&quot; data-orig-width=&quot;1188&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/ide-cucumber-output.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/2b9505cb00c137a2246a8f353a981c3d/tumblr_inline_pjzq05TyS81r4ik0y_540.png&quot; width=&quot;600px&quot; data-orig-height=&quot;728&quot; data-orig-width=&quot;1188&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/ide-cucumber-output.png&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;On the left we have a collapsible, colored outline of our features, scenarios, and steps.  We can select anything in the tree and see corresponding details on the right.&lt;/p&gt;

&lt;p&gt;And here’s a standalone HTML report:&lt;/p&gt;
&lt;figure class=&quot;tmblr-full&quot; data-orig-height=&quot;1410&quot; data-orig-width=&quot;1896&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/web-cucumber-output.png&quot;&gt;&lt;img src=&quot;https://64.media.tumblr.com/116c8b133d374021376065b667d1341d/tumblr_inline_pjzq06uSaT1r4ik0y_540.png&quot; width=&quot;600px&quot; data-orig-height=&quot;1410&quot; data-orig-width=&quot;1896&quot; data-orig-src=&quot;https://sandbox-9221c.firebaseapp.com/blog/web-cucumber-output.png&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;Again we have a collapsible, colored outline that documents the expected behavior and HTTP details.&lt;/p&gt;

&lt;h2 id=&quot;process&quot;&gt;Process&lt;/h2&gt;
&lt;p&gt;This approach is designed drive collaboration early in the process so it’s a great chance to work in pairs.  Pairing a frontend developer and a backend developer can help start the conversation about how systems should interact.  Getting other roles like analysts, designers, and testers involved can level-set everyone’s understanding of how the product is supposed to work.   As soon as we have requirements for our first feature, we can start writing tests.  The code required to fulfill step definitions should be easy enough for any developer to pick up quickly regardless of language choice.  I prefer to put API acceptance tests in a separate repository apart from any other production code.   This limits external dependencies from affecting our ability to write and run the tests.&lt;/p&gt;</content><author><name></name></author><summary type="html">On projects where multiple systems undergo development at the same time, it’s crucial to maintain a clear picture of how they should interact. We commonly have a backend system providing a REST API to multiple frontends (browsers, mobile apps, chatbots, IoT, etc.). Because it will likely change over time, keeping the API picture clear and up to date can be a significant challenge. How can we efficiently describe the currently expected behavior and know if it’s working as expected so teams don’t spin their wheels due to miscommunication?</summary></entry><entry><title type="html">Serverless Apps With Firebase</title><link href="/2017/03/17/serverless-apps-with-firebase.html" rel="alternate" type="text/html" title="Serverless Apps With Firebase" /><published>2017-03-17T00:00:00+00:00</published><updated>2017-03-17T00:00:00+00:00</updated><id>/2017/03/17/serverless-apps-with-firebase</id><content type="html" xml:base="/2017/03/17/serverless-apps-with-firebase.html">&lt;p&gt;&lt;a href=&quot;http://firebase.google.com&quot;&gt;Firebase&lt;/a&gt; is a set of backend platform services (owned by Google and closely integrated with the Google Cloud Platform) for building web and mobile apps.  They have SDKs for Android, iOS, web, C++, Unity, Node.js, and Java.  Their generous free tier makes it easy to launch fully functional apps to a modest user base without cost.&lt;/p&gt;

&lt;p&gt;Free and unlimited features include: 
Authentication, Analytics, App Indexing, Cloud Messaging, Crash Reporting, Dynamic Links, Notifications, Remote Config&lt;/p&gt;

&lt;p&gt;Free features with usage limits: 
Realtime Database, Cloud Functions, Hosting, Storage, Test Lab&lt;/p&gt;

&lt;p&gt;There is way too much to cover here.  If you want all the details, their &lt;a href=&quot;https://firebase.google.com/docs/database/&quot;&gt;website docs&lt;/a&gt; are some of the best I’ve encountered.  You can also demo many features right from the &lt;a href=&quot;https://console.firebase.google.com/&quot;&gt;web console&lt;/a&gt;.  Here are a few of the highlights that I think can considerably reduce effort and improve quality for app development.&lt;/p&gt;

&lt;h2 id=&quot;sign-inup-simply&quot;&gt;Sign in/up simply&lt;/h2&gt;
&lt;p&gt;Firebase Authentication provides email, social, anonymous, and custom sign in methods out of the box.  Accounts can be managed and each method enabled or disabled from the Firebase web console.   Access tokens are based on the JWT feature of OpenID Connect which encrypts portable authorization data in each token.  This means multi-system architectures can share tokens and without the expense of server-to-server callbacks on client requests.&lt;/p&gt;

&lt;h2 id=&quot;realtime-apps-are-no-longer-a-luxury&quot;&gt;Realtime apps are no longer a luxury&lt;/h2&gt;
&lt;p&gt;The Realtime Database is a NoSQL cloud database with REST and SDK (websocket) support.  Data is synced across all clients in realtime, and remains available even when offline.   Network calls, cache updates, device resources, and intermittent connectivity are managed automatically by the SDK.  Clients simply listen for data changes and react with UI updates.&lt;/p&gt;

&lt;h2 id=&quot;free-backend---if-needed&quot;&gt;Free backend - if needed&lt;/h2&gt;
&lt;p&gt;For the most part Firebase requires no server-side code, but if you want something to be handled in a trusted backend environment (e.g. push notification logic), there are two relatively simple and free-tier options: Cloud Functions and App Engine.  Cloud Functions is a hosted, private, and scalable Node.js environment where you can run JavaScript code and interact with Firebase.   App Engine is a hosted, private, and scalable environment that supports Java, Python, PHP, and Go.  If you’re building an Android app, App Engine is a convenient option because your Java code and IDE tools can be shared between the two.&lt;/p&gt;

&lt;h2 id=&quot;deep-links-that-survive-installs&quot;&gt;Deep links that survive installs&lt;/h2&gt;
&lt;p&gt;A Dynamic Link is a deep link that can survive the optional app installation step (on Android and iOS) or fall back to a web link if the user is on a desktop machine.  Firebase will generate short links that contain all the details required.  This works great for letting users invite their friends to an app or tracking referral codes.&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Serverless isn’t the right approach for every situation, but the potential for reduced effort, early feedback, and tighter operational management is compelling - especially in the early life stages of an app.  Firebase is one of the most complete Backend-as-a-Service platforms, but the field is still fairly new.  The competition will evolve and so will your app.  Design principles like &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_inversion_principle&quot;&gt;dependency inversion&lt;/a&gt; can help minimize these future risks.&lt;/p&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;https://scotch.io/bar-talk/a-look-at-the-new-firebase-a-powerful-google-platform&lt;/li&gt;
  &lt;li&gt;https://firebase.google.com/docs/&lt;/li&gt;
  &lt;li&gt;https://martinfowler.com/articles/serverless.html&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">Firebase is a set of backend platform services (owned by Google and closely integrated with the Google Cloud Platform) for building web and mobile apps. They have SDKs for Android, iOS, web, C++, Unity, Node.js, and Java. Their generous free tier makes it easy to launch fully functional apps to a modest user base without cost.</summary></entry><entry><title type="html">Reuse Android Code Without Remote Dependencies</title><link href="/2016/11/11/reuse-android-code-without-remote-dependencies.html" rel="alternate" type="text/html" title="Reuse Android Code Without Remote Dependencies" /><published>2016-11-11T00:00:00+00:00</published><updated>2016-11-11T00:00:00+00:00</updated><id>/2016/11/11/reuse-android-code-without-remote-dependencies</id><content type="html" xml:base="/2016/11/11/reuse-android-code-without-remote-dependencies.html">&lt;p&gt;You’re starting to write similar code project after project and think it would be useful to establish some base components that can be reused across multiple projects.  First you create a library module to isolate your code.  Then you need to figure out how you’re going to include it in each project.&lt;/p&gt;

&lt;p&gt;If it’s open source, hosting it in a public maven repository like JCenter/Maven Central is a good solution.  If the code can’t be shared publicly, the simplest way I’ve found is this:&lt;/p&gt;

&lt;p&gt;[[MORE]]&lt;/p&gt;

&lt;h2 id=&quot;step-1&quot;&gt;Step 1&lt;/h2&gt;
&lt;p&gt;Copy the packaged library file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;MyReusableLibrary/build/outputs/aar/MyReusableLibrary-release.aar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and paste it into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/libs&lt;/code&gt; directory of each project you want to use it in.&lt;/p&gt;

&lt;h2 id=&quot;step-2&quot;&gt;Step 2&lt;/h2&gt;
&lt;p&gt;Add the following to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/build.gradle&lt;/code&gt; of each project&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;repositories {
    ...
    flatDir {
        dirs 'libs'
    }
}

dependencies {
	...
	compile ':MyReusableLibrary-release.aar
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-i-like-about-it&quot;&gt;What I like about it&lt;/h2&gt;
&lt;p&gt;It’s self-contained for library consumers.  If a developer tries to download and build a project that uses this library, there are no additional commands to run and no extra credentials to track down.&lt;/p&gt;

&lt;p&gt;It’s low maintenance for library providers.  You can host the aar files directly in your source repository or wherever else makes sense.  You don’t need to worry about maintaining a private maven server.&lt;/p&gt;

&lt;h2 id=&quot;what-i-dont-like-about-it&quot;&gt;What I don’t like about it&lt;/h2&gt;
&lt;p&gt;It doesn’t include transitive dependencies automatically.  Since there is no associated pom file, you need to describe them along with your library.  If the example library above depended on the Android Support Library, the project dependencies would need to include both:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dependencies {
	...
	compile ':MyReusableLibrary-release.aar
	compile 'com.android.support:appcompat-v7:24.2.0'
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;additional-tips&quot;&gt;Additional tips&lt;/h2&gt;
&lt;p&gt;Add the following to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; of your library module to store versioned aar files:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;android {
	defaultConfig {
		versionName &quot;1.0&quot;
	}
    buildTypes {
        release {
            archivesBaseName = &quot;${project.name}-${android.defaultConfig.versionName}&quot;
        }
    }
}

task copyAar(type: Copy) {
    from('build/outputs/aar')
    into('../app/libs')
    include(archivesBaseName + '-release.aar')
}
copyAar.dependsOn assemble
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./gradlew copyAar&lt;/code&gt; assembles the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MyResuableLibrary-1.0-release.aar&lt;/code&gt; and copies it to the libs folder.&lt;/p&gt;

&lt;p&gt;Have a sample app module in your library project so you can test your library before using it in other projects.  See the &lt;a href=&quot;https://github.com/square/picasso&quot;&gt;Picasso library&lt;/a&gt; from Square (or many of the other Android library projecst on Github) as an example.  The /picasso directory is the library and /picasso-sample directory is the sample app.  You can also use this sample app module to test the flatDir dependency approach described above.&lt;/p&gt;</content><author><name></name></author><summary type="html">You’re starting to write similar code project after project and think it would be useful to establish some base components that can be reused across multiple projects. First you create a library module to isolate your code. Then you need to figure out how you’re going to include it in each project.</summary></entry></feed>