Jekyll2023-01-31T11:13:36-05:00https://americanexpress.io/American Express TechnologyAmerican Express Technology Open Source and BlogCleaner Unit Tests with Custom Matchers2023-01-09T00:00:00-05:002023-01-09T00:00:00-05:00https://americanexpress.io/cleaner-unit-tests-with-custom-matchers<p>When unit testing, it’s important to cover all your edge cases, but that can come
at a cost. Covering edge cases often means making the same or similar assertions
over and over again. While test names should clearly describe what is being tested,
sometimes these assertions can be messy and have an unclear purpose. Using custom
matchers in your tests can help make your assertions cleaner and less ambiguous.</p>
<blockquote>
<p>Note: the example used in this article is written using the <a href="https://jestjs.io/">Jest</a>
testing framework.</p>
</blockquote>
<p>Let’s take a look at an example. I needed to test several cases to see if
<a href="https://www.npmjs.com/package/cacheable-lookup"><code class="highlighter-rouge">cacheable-lookup</code></a> was installed
on an <a href="https://nodejs.org/api/http.html#class-httpagent"><code class="highlighter-rouge">Agent</code></a>. <code class="highlighter-rouge">cacheable-lookup</code>
adds some symbol properties to any <code class="highlighter-rouge">Agent</code> it’s installed on. We just need to look
at the agent’s symbol properties and see if they exist there. The assertion may
look something like this:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">expect</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">)).</span><span class="nx">toEqual</span><span class="p">(</span><span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">));</span>
</code></pre>
</div>
<p>So when we are testing that <code class="highlighter-rouge">cacheable-lookup</code> gets successfully uninstalled our spec
would be similar to the below.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">it</span><span class="p">(</span><span class="s1">'should uninstall cacheable lookup when DNS cache is not enabled and cacheable lookup is installed'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">installCacheableLookup</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">)).</span><span class="nx">toEqual</span><span class="p">(</span><span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">));</span>
<span class="nx">expect</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">https</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">)).</span><span class="nx">toEqual</span><span class="p">(</span><span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">));</span>
<span class="nx">setupDnsCache</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">)).</span><span class="nx">not</span><span class="p">.</span><span class="nx">toEqual</span><span class="p">(</span><span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">));</span>
<span class="nx">expect</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">https</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">)).</span><span class="nx">not</span><span class="p">.</span><span class="nx">toEqual</span><span class="p">(</span><span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">));</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Now we’ve got a working test, but it’s quite repetitive and a little hard to read, a problem
that will just be exacerbated when we add more use cases. It’s also not very clear to the next
engineer to come across our code what the significance is of each of these assertions.
<a href="https://www.merriam-webster.com/dictionary/grok">Grokable</a> tests can act as an extension of
your documentation, and we’re missing out on that here. Let’s refactor this with a custom matcher
to make it DRY, more readable, and more easily comprehendable.</p>
<p>We’ll do this by calling <a href="https://jestjs.io/docs/expect#expectextendmatchers"><code class="highlighter-rouge">expect.extend</code></a>,
and to keep things simple we’ll reuse the same <code class="highlighter-rouge">toEqual</code> matcher from before. Reusing the
built-in matchers means that there are fewer implementation details for us to worry about in
our custom matcher.</p>
<p>Keeping the matcher in the same file as the tests will reduce indirection and keep the tests
grokable. It’s important that we keep it easy for others to understand what exactly the matcher
is doing, and, since the matcher is added globally to expect, that can become difficult if we
move the matcher to a different file.</p>
<p>Now, let’s give the matcher a really explicit name that tells us exactly what the assertion
is checking for, <code class="highlighter-rouge">toHaveCacheableLookupInstalled</code>.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="nx">matchers</span> <span class="nx">from</span> <span class="s1">'expect/build/matchers'</span><span class="p">;</span>
<span class="nx">expect</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
<span class="nx">toHaveCacheableLookupInstalled</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">matchers</span><span class="p">.</span><span class="nx">toEqual</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span>
<span class="k">this</span><span class="p">,</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">),</span>
<span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">)</span>
<span class="p">);</span>
<span class="p">},</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Now that we have our custom matcher, we’re ready to refactor those assertions.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">it</span><span class="p">(</span><span class="s1">'should uninstall cacheable lookup when DNS cache is not enabled and cacheable lookup is installed'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">installCacheableLookup</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">http</span><span class="p">).</span><span class="nx">toHaveCacheableLookupInstalled</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">https</span><span class="p">).</span><span class="nx">toHaveCacheableLookupInstalled</span><span class="p">();</span>
<span class="nx">setupDnsCache</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">http</span><span class="p">).</span><span class="nx">not</span><span class="p">.</span><span class="nx">toHaveCacheableLookupInstalled</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">https</span><span class="p">).</span><span class="nx">not</span><span class="p">.</span><span class="nx">toHaveCacheableLookupInstalled</span><span class="p">();</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Now our tests are cleaner, but our failure message is not great. Reusing a built-in matcher
worked well for us to get things running quickly, but it does have its limitations. Take a
look at what we see if we comment out the function that is uninstalling <code class="highlighter-rouge">cacheable-lookup</code>.</p>
<div class="highlighter-rouge"><pre class="highlight"><code> ● setupDnsCache › should uninstall cacheable lookup when DNS cache is not enabled and cacheable lookup is installed
expect(received).not.toEqual(expected) // deep equality
Expected: not ArrayContaining [Symbol(cacheableLookupCreateConnection), Symbol(cacheableLookupInstance)]
Received: [Symbol(kCapture), Symbol(cacheableLookupCreateConnection), Symbol(cacheableLookupInstance)]
59 | expect(https).toHaveCacheableLookupInstalled();
60 | // setupDnsCache();
> 61 | expect(http).not.toHaveCacheableLookupInstalled();
| ^
62 | expect(https).not.toHaveCacheableLookupInstalled();
63 | });
64 |
</code></pre>
</div>
<p>It’s the same as before the refactor, but now it’s worse because the matcher hint still
says <code class="highlighter-rouge">toEqual</code> even though we’re now using <code class="highlighter-rouge">toHaveCacheableLookupInstalled</code>. If we were to
write a custom matcher from scratch we could make this test more effective. We can fix the
hint and add a custom error message with a more explicit description of the failure.</p>
<div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">expect</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
<span class="nx">toHaveCacheableLookupInstalled</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">isNot</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="na">secondArgument</span><span class="p">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">isNot</span> <span class="p">};</span>
<span class="kr">const</span> <span class="nx">pass</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">equals</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">),</span> <span class="nx">expect</span><span class="p">.</span><span class="nx">arrayContaining</span><span class="p">(</span><span class="nx">cacheableLookupSymbols</span><span class="p">))</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">pass</span><span class="p">,</span>
<span class="na">message</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="err">`</span><span class="nx">$</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">utils</span><span class="p">.</span><span class="nx">matcherHint</span><span class="p">(</span><span class="s1">'toHaveCacheableLookupInstalled'</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span>
<span class="p">}</span><span class="err">\</span><span class="nx">n</span><span class="err">\</span><span class="nx">nExpected</span> <span class="nx">agent</span> <span class="nx">$</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">isNot</span> <span class="p">?</span> <span class="s1">'not '</span> <span class="p">:</span> <span class="s1">''</span><span class="p">}</span><span class="nx">to</span> <span class="nx">have</span> <span class="nx">cacheable</span><span class="o">-</span><span class="nx">lookup</span><span class="err">'</span><span class="nx">s</span> <span class="nx">symbols</span> <span class="nx">present</span><span class="err">`</span><span class="p">,</span>
<span class="p">};</span>
<span class="p">},</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Here we’ve used <a href="https://jestjs.io/docs/expect#thisequalsa-b"><code class="highlighter-rouge">this.equals</code></a> to do our comparison,
and <a href="https://jestjs.io/docs/expect#thisutils"><code class="highlighter-rouge">this.utils.matcherHint</code></a> to fix the name of our
matcher in the hint. <code class="highlighter-rouge">this.utils.matcherHint</code> is not very well documented, so you may have to
<a href="https://github.com/facebook/jest/blob/6094810c9d571686447c2320ba8c150add414e1b/packages/jest-matcher-utils/src/index.ts#L512">source dive</a>
to better understand the API. The order of arguments is <code class="highlighter-rouge">matcherName</code>, <code class="highlighter-rouge">received</code>, <code class="highlighter-rouge">expected</code>, and
finally <code class="highlighter-rouge">options</code>. Using an empty string for <code class="highlighter-rouge">expected</code> prevents the hint from looking like our matcher
requires an expected value.</p>
<p>See how greatly this improved our error message:</p>
<div class="highlighter-rouge"><pre class="highlight"><code> ● setupDnsCache › should uninstall cacheable lookup when DNS cache is not enabled and cacheable lookup is installed
expect(received).not.toHaveCacheableLookupInstalled()
Expected agent not to have cacheable-lookup's symbols present
61 | expect(https).toHaveCacheableLookupInstalled();
62 | // setupDnsCache();
> 63 | expect(http).not.toHaveCacheableLookupInstalled();
| ^
64 | expect(https).not.toHaveCacheableLookupInstalled();
65 | });
66 |
</code></pre>
</div>
<p>We’ve already made some great improvements to our test suite, but we can make it even better. By
further customizing our matcher and getting away from the simple <code class="highlighter-rouge">this.equals</code>, we can make our
test assert not only that all of the symbols are present when <code class="highlighter-rouge">cacheable-lookup</code> is installed, but
that <em>none</em> of them are present when it shouldn’t be installed rather than just “not all of them.”
We’ll use <code class="highlighter-rouge">this.isNot</code> to conditionally use <code class="highlighter-rouge">Array.prototype.some</code> or <code class="highlighter-rouge">Array.prototype.every</code>
when we look for the symbols on the agent depending on whether <code class="highlighter-rouge">cacheable-lookup</code> should be installed.</p>
<div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">expect</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
<span class="nx">toHaveCacheableLookupInstalled</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">isNot</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="na">secondArgument</span><span class="p">:</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">isNot</span> <span class="p">};</span>
<span class="kr">const</span> <span class="nx">agentSymbols</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertySymbols</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">globalAgent</span><span class="p">);</span>
<span class="kr">const</span> <span class="nx">pass</span> <span class="o">=</span> <span class="nx">isNot</span>
<span class="p">?</span> <span class="nx">cacheableLookupSymbols</span><span class="p">.</span><span class="nx">some</span><span class="p">((</span><span class="nx">symbol</span><span class="p">)</span> <span class="o">=></span> <span class="nx">agentSymbols</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">symbol</span><span class="p">))</span>
<span class="p">:</span> <span class="nx">cacheableLookupSymbols</span><span class="p">.</span><span class="nx">every</span><span class="p">((</span><span class="nx">symbol</span><span class="p">)</span> <span class="o">=></span> <span class="nx">agentSymbols</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">symbol</span><span class="p">));</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">pass</span><span class="p">,</span>
<span class="na">message</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="err">`</span><span class="nx">$</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">utils</span><span class="p">.</span><span class="nx">matcherHint</span><span class="p">(</span><span class="s1">'toHaveCacheableLookupInstalled'</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span>
<span class="p">}</span><span class="err">\</span><span class="nx">n</span><span class="err">\</span><span class="nx">nExpected</span> <span class="nx">agent</span> <span class="nx">$</span><span class="p">{</span><span class="nx">isNot</span> <span class="p">?</span> <span class="s1">'not '</span> <span class="p">:</span> <span class="s1">''</span><span class="p">}</span><span class="nx">to</span> <span class="nx">have</span> <span class="nx">cacheable</span><span class="o">-</span><span class="nx">lookup</span><span class="err">'</span><span class="nx">s</span> <span class="nx">symbols</span> <span class="nx">present</span><span class="err">`</span><span class="p">,</span>
<span class="p">};</span>
<span class="p">},</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Now on top of having a clean, DRY test that’s easy to understand and a matcher that we can reuse
throughout the rest of our test suite, we have assertions that are even more effective than the
simple (but hard to read) <code class="highlighter-rouge">toEqual</code> check we started with.</p>
<p>Remember, keeping your custom matcher at the top of the same file that the tests using it are in is
vital to its usefulness. If you do not, other engineers may not know that it is a custom matcher
and not know where it comes from. The last thing you want is for your teammates to waste hours
searching the internet for documentation on a matcher that doesn’t exist outside your codebase.
It’s also important that your matcher is easily understandable. Personally I’m partial to
<code class="highlighter-rouge">cacheableLookupSymbols.every(agentSymbols.includes.bind(this))</code>, but being explicit in our matcher
provides more value than being terse.</p>
<p>Check out the original <a href="https://github.com/americanexpress/one-app/pull/727">pull request</a>
to <a href="https://github.com/americanexpress/one-app">One App</a> that inspired this blog post.</p>Jamie KingAdvanced Kotlin - Part 2 - Use-Site Targets2019-12-03T00:00:00-05:002019-12-03T00:00:00-05:00https://americanexpress.io/advanced-kotlin-use-site-targets<h1 id="annotation-use-site-targets">Annotation Use-Site targets</h1>
<p>This is our second entry in our on-going “Advanced Kotlin” blog series.
Be sure to check out our first post; <a href="https://americanexpress.io/advanced-kotlin-delegates/">Advanced Kotlin - Delegates</a> if you haven’t yet.</p>
<p>In this post we’re going to take a deep-dive into Kotlin Annotation <a href="https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets">Use-Site targets</a>.</p>
<p>You’ve probably used <code class="highlighter-rouge">@get</code> and <code class="highlighter-rouge">@set</code> in Kotlin before, but have you come across <code class="highlighter-rouge">@receiver</code> or <code class="highlighter-rouge">@delegate</code>?
Kotlin provides us with nine different Annotation use-site targets. In this post we’ll cover all of them.
By writing Kotlin code that uses each of these annotation use-site targets and then decompiling from Kotlin into Java using the <code class="highlighter-rouge">Show Kotlin Bytecode -> Decompile</code> tool in IntelliJ we’ll see exactly where each annotation ends up in the resulting code.</p>
<h2 id="the-basics">The Basics</h2>
<p>But first, what exactly are use-site targets and why do we need them?</p>
<p>Many of the libraries, frameworks, and tools we use in Kotlin are actually designed for Java.
Either at compile time or at runtime a library may require an annotation to be in a very specific place in your code and/or bytecode for it to function correctly.
However, Kotlin is not Java and therefore doesn’t have some of the constructs expected in a Java program, and Kotlin also has some new constructs which are not available to Java.
We can use annotation use-site targets to bridge this gap so that various libraries will work as expected.</p>
<p>Simply put, annotation use-site targets allow any <code class="highlighter-rouge">@Annotations</code> in your source code to end up at a very specific place in your compiled bytecode or in the Java code generated by <code class="highlighter-rouge">kapt</code>.</p>
<h2 id="a-simple-example">A Simple Example</h2>
<p>Let’s start with a simple example that many of you may have already written yourselves:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@get</span><span class="p">:</span><span class="n">SomeAnnotation</span>
<span class="kd">var</span> <span class="py">someProperty</span><span class="p">:</span> <span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
</code></pre>
</div>
<p>By prefixing the annotation with <code class="highlighter-rouge">@get:</code> the resulting bytecode will have the annotation on the generated getter function:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="c1">// Decompiled from the resulting Kotlin Bytecode</span>
<span class="nd">@SomeAnnotation</span>
<span class="nd">@Nullable</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getSomeProperty</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">someProperty</span><span class="o">;</span>
<span class="o">}</span>
</code></pre>
</div>
<p>However, the member variable, the setter function, and any function parameters will not have the <code class="highlighter-rouge">SomeAnnotation</code> annotation.
In many cases this may be what a framework requires, be it <code class="highlighter-rouge">@get:Rule</code> for a JUnit test, <code class="highlighter-rouge">@get:ColorRes</code> for an Android resource, or <code class="highlighter-rouge">@get:GET</code> for a Retrofit interface.</p>
<h2 id="overview">Overview</h2>
<p>In this article we’ll be looking at all nine of the annotation use-site targets available in Kotlin:</p>
<ul>
<li><code class="highlighter-rouge">@get</code></li>
<li><code class="highlighter-rouge">@set</code></li>
<li><code class="highlighter-rouge">@file</code></li>
<li><code class="highlighter-rouge">@param</code></li>
<li><code class="highlighter-rouge">@field</code></li>
<li><code class="highlighter-rouge">@setparam</code></li>
<li><code class="highlighter-rouge">@receiver</code></li>
<li><code class="highlighter-rouge"><span class="k">@property</span></code></li>
<li><code class="highlighter-rouge">@delegate</code></li>
</ul>
<p>Some of these will be either familiar or obvious, such as <code class="highlighter-rouge">@get</code> and <code class="highlighter-rouge">@set</code>, but some are less obvious and less used, such as <code class="highlighter-rouge">@delegate</code> and <code class="highlighter-rouge">@receiver</code>.
Knowing all of the above is good knowledge to have even if you’ll only use it a handful of times.</p>
<p>We will be using the same method as used above with the <code class="highlighter-rouge">@get</code> example in order to test where an annotation resides in decompiled bytecode when using each use-site targets.
Each example will begin with an annotation that can be used in our sample code that matches the use-site target name so that it’s easy to spot:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">GetAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">SetAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">PropertyAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">ReceiverAnnotation</span>
<span class="o">..</span><span class="p">.</span><span class="n">etc</span><span class="o">..</span><span class="p">.</span>
</code></pre>
</div>
<p>We’ll then add the matching use-site target to the annotation in some sample Kotlin code, decompile the bytecode and see where the resulting annotation lives.</p>
<p>You may notice that many items on this list closely match Java naming conventions (getters, setters, parameters, etc) as they are intended to help facilitate Kotlin-Java interop.
Kotlin’s annotation use-site targets currently only affect JVM bytecode not Kotlin/native, Kotlin/js, or Kotlin Multiplatform projects.
This may change in the future, especially for multiplatform language targets such as Swift.</p>
<h2 id="get-and-set-use-site-targets">Get and Set use-site targets</h2>
<p>Let’s start with the few annotation use-site targets that you’ve probably already seen or used.
As an added bonus I’ll also include how you can provide multiple annotations to a single use-site target using <code class="highlighter-rouge">[]</code> brackets.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">GetAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">SetAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">SetAnnotation2</span>
<span class="kd">class</span> <span class="nc">Person</span><span class="p">(</span>
<span class="n">@get</span><span class="p">:</span><span class="n">GetAnnotation</span> <span class="kd">val</span> <span class="py">first</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span>
<span class="n">@set</span><span class="p">:[</span><span class="n">SetAnnotation</span> <span class="n">SetAnnotation2</span><span class="p">]</span> <span class="kd">var</span> <span class="py">last</span><span class="p">:</span> <span class="n">String</span>
<span class="p">)</span> <span class="p">{</span>
<span class="c1">// ...
</span><span class="p">}</span>
</code></pre>
</div>
<p>The resulting decompiled bytecode is as follows:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Person</span> <span class="o">{</span>
<span class="nd">@NotNull</span> <span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">first</span><span class="o">;</span>
<span class="nd">@NotNull</span> <span class="kd">private</span> <span class="n">String</span> <span class="n">last</span><span class="o">;</span>
<span class="nd">@GetAnnotation</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getFirst</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">first</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getLast</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">last</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@SetAnnotation</span>
<span class="nd">@SetAnnotation2</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kt">void</span> <span class="nf">setLast</span><span class="o">(</span><span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">var1</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">last</span> <span class="o">=</span> <span class="n">var1</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nf">Person</span><span class="o">(</span><span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">first</span><span class="o">,</span> <span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">last</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">first</span> <span class="o">=</span> <span class="n">first</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">last</span> <span class="o">=</span> <span class="n">last</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>As you can see, the <code class="highlighter-rouge">@GetAnnotation</code> is on the getter and both <code class="highlighter-rouge">@SetAnnotation</code> and <code class="highlighter-rouge">@SetAnnotation2</code> are on the setter. They don’t appear anywhere else in the code.</p>
<h2 id="file-use-site-targets">File use-site targets</h2>
<p><code class="highlighter-rouge">@file</code> is most commonly used with <code class="highlighter-rouge">@file:JvmName</code> in order to provide a custom name for a file.
This is useful when a file only contains top-level functions or constants.
In this case the Kotlin compiler creates a class called <code class="highlighter-rouge">YourFileNameKt</code>, which ends with <code class="highlighter-rouge">Kt</code>.
This can look odd when used from Java:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@file</span><span class="p">:</span><span class="n">JvmName</span><span class="p">(</span><span class="s">"HttpConstants"</span><span class="p">)</span>
<span class="k">const</span> <span class="kd">val</span> <span class="py">HTTP_OK</span> <span class="p">=</span> <span class="m">200</span>
<span class="k">const</span> <span class="kd">val</span> <span class="py">HTTP_NOT_FOUND</span> <span class="p">=</span> <span class="m">404</span>
</code></pre>
</div>
<p>Without the above <code class="highlighter-rouge">@file:JvmName</code> annotation the usage of these constants from java would appear as <code class="highlighter-rouge">HttpConstantsKt.HTTP_OK</code> instead of <code class="highlighter-rouge">HttpConstants.HTTP_OK</code>.</p>
<p>The <code class="highlighter-rouge">@file</code> use-site target can also be used with other annotations, but since this annotation does not end up in the resulting bytecode it would normally be used by Kotlin-specific tools and libraries, not Java ones.
An example of this would be using <code class="highlighter-rouge">@file:Suppress</code> to suppress lint or <a href="https://arturbosch.github.io/detekt/">detekt</a> rules for an entire file.</p>
<h2 id="field-and-parameter-use-site-targets">Field and Parameter use-site targets</h2>
<p>Let’s look at how <code class="highlighter-rouge">@param</code> and <code class="highlighter-rouge">@field</code> affect resulting bytecode by using both in a single piece of code on similar class properties:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">ParamAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">FieldAnnotation</span>
<span class="kd">class</span> <span class="nc">Person</span><span class="p">(</span>
<span class="n">@param</span><span class="p">:</span><span class="n">ParamAnnotation</span> <span class="kd">val</span> <span class="py">first</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span>
<span class="n">@field</span><span class="p">:</span><span class="n">FieldAnnotation</span> <span class="kd">val</span> <span class="py">last</span><span class="p">:</span> <span class="n">String</span>
<span class="p">)</span> <span class="p">{</span>
<span class="c1">// ...
</span><span class="p">}</span>
</code></pre>
</div>
<p>The resulting decompiled bytecode is:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Person</span> <span class="o">{</span>
<span class="nd">@NotNull</span> <span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">first</span><span class="o">;</span>
<span class="nd">@FieldAnnotation</span>
<span class="nd">@NotNull</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">last</span><span class="o">;</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getFirst</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">first</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getLast</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">last</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nf">Person</span><span class="o">(</span><span class="nd">@ParamAnnotation</span> <span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">first</span><span class="o">,</span> <span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">last</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">first</span> <span class="o">=</span> <span class="n">first</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">last</span> <span class="o">=</span> <span class="n">last</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>As you can see, where <code class="highlighter-rouge">@param</code> was used on <code class="highlighter-rouge">first</code>, only the parameter to the constructor is annotated.
If this was a <code class="highlighter-rouge">var</code> instead of a <code class="highlighter-rouge">val</code> the parameter to the setter function would <strong>not</strong> be annotated.
We’ll see <code class="highlighter-rouge">@setparam</code> shortly which can be used to target setter parameters.</p>
<p><code class="highlighter-rouge">last</code>, being annotated with <code class="highlighter-rouge">@field</code>, only has an annotation on the <code class="highlighter-rouge">private</code> field used by the getter function.
The getter/setter function and the constructor params do not contain the <code class="highlighter-rouge">FieldAnnotation</code> annotation.</p>
<p>These can be useful for targeting specific pieces of code when using a dependency injection framework:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">MyClass</span> <span class="n">@Inject</span> <span class="k">constructor</span><span class="p">(</span>
<span class="n">@param</span><span class="p">:</span><span class="n">SpecificString</span> <span class="k">private</span> <span class="kd">val</span> <span class="py">str</span><span class="p">:</span> <span class="n">String</span>
<span class="p">)</span>
<span class="o">..</span><span class="p">.</span>
<span class="n">@Inject</span>
<span class="n">@field</span><span class="p">:</span><span class="n">MainThread</span>
<span class="k">lateinit</span> <span class="kd">var</span> <span class="py">scheduler</span><span class="p">:</span> <span class="n">Scheduler</span>
</code></pre>
</div>
<h2 id="setter-parameter-use-site-targets">Setter Parameter use-site targets</h2>
<p>As mentioned above, you can use <code class="highlighter-rouge">@setparam</code> to add annotations to setter parameters.
Let’s compare <code class="highlighter-rouge">@set</code> and <code class="highlighter-rouge">@setparam</code> in the same example so you can clearly see the difference.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">SetParamAnnotation</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">SetAnnotation</span>
<span class="kd">class</span> <span class="nc">SetParamAnnTest</span><span class="p">()</span> <span class="p">{</span>
<span class="n">@setparam</span><span class="p">:</span><span class="n">SetParamAnnotation</span>
<span class="n">@set</span><span class="p">:</span><span class="n">SetAnnotation</span>
<span class="kd">var</span> <span class="py">myStr</span><span class="p">:</span> <span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Here we’ve added two use-site targets to the same property; <code class="highlighter-rouge">@setparam</code> and <code class="highlighter-rouge">@set</code>. The resulting decompiled bytecode shows the difference between these 2:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">SetParamAnnTest</span> <span class="o">{</span>
<span class="nd">@Nullable</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">myStr</span><span class="o">;</span>
<span class="nd">@Nullable</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getMyStr</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">myStr</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@SetAnnotation</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kt">void</span> <span class="nf">setMyStr</span><span class="o">(</span><span class="nd">@SetParamAnnotation</span> <span class="nd">@Nullable</span> <span class="n">String</span> <span class="n">var1</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">myStr</span> <span class="o">=</span> <span class="n">var1</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>As expected, both the field and getter method are <em>not</em> annotated.
As we’ve seen before using <code class="highlighter-rouge">@set</code> resulted in the annotation being applied to the setter function.
The <code class="highlighter-rouge">@setparam</code> use-site target added an annotation to the <strong>parameter</strong> expected by the setter function.</p>
<p>A combination of these can be useful with some java-based dependency injection libraries:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@set</span><span class="p">:</span><span class="n">Inject</span>
<span class="n">@setparam</span><span class="p">:[</span><span class="n">Nullable</span> <span class="n">SomeString</span><span class="p">]</span>
<span class="k">lateinit</span> <span class="kd">var</span> <span class="py">str</span><span class="p">:</span> <span class="n">String</span>
</code></pre>
</div>
<h2 id="receiver-use-site-targets">Receiver use-site targets</h2>
<p>In Kotlin a “receiver” is the instance on which an <a href="https://kotlinlang.org/docs/reference/extensions.html">extension function</a> is defined, or the type for a <a href="https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver">lambda with receiver</a>.
It is essentially the type on which a block of code is intended to run.
In the case of a lambda with receiver in Kotlin, the lambda runs as if it is part of the receiving class.
In the case of extension functions, the defined function also runs as if it is part of the receiving class type.
The bytecode for extension functions actually contain the receiver as the first parameter to a static function.
This allows extension functions to be used by Java code as well as Kotlin code by simply passing the receiving type when used from Java.
Knowing this helps us better understand the resulting bytecode and therefore also understand where an <code class="highlighter-rouge">@receiver</code> annotation will reside.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">ReceiverAnnotation</span>
<span class="k">fun</span> <span class="nf">@receiver</span><span class="p">:</span><span class="n">ReceiverAnnotation</span> <span class="n">String</span><span class="p">.</span><span class="n">capitalizeVowels</span><span class="p">()</span> <span class="p">=</span>
<span class="k">this</span><span class="p">.</span><span class="n">map</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">it</span> <span class="k">in</span> <span class="n">listOf</span><span class="p">(</span><span class="sc">'a'</span><span class="p">,</span> <span class="sc">'e'</span><span class="p">,</span> <span class="sc">'i'</span><span class="p">,</span> <span class="sc">'o'</span><span class="p">,</span> <span class="sc">'u'</span><span class="p">))</span> <span class="n">it</span><span class="p">.</span><span class="n">toUpperCase</span><span class="p">()</span> <span class="k">else</span> <span class="n">it</span>
<span class="p">}.</span><span class="n">joinToString</span><span class="p">(</span><span class="s">""</span><span class="p">)</span>
</code></pre>
</div>
<p>The result is the function’s <strong>receiver</strong> parameter being annotated:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">capitalizeVowels</span><span class="o">(</span>
<span class="nd">@ReceiverAnnotation</span> <span class="nd">@Nullable</span> <span class="n">String</span> <span class="n">$receiver</span>
<span class="o">)</span> <span class="o">{</span>
<span class="o">...</span>
<span class="o">}</span>
</code></pre>
</div>
<h2 id="property-use-site-targets">Property use-site targets</h2>
<p><code class="highlighter-rouge"><span class="k">@property</span></code> is the only use-site target that has no effect on the resulting bytecode when viewed from Java.
This is due to the fact that Java does not have the same notion of properties as Kotlin.
Because of this, adding property-specific annotations will only be useful to kotlin-specific libraries and tools.
To demonstrate this we will add two <code class="highlighter-rouge"><span class="k">@property</span></code>-targeted annotations to a class and then use the Kotlin reflection library to see which items are annotated.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">PropertyAnnotation</span>
<span class="kd">class</span> <span class="nc">SomeClass1</span><span class="p">(</span>
<span class="n">@property</span><span class="p">:</span><span class="n">PropertyAnnotation</span> <span class="kd">val</span> <span class="py">constructorProp</span><span class="p">:</span> <span class="n">String</span>
<span class="p">)</span> <span class="p">{</span>
<span class="n">@property</span><span class="p">:</span><span class="n">PropertyAnnotation</span>
<span class="kd">val</span> <span class="py">regProp</span> <span class="p">=</span> <span class="s">"Test"</span>
<span class="p">}</span>
</code></pre>
</div>
<p>As you can see, we’ve added <code class="highlighter-rouge">PropertyAnnotation</code> to both a constructor argument and also to a regular Kotlin property.</p>
<p>If we decompile the kotlin bytecode you will see that these annotations are not present in what would be the Java equivalent of this Kotlin code:</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">SomeClass1</span> <span class="o">{</span>
<span class="nd">@NotNull</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">regProp</span><span class="o">;</span>
<span class="nd">@NotNull</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">constructorProp</span><span class="o">;</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getRegProp</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">regProp</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getConstructorProp</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">constructorProp</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nf">SomeClass1</span><span class="o">(</span><span class="nd">@NotNull</span> <span class="n">String</span> <span class="n">constructorProp</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">constructorProp</span> <span class="o">=</span> <span class="n">constructorProp</span><span class="o">;</span>
<span class="k">this</span><span class="o">.</span><span class="na">regProp</span> <span class="o">=</span> <span class="s">"Test"</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>In order to read the property annotations we will need to use Kotlin’s reflection library to read the annotations at runtime.
This would be similar to how other libraries or tools would need to make use of property-targeted annotations.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">fun</span> <span class="nf">main</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="n">Array</span><span class="p"><</span><span class="n">String</span><span class="p">>)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="n">prop</span> <span class="k">in</span> <span class="n">SomeClass1</span><span class="o">::</span><span class="k">class</span><span class="p">.</span><span class="n">memberProperties</span><span class="p">)</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">"${prop.name} has annotations ${prop.annotations}"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The output from this code shows that each member property has the <code class="highlighter-rouge">PropertyAnnotation</code> annotation specified:</p>
<div class="language-text highlighter-rouge"><pre class="highlight"><code>constructorProp has annotations [@PropertyAnnotation()]
regProp has annotations [@PropertyAnnotation()]
</code></pre>
</div>
<h2 id="delegate-use-site-targets">Delegate use-site targets</h2>
<p>The <a href="https://americanexpress.io/advanced-kotlin-delegates/">previous blog post</a> in our “Advanced Kotlin” series covered delegates in Kotlin.
If you are not familiar with delegates I recommend you check out that post.</p>
<p>The <code class="highlighter-rouge">@delegate</code> use-site target might be one the hardest to guess where the actual annotation will end up.
Is it on the delegate itself? On the delegate class? On the function used to receive the value from the delegate?
Let’s take a look at some code and see what happens.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">annotation</span> <span class="kd">class</span> <span class="nc">DelegateAnnotation</span>
<span class="kd">class</span> <span class="nc">MyDel</span> <span class="p">{</span>
<span class="n">@delegate</span><span class="p">:</span><span class="n">DelegateAnnotation</span>
<span class="kd">val</span> <span class="py">name</span> <span class="k">by</span> <span class="n">lazy</span> <span class="p">{</span> <span class="s">"something"</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>As you can see from the decompiled code, the annotation will reside on the generated <code class="highlighter-rouge">private</code> backing property whose type is the delegate type.
The function used to call the delegate (in this case <code class="highlighter-rouge">getName</code>) does not receive the annotation.</p>
<div class="language-java highlighter-rouge"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">MyDel</span> <span class="o">{</span>
<span class="nd">@DelegateAnnotation</span>
<span class="nd">@NotNull</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Lazy</span> <span class="n">name$delegate</span><span class="o">;</span>
<span class="nd">@NotNull</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
<span class="n">Lazy</span> <span class="n">var1</span> <span class="o">=</span> <span class="k">this</span><span class="o">.</span><span class="na">name</span><span class="n">$delegate</span><span class="o">;</span>
<span class="n">KProperty</span> <span class="n">var3</span> <span class="o">=</span> <span class="err">$</span><span class="n">$delegatedProperties</span><span class="o">[</span><span class="mi">0</span><span class="o">];</span>
<span class="k">return</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span><span class="n">var1</span><span class="o">.</span><span class="na">getValue</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nf">MyDel</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">name</span><span class="n">$delegate</span> <span class="o">=</span> <span class="n">LazyKt</span><span class="o">.</span><span class="na">lazy</span><span class="o">((</span><span class="n">Function0</span><span class="o">)</span><span class="kc">null</span><span class="o">.</span><span class="na">INSTANCE</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre>
</div>
<p>You may find <code class="highlighter-rouge">@delegate</code> useful for targeting a property that you wish to wrap in something like a <code class="highlighter-rouge">lazy</code> delegate:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@delegate</span><span class="p">:</span><span class="n">Transient</span>
<span class="kd">val</span> <span class="py">myLock</span> <span class="k">by</span> <span class="n">lazy</span> <span class="p">{</span> <span class="o">..</span><span class="p">.</span> <span class="p">}</span>
</code></pre>
</div>
<h2 id="default-targets">Default Targets</h2>
<p>Now that we’ve covered all nine of the available use-site targets, let’s cover what happens when a target is not specified on an annotation.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@SomeAnnotation</span>
<span class="kd">val</span> <span class="py">str</span><span class="p">:</span> <span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
</code></pre>
</div>
<p>When an annotation is created, it can itself be annotated with an <code class="highlighter-rouge">@Target</code> annotation which lists the targets that are available for the annotation.
The available target values for <code class="highlighter-rouge">@Target</code> are defined in the <code class="highlighter-rouge">AnnotationTarget</code> enum:</p>
<ul>
<li>‘CLASS’</li>
<li>‘ANNOTATION_CLASS’</li>
<li>‘TYPE_PARAMETER’</li>
<li>‘PROPERTY’</li>
<li>‘FIELD’</li>
<li>‘LOCAL_VARIABLE’</li>
<li>‘VALUE_PARAMETER’</li>
<li>‘CONSTRUCTOR’</li>
<li>‘FUNCTION’</li>
<li>‘PROPERTY_GETTER’</li>
<li>‘PROPERTY_SETTER’</li>
<li>‘TYPE’</li>
<li>‘EXPRESSION’</li>
<li>‘FILE’</li>
<li>‘TYPEALIAS’</li>
</ul>
<p>The main purpose of these values is to let the compiler know where in source code an annotation is allowed to be used.
For example, if an annotation is defined with the <code class="highlighter-rouge">CLASS</code> target:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@Target</span><span class="p">(</span><span class="n">AnnotationTarget</span><span class="p">.</span><span class="n">CLASS</span><span class="p">)</span>
<span class="k">annotation</span> <span class="kd">class</span> <span class="nc">ClassAnnotation</span>
</code></pre>
</div>
<p>Then the annotation can only be applied to a class:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@ClassAnnotation</span> <span class="c1">// OK
</span><span class="kd">class</span> <span class="nc">Temp</span> <span class="p">{</span>
<span class="n">@ClassAnnotation</span> <span class="c1">// Compilation error!
</span> <span class="kd">val</span> <span class="py">str</span><span class="p">:</span> <span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
<span class="p">}</span>
</code></pre>
</div>
<p>These target values along with the placement of the annotation are used to pick a default use-site target for an annotation if one is not specified.
If there’s more than one applicable target either <code class="highlighter-rouge">@param</code> (constructor parameters), <code class="highlighter-rouge"><span class="k">@property</span></code> , or <code class="highlighter-rouge">@field</code> are used, in that order.</p>
<p>Let’s see an example of this. Using the same example code as above:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="n">@SomeAnnotation</span>
<span class="kd">val</span> <span class="py">str</span><span class="p">:</span> <span class="n">String</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
</code></pre>
</div>
<p>If the <code class="highlighter-rouge">@SomeAnnotation</code> annotation was defined with <code class="highlighter-rouge">@Target(FIELD)</code> then your annotation usage would target using <code class="highlighter-rouge">@field</code> as though your code was written as <code class="highlighter-rouge">@field:SomeAnnotation</code>.
As we saw earlier, using <code class="highlighter-rouge">@field</code> means that the <code class="highlighter-rouge">private</code> field value would have the annotation in the bytecode.
Now, if the <code class="highlighter-rouge">@SomeAnnotation</code> annotation in this example had no <code class="highlighter-rouge">@Target</code> defined, then it would apply to <em>any</em> element meaning that <code class="highlighter-rouge"><span class="k">@property</span></code> would be chosen first from the list (<code class="highlighter-rouge">@param</code>, <code class="highlighter-rouge"><span class="k">@property</span></code>, <code class="highlighter-rouge">@field</code>).
Remember that <code class="highlighter-rouge"><span class="k">@property</span></code> is only visible from Kotlin so the resulting annotation would not be useful from Java.
If you’ve ever struggled with a framework not finding an annotation that you thought you had added to the code, this is the likely culprit.</p>
<h2 id="stay-tuned-more-to-come">Stay tuned! More to come!</h2>
<p>This article hopefully covered some annotation use-site targets that you have not encountered before.
Knowing each of these can often get you out of a bind when trying to use a framework that requires very specific placement of annotations in your code.</p>
<p>If you would like to read more about use-site targets in Kotlin take a look at:</p>
<ul>
<li>The official <a href="https://kotlinlang.org/docs/reference/annotations.html">Kotlin Annotation docs</a></li>
<li>Chapter 10 in Kotlin In Action</li>
</ul>
<p>Stay tuned for more!</p>Brent WatsonAnnotation Use-Site targetsChoosing Go at American Express2019-11-25T00:00:00-05:002019-11-25T00:00:00-05:00https://americanexpress.io/choosing-go<p>Selecting a new programming language is an important decision for any organization.</p>
<p>In this article, I’m going to walk through some of the reasons American Express elected to use Go within our payment
and rewards systems.</p>
<h2 id="background">Background</h2>
<p>Our journey with Go started in late 2016, when certain legacy platforms were due for a refresh.</p>
<p>These platforms were purpose built for performance, concurrency, resiliency, and availability. Given advancements in
the programming space, we wanted to see what languages best suited our reliability and performance needs. We also
needed something that fit modern infrastructure and design patterns.</p>
<p>As such, we launched an effort to evaluate different languages.</p>
<h2 id="language-showdown">Language Showdown</h2>
<p>We called our evaluation the “Language Showdown.” To begin, we wrote the same application in multiple languages and
then benchmarked them one by one. Since we were measuring performance, we optimized each version for the language used.
We ensured the logic to process requests was consistent across each version. Since the way one writes code is as
important as the language used, inefficient code can have a large effect on performance.</p>
<p>The application requirements were simple, but they covered our use cases well.</p>
<blockquote>
<p>Write an HTTP/S service that converts ISO8583 messages to JSON.</p>
</blockquote>
<p>The binary message format, ISO8583, is commonly used in credit card processing and other parts of the financial services
industry.</p>
<p>By focusing our showdown on converting ISO8583 to JSON, we ensured that the winner had support for both older and newer
message formats.</p>
<h3 id="choosing-what-to-evaluate">Choosing what to evaluate</h3>
<p>With so many programming languages available, we knew it would be difficult to test every possible option; instead, we
elected to test four, provided that each language:</p>
<ul>
<li>was used in high performance platforms;</li>
<li>had good support for network programming;</li>
<li>was well suited for creating backend REST/gRPC APIs; and</li>
<li>offered an open source toolchain, libraries, and a large community.</li>
</ul>
<p>Based on these criteria, we narrowed our testing languages to C++17, Java, Node.js, and Go. The first three languages
were already in use at American Express, whereas Go was not.</p>
<h3 id="showdown-results">Showdown Results</h3>
<p>With performance being the primary testing method, we found some interesting results. Go achieved the second-best
performance at <strong>140,000 requests per second</strong>. This number wasn’t far off from the top performer, which clocked in at
167,000 requests per second.</p>
<p>From a performance perspective, we saw that Go lived up to its promise.</p>
<p>Even more compelling was that Go achieved this performance without any warm up time. Warm up time is a common challenge
we see in languages that use Just-In-Time compilation. Being a compiled language, Go was ready to handle the brunt of
our tests the second the HTTP listener started.</p>
<p>In our showdown, we included languages that have garbage collection and those that don’t. Even though Go does have
garbage collection, the pause times were negligible. In production today, we see pause times in the range of 250µs to
1ms. All without any special garbage collection tuning options (as there are none for Go).</p>
<h2 id="what-we-like-about-go">What we like about Go</h2>
<p>While performance is important to our use case, it wasn’t the only criteria we assessed. Here’s what else stood out
about Go.</p>
<h3 id="simple-and-straightforward">Simple and Straightforward</h3>
<p>For the most part, Go is a straightforward language to learn. Those with basic programming experience can often pick it
up quickly. This was an important factor. Since we have many engineers with experience in other languages, we sought a
language that lent itself to approachable learning and teaching.</p>
<p>While that doesn’t take away the anxiety of learning a new language, once our engineers started practicing and
learning Go, those nerves settled quickly. Expertise takes time to build, but our engineers were able to contribute to
existing Go projects within one to two months.</p>
<p>The below example shows a very simple Hello World program in Go.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="k">package</span><span class="x"> </span><span class="n">main</span><span class="x">
</span><span class="k">import</span><span class="x"> </span><span class="p">(</span><span class="x">
</span><span class="s">"fmt"</span><span class="x">
</span><span class="s">"math/rand"</span><span class="x">
</span><span class="p">)</span><span class="x">
</span><span class="k">func</span><span class="x"> </span><span class="n">greeting</span><span class="p">()</span><span class="x"> </span><span class="kt">string</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="n">g</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"Hello"</span><span class="p">,</span><span class="x"> </span><span class="s">"Hi"</span><span class="p">,</span><span class="x"> </span><span class="s">"Howdy"</span><span class="p">}</span><span class="x">
</span><span class="k">return</span><span class="x"> </span><span class="n">g</span><span class="p">[</span><span class="n">rand</span><span class="o">.</span><span class="n">Intn</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">))]</span><span class="x">
</span><span class="p">}</span><span class="x">
</span><span class="k">func</span><span class="x"> </span><span class="n">main</span><span class="p">()</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"%s, World"</span><span class="p">,</span><span class="x"> </span><span class="n">greeting</span><span class="p">())</span><span class="x">
</span><span class="p">}</span><span class="x">
</span></code></pre>
</div>
<p>Overall, Go should look familiar to anyone who has experience with C-family languages.</p>
<h3 id="encourages-best-practices">Encourages Best Practices</h3>
<p>Another aspect of Go that we like is that it encourages programming best practices. This can be seen in many ways, but
one clear example is seen in unused <strong>imports</strong> and <strong>variables</strong>.</p>
<p>Most languages will let you import a library or define a variable and never use them. In the case of Go, build tools
will fail to build a program if they find either of these states. This keeps programs lean and performant by
eliminating unnecessary dependencies and objects.</p>
<h4 id="error-handling">Error handling</h4>
<p>Error handling in Go is a bit controversial within the programming community. Yet it is another way that Go encourages
best practices.</p>
<p>Go supports multiple return values on functions. If we write idiomatic Go, then our standard method of showing an issue
is to return an Error type. This leads to every function call looking like the below example.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="n">x</span><span class="p">,</span><span class="x"> </span><span class="n">err</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="n">something</span><span class="p">()</span><span class="x">
</span><span class="k">if</span><span class="x"> </span><span class="n">err</span><span class="x"> </span><span class="o">!=</span><span class="x"> </span><span class="no">nil</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="c">// do stuff</span><span class="x">
</span><span class="p">}</span><span class="x">
</span><span class="n">y</span><span class="p">,</span><span class="x"> </span><span class="n">err</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="n">somethingElse</span><span class="p">()</span><span class="x">
</span><span class="k">if</span><span class="x"> </span><span class="n">err</span><span class="x"> </span><span class="o">!=</span><span class="x"> </span><span class="no">nil</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="c">// do stuff</span><span class="x">
</span><span class="p">}</span><span class="x">
</span></code></pre>
</div>
<p>You can pretty much look at any Go program and find the same <code class="highlighter-rouge">err != nil</code> checks throughout. Some would say that this
violates the DRY (Don’t Repeat Yourself) principle. They wouldn’t be wrong.</p>
<p>In my opinion, though this goes against the DRY principle, it encourages a better practice. This style of error
handling encourages engineers to act immediately. It’s also very simple to see when engineers are not handling errors.</p>
<p>Code like this is a big red flag.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="n">v</span><span class="p">,</span><span class="x"> </span><span class="n">_</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="n">something</span><span class="p">()</span><span class="x">
</span></code></pre>
</div>
<p>The above example throws away the error returned from the <code class="highlighter-rouge">something()</code> function. This is very easy to spot during code
reviews. But even if one sneaks by, Go provides tooling to catch unhandled errors. These tools can easily be integrated
into a continuous integration pipeline.</p>
<p>Go makes it difficult to have unhandled errors.</p>
<h4 id="godocs">Godocs</h4>
<p>Commenting code is a best practice in any language. Go encourages this by using code comments as the source for package
documentation.</p>
<p>Let’s take a look at an example.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="c">// Greeting will return a random greeting from a pre-defined list of greetings.</span><span class="x">
</span><span class="k">func</span><span class="x"> </span><span class="n">Greeting</span><span class="p">()</span><span class="x"> </span><span class="kt">string</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="n">g</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"Hello"</span><span class="p">,</span><span class="x"> </span><span class="s">"Hi"</span><span class="p">,</span><span class="x"> </span><span class="s">"Howdy"</span><span class="p">}</span><span class="x">
</span><span class="k">return</span><span class="x"> </span><span class="n">g</span><span class="p">[</span><span class="n">rand</span><span class="o">.</span><span class="n">Intn</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">)</span><span class="o">-</span><span class="m">1</span><span class="p">)]</span><span class="x">
</span><span class="p">}</span><span class="x">
</span></code></pre>
</div>
<p>When the <code class="highlighter-rouge">godoc</code> command is run against the code above. The <code class="highlighter-rouge">Greeting()</code> function documentation will read as follows.</p>
<blockquote>
<p>Greeting will return a random greeting from a pre-defined list of greetings.</p>
</blockquote>
<p>While generating package documentation from code comments is not unique to Go, the Go community emphasizes and helps
enforce this practice.</p>
<p>Any open source Go package that seeks popularity must have quality Go Docs.</p>
<h3 id="concurrency-in-its-dna">Concurrency in its DNA</h3>
<p>For most languages, the standard answer to processing concurrent requests is threads. Applications will create
operating system (OS) threads and distribute work across those threads. These OS threads, however, can be quite
resource intensive, using at least 1Mb of stack space per thread.</p>
<p>As such, applications have to control how many threads they create. This is typically done by creating a thread pool
and managing the size and longevity of the pool.</p>
<p>Go’s approach is a bit different. In Go, work is distributed across Goroutines. These Goroutines are not OS threads and
come at a much lower resource cost, using at least 2Kb of stack space per Goroutine (0.19% of the memory an OS thread
uses). They are managed by the Go runtime, which will manage the allocation of OS threads as needed. It will also
distribute Goroutines to those threads as required.</p>
<p>This makes distributing concurrent work easier by reducing the need to create pools.</p>
<p>But Go doesn’t just make it easy to distribute concurrent work, Go also makes creating Goroutines straightforward. It’s
as easy as adding the term <code class="highlighter-rouge">go</code> in front of a function.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="k">go</span><span class="x"> </span><span class="n">example</span><span class="p">()</span><span class="x">
</span></code></pre>
</div>
<p>Another core aspect of Go’s concurrency approach are channels. Channels act like internal queues for a Go program.
These channels provide a thread-safe way of passing information across Goroutines.
The below example shows how to create a channel (<code class="highlighter-rouge">c</code>). It also shows reading from that channel in a Goroutine and
writing to it from the main routine.</p>
<div class="language-go highlighter-rouge"><pre class="highlight"><code><span class="c">// Creating a channel</span><span class="x">
</span><span class="n">c</span><span class="x"> </span><span class="o">:=</span><span class="x"> </span><span class="nb">make</span><span class="p">(</span><span class="k">chan</span><span class="x"> </span><span class="kt">string</span><span class="p">)</span><span class="x">
</span><span class="c">// Kick off anonymous Go routine</span><span class="x">
</span><span class="k">go</span><span class="x"> </span><span class="k">func</span><span class="p">()</span><span class="x"> </span><span class="p">{</span><span class="x">
</span><span class="c">// Read from a channel </span><span class="x">
</span><span class="n">msg</span><span class="x"> </span><span class="o"><-</span><span class="x"> </span><span class="n">c</span><span class="x">
</span><span class="c">// do stuff</span><span class="x">
</span><span class="p">}()</span><span class="x">
</span><span class="c">// Writing to a channel</span><span class="x">
</span><span class="n">c</span><span class="x"> </span><span class="o"><-</span><span class="x"> </span><span class="s">"This is a channel"</span><span class="x">
</span></code></pre>
</div>
<p>When building high volume, low latency platforms, concurrency is very important. With Goroutines and channels, it takes
a lot less work to build for concurrency.</p>
<h3 id="great-tooling">Great Tooling</h3>
<p>Tooling is an area where we feel Go especially excels. Go comes with an assortment of tooling that makes developing in
Go easier. This can be seen in its powerful built-in testing and benchmarking framework, and in the simple, but
all-important, <code class="highlighter-rouge">gofmt</code> command which auto-formats code to keep all Go code looking the same. Even its profiling tool,
PProf, lets you really dig into performance hot spots.</p>
<p>Build is one specific area where we have seen significant productivity gains. Our Go projects build time tends to be
about half or better than the build time of other comparable projects. Though it may be only a few minutes of savings
per build, the benefit scales quickly because engineers run many builds per day.</p>
<h3 id="dependency-management-needs-some-work">Dependency Management needs some work</h3>
<p>While there are many good things about Go, it has some areas that are less refined. One example of this is in
dependency management. A lot of work is going into how Go manages dependencies, but the Go Community is still adopting
the new tools and adapting to the changes they bring.</p>
<p>I’m confident this will settle over time.</p>
<h2 id="convincing-leadership">Convincing Leadership</h2>
<p>In summary, there is a lot to like about Go for our use case of backend and network-based services. It’s fast, built
for concurrency, easy to learn, and encourages best practices.</p>
<p>When all the showdown results were in, we chose Go as the recommended language. However, this by itself wasn’t enough
to start writing in Go. As with many engineering decisions, Go started as a grassroots effort.</p>
<p>Before we could start re-writing critical platforms in Go, we had to first convince our leadership. We did this in a
couple of ways.</p>
<p>One was via an internal position paper. It went in-depth into the syntax and benefits of Go and discussed how we could
apply Go to specific systems. This paper helped add context around where Go could be used and where it shouldn’t be
used.</p>
<p>Beyond the paper and the showdown proof of concept, we also picked several pilot applications. These were not test
applications but real-world services that had to run in production. It spoke volumes being able to show how we reduced
our memory overhead by nine-tenths using Go.</p>
<p>Thanks to the combination of the paper, proof of concept, pilot applications, and some long conversations, we were able
to make a convincing case about the enterprise readiness of Go.</p>
<p>To help other enterprises determine if Go is right for them we’ve published a
<a href="https://go.dev/solutions/americanexpress/">Go Case Study</a>.</p>Benjamin CaneAdvanced Kotlin - Part 1 - Delegates2019-07-01T00:00:00-04:002019-07-01T00:00:00-04:00https://americanexpress.io/advanced-kotlin-delegates<h1 id="advanced-kotlin---delegates">Advanced Kotlin - Delegates</h1>
<p>This post is part of an on-going series discussing some of the more advanced
and intermediate features of the <a href="https://kotlinlang.org">Kotlin programming language</a>.</p>
<p>The target audience for this
series of posts will be Kotlin developers who are comfortable with the language but
would like to learn about the more advanced features that are available. Some of the items I’ll cover over
the coming months will be DSLs, reflection, tail recursion, use-site targets, and much more.
If this resonates with you, read on!</p>
<p>To kick off the series, we’ll look at delegates in Kotlin. I’ll discuss both the built-in delegates provided
by the standard library and also dive into how (and when) to create your own.</p>
<h2 id="delegates">Delegates?</h2>
<p>But first, what exactly is a property delegate? I guarantee you’ve used a delegate before if you’ve been writing Kotlin
for any length of time:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">val</span> <span class="py">myString</span> <span class="k">by</span> <span class="n">lazy</span> <span class="p">{</span> <span class="s">"Some Value"</span> <span class="p">}</span>
</code></pre>
</div>
<p>Here <code class="highlighter-rouge">lazy</code> is a property delegate that Kotlin provides us. It’s one of the four built-in delegates from the stdlib,
and probably the most used and most well-known. We’ll take a look at the others in a moment.</p>
<p>A delegate is simply a way to wrap common code that will be executed each time you read and/or write from a
property value. In this case <code class="highlighter-rouge">lazy</code> is used only to construct the value of a field when it is first
accessed (aka “lazy loading”).</p>
<p>In the case of <code class="highlighter-rouge">lazy</code> this is a top-level Kotlin function that returns an instance of <a href="https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/util/Lazy.kt">Lazy</a>, which
conforms to a very specific interface that allows it to be treated as a delegate by the Kotlin compiler. Each time
<code class="highlighter-rouge">myString</code> is referenced the code within the stdlib implementation of <code class="highlighter-rouge">Lazy</code> gets invoked. It’s simply a means of
code-sharing that helps you adhere to the DRY (Don’t Repeat Yourself) good coding practice.</p>
<h2 id="theres-more-than-just-lazy">There’s more than just <code class="highlighter-rouge">lazy</code>?</h2>
<p>Yup. The stdlib actually provides 3 other delegates that are useful to know about.</p>
<ul>
<li><code class="highlighter-rouge">observable</code></li>
<li><code class="highlighter-rouge">vetoable</code></li>
<li><code class="highlighter-rouge">notNull</code></li>
</ul>
<p>Let’s look at each of these in turn.</p>
<h3 id="the-observable-delegate">The <code class="highlighter-rouge">observable</code> delegate</h3>
<p>The next stdlib delegate we’ll look at is <code class="highlighter-rouge">observable</code> (not to be confused with
RxJava’s <code class="highlighter-rouge">Observable</code>). Like the other built-in delegates, this is found in Kotlin’s <code class="highlighter-rouge">Delegates</code> class.</p>
<p>Usage is pretty straight-forward:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">var</span> <span class="py">maxCount</span><span class="p">:</span> <span class="n">Int</span> <span class="k">by</span> <span class="n">observable</span><span class="p">(</span><span class="n">initialValue</span> <span class="p">=</span> <span class="m">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">property</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">newValue</span> <span class="p">-></span>
<span class="n">println</span><span class="p">(</span><span class="s">"${property.name} is being changed from $oldValue to $newValue"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre>
</div>
<p>This delegate takes two parameters; an initial value and a lambda. The lambda will be executed each time
the value of the field is changed.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">maxCount</span><span class="p">++</span>
<span class="n">maxCount</span><span class="p">++</span>
<span class="n">maxCount</span> <span class="p">+=</span> <span class="m">10</span>
<span class="p">}</span>
<span class="p">></span> <span class="n">maxCount</span> <span class="k">is</span> <span class="n">being</span> <span class="n">changed</span> <span class="n">from</span> <span class="m">0</span> <span class="n">to</span> <span class="m">1</span>
<span class="p">></span> <span class="n">maxCount</span> <span class="k">is</span> <span class="n">being</span> <span class="n">changed</span> <span class="n">from</span> <span class="m">1</span> <span class="n">to</span> <span class="m">2</span>
<span class="p">></span> <span class="n">maxCount</span> <span class="k">is</span> <span class="n">being</span> <span class="n">changed</span> <span class="n">from</span> <span class="m">2</span> <span class="n">to</span> <span class="m">12</span>
</code></pre>
</div>
<p>This delegate is great if you need to drive one property off of another, log changes (like in the example
above), cache old values for undo-style actions, and various other things.</p>
<h3 id="the-vetoable-delegate">The <code class="highlighter-rouge">vetoable</code> delegate</h3>
<p>The signature of <code class="highlighter-rouge">vetoable</code> looks very much like <code class="highlighter-rouge">observable</code>:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">var</span> <span class="py">age</span><span class="p">:</span> <span class="n">Int</span> <span class="k">by</span> <span class="n">vetoable</span><span class="p">(</span><span class="n">initialValue</span> <span class="p">=</span> <span class="m">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">property</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">newValue</span> <span class="p">-></span>
<span class="n">newValue</span> <span class="p">></span> <span class="m">0</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The difference between <code class="highlighter-rouge">observable</code> and <code class="highlighter-rouge">vetoable</code> is that the lambda parameter for <code class="highlighter-rouge">vetoable</code> must return a <code class="highlighter-rouge">Boolean</code>.
If <code class="highlighter-rouge">false</code> is returned then the value will not be modified.</p>
<p>This delegate is a great way to either set reasonable bounds on a value or implement a simple validation framework.</p>
<h3 id="the-notnull-delegate">The <code class="highlighter-rouge">notNull</code> delegate</h3>
<p><code class="highlighter-rouge">notNull</code> is the simplest of the four stdlib delegates. It works similar to <code class="highlighter-rouge">lateinit</code> in that it will throw an
<code class="highlighter-rouge">IllegalStateException</code> if a variable is accessed before it is initialized.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">var</span> <span class="py">age</span> <span class="k">by</span> <span class="n">notNull</span><span class="p"><</span><span class="n">Int</span><span class="p">>()</span>
<span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">=</span> <span class="n">println</span><span class="p">(</span><span class="n">age</span><span class="p">)</span>
<span class="p">></span> <span class="n">Exception</span> <span class="k">in</span> <span class="n">thread</span> <span class="s">"main"</span> <span class="n">java</span><span class="p">.</span><span class="n">lang</span><span class="p">.</span><span class="n">IllegalStateException</span><span class="p">:</span> <span class="n">Property</span> <span class="n">age</span> <span class="n">should</span> <span class="n">be</span> <span class="n">initialized</span> <span class="n">before</span> <span class="k">get</span><span class="p">.</span>
</code></pre>
</div>
<p>This brings up a good question; what is the difference between <code class="highlighter-rouge">notNull</code> and <code class="highlighter-rouge">lateinit</code>? When would you have
to use <code class="highlighter-rouge">notNull</code> when <code class="highlighter-rouge">lateinit</code> does the same thing? The answer is that <code class="highlighter-rouge">lateinit</code> can only be used on
non-primitive types. If you tried to change the above example to “<code class="highlighter-rouge">lateinit var age: Int</code>” you would receive the
compilation error “<em>‘lateinit’ modifier is not allowed on properties of primitive types</em>”. This is exactly
what <code class="highlighter-rouge">notNull</code> is meant to solve.</p>
<h2 id="creating-your-own-delegates">Creating your own delegates</h2>
<p>Creating your own delegates is a matter of creating a class that has a specific <code class="highlighter-rouge">getValue</code> function for
delegates used by <code class="highlighter-rouge">val</code> properties, and also a specific <code class="highlighter-rouge">setValue</code> function if you want your delegate
to also be usable for <code class="highlighter-rouge">var</code>s.</p>
<p>The signatures of these functions are as follows:</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">fun</span> <span class="nf">getValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">R</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>):</span> <span class="n">T</span>
<span class="k">fun</span> <span class="nf">setValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">R</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">value</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span>
</code></pre>
</div>
<p>Since the creation of delegates is a compiler feature (vs a runtime feature) you actually don’t need to
implement an interface to provide these functions. As long as a class implements these with the <code class="highlighter-rouge">operator</code>
keyword, the compiler will treat your class as a delegate. However, the stdlib does provide a few interfaces
that can be used regardless of this fact. I highly suggest using these interfaces so that future developers
looking at your code know that a class is indeed a delegate and the interface also provides a reference for docs.
Using the stdlib delegate interfaces also makes it impossible to get the function signatures wrong.</p>
<p>Here are the two interfaces and one abstract class we’ll look at:</p>
<ul>
<li><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-only-property/index.html"><code class="highlighter-rouge">ReadOnlyProperty</code></a></li>
<li><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-read-write-property/index.html"><code class="highlighter-rouge">ReadWriteProperty</code></a></li>
<li><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-observable-property/index.html"><code class="highlighter-rouge">ObservableProperty</code></a></li>
</ul>
<h3 id="the-readonlyproperty-interface">The <code class="highlighter-rouge">ReadOnlyProperty</code> interface</h3>
<p>The <code class="highlighter-rouge">ReadOnlyProperty</code> interface only has the <code class="highlighter-rouge">getValue()</code> function, so delegates created with it can only be used
on <code class="highlighter-rouge">val</code> properties.</p>
<p>Let’s create a simple delegate using the <code class="highlighter-rouge">ReadOnlyProperty</code> interface and see how it works.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">SimpleReadOnlyDelegate</span><span class="p"><</span><span class="k">out</span> <span class="n">T</span><span class="p">>(</span><span class="k">private</span> <span class="kd">val</span> <span class="py">id</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="p">:</span> <span class="n">ReadOnlyProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">,</span> <span class="n">T</span><span class="p">></span> <span class="p">{</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">getValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>)</span> <span class="p">=</span> <span class="n">id</span><span class="p">.</span><span class="n">also</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">"Getting value for ${property.name} from ${thisRef::class.simpleName}"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">DelegateExample</span> <span class="p">{</span>
<span class="kd">val</span> <span class="py">myProperty</span> <span class="k">by</span> <span class="n">SimpleReadOnlyDelegate</span><span class="p">(</span><span class="s">"demo"</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">=</span> <span class="n">println</span><span class="p">(</span><span class="n">DelegateExample</span><span class="p">().</span><span class="n">myProperty</span><span class="p">)</span>
<span class="p">></span> <span class="n">Getting</span> <span class="n">value</span> <span class="k">for</span> <span class="n">myProperty</span> <span class="n">from</span> <span class="n">DelegateExample</span>
<span class="p">></span> <span class="s">"demo"</span>
</code></pre>
</div>
<p>If you tried to use our <code class="highlighter-rouge">SimpleReadOnlyDelegate</code> delegate on a <code class="highlighter-rouge">var</code> type the compiler lets you know that
the <code class="highlighter-rouge">setValue</code> method is missing:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>> Missing 'setValue(DelegateExample, KProperty<*>, String)' method on delegate of type 'SimpleReadOnlyDelegate'
</code></pre>
</div>
<p>We can fix this by changing our class from implementing <code class="highlighter-rouge">ReadOnlyProperty</code> to instead implement <code class="highlighter-rouge">ReadWriteProperty</code>
which contains both <code class="highlighter-rouge">getValue</code> and <code class="highlighter-rouge">setValue</code> functions.</p>
<h3 id="the-readwriteproperty-interface">The <code class="highlighter-rouge">ReadWriteProperty</code> interface</h3>
<p>If we want to allow both reading <em>and writing</em> values from a delegate we must also include a <code class="highlighter-rouge">setValue</code> function.
Here’s a very simple delegate that shows using the <code class="highlighter-rouge">ReadWriteProperty</code> interface. Note that for brevity this
delegate does nothing more than store and return a value. We’ll take a look at some more complex examples
further down. For now let’s focus on the basic structure.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">SimpleDelegate</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="p">:</span> <span class="n">ReadWriteProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">,</span> <span class="n">T</span><span class="p">?></span> <span class="p">{</span>
<span class="k">private</span> <span class="kd">var</span> <span class="py">value</span><span class="p">:</span> <span class="n">T</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">getValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>)</span> <span class="p">=</span> <span class="n">value</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">setValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">value</span><span class="p">:</span> <span class="n">T</span><span class="p">?)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">value</span> <span class="p">=</span> <span class="n">value</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">DelegateDemo</span> <span class="p">{</span>
<span class="kd">var</span> <span class="py">someNum</span> <span class="k">by</span> <span class="n">SimpleDelegate</span><span class="p"><</span><span class="n">Int</span><span class="p">>()</span>
<span class="kd">var</span> <span class="py">someStr</span> <span class="k">by</span> <span class="n">SimpleDelegate</span><span class="p"><</span><span class="n">String</span><span class="p">>()</span>
<span class="p">}</span>
<span class="k">fun</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">val</span> <span class="py">demo</span> <span class="p">=</span> <span class="n">DelegateDemo</span><span class="p">().</span><span class="n">apply</span> <span class="p">{</span>
<span class="n">someNum</span> <span class="p">=</span> <span class="m">42</span>
<span class="n">someStr</span> <span class="p">=</span> <span class="s">"demo"</span>
<span class="p">}</span>
<span class="n">println</span><span class="p">(</span><span class="s">"${demo.someNum} ${demo.someStr}"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">></span> <span class="m">42</span> <span class="n">demo</span>
</code></pre>
</div>
<p>Now that you understand <em>how</em> delegates work and how they are created, you can hopefully see the power that they
can provide in helping to encapsulate reusable code.</p>
<p>A few complex examples would include a delegate that stores and retrieves values from a database
“<code class="highlighter-rouge">var record by MyDBDelegate<String>()</code>”, or on Android a delegate that backs values using <code class="highlighter-rouge">SharedPreferences</code>
(local storage) “<code class="highlighter-rouge">var pref by MySharedPrefsDelegate()</code>”, or a delegate similar to <code class="highlighter-rouge">lazy</code> which constructs parts
of an object that is expensive to initialize.</p>
<h3 id="the-observableproperty-abstract-class">The <code class="highlighter-rouge">ObservableProperty</code> abstract class</h3>
<p>The last item that I’ll cover is an abstract class in the stdlib called <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-observable-property/index.html"><code class="highlighter-rouge">ObservableProperty</code></a>.</p>
<p>If you take a peak at the source code for this class you’ll find that it implements logic that allows you to
validate properties in a <code class="highlighter-rouge">beforeChange</code> function which is called from <code class="highlighter-rouge">setValue</code>. If <code class="highlighter-rouge">beforeChange</code> returns <code class="highlighter-rouge">false</code>
then the property value is not updated. It also provides a (default no-op) <code class="highlighter-rouge">afterChange</code> function which is called
after <code class="highlighter-rouge">setValue</code> is executed.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">abstract</span> <span class="kd">class</span> <span class="nc">ObservableProperty</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="n">initialValue</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="p">:</span> <span class="n">ReadWriteProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">?,</span> <span class="n">T</span><span class="p">></span> <span class="p">{</span>
<span class="k">private</span> <span class="kd">var</span> <span class="py">value</span> <span class="p">=</span> <span class="n">initialValue</span>
<span class="cm">/**
* If the callback returns `true` the value of the property is being set to the new value,
* and if the callback returns `false` the new value is discarded.
*/</span>
<span class="k">protected</span> <span class="k">open</span> <span class="k">fun</span> <span class="nf">beforeChange</span><span class="p">(</span><span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">oldValue</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">newValue</span><span class="p">:</span> <span class="n">T</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">=</span> <span class="k">true</span>
<span class="k">protected</span> <span class="k">open</span> <span class="k">fun</span> <span class="nf">afterChange</span><span class="p">(</span><span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">oldValue</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">newValue</span><span class="p">:</span> <span class="n">T</span><span class="p">):</span> <span class="n">Unit</span> <span class="p">{}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">fun</span> <span class="nf">setValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">?,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">value</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">val</span> <span class="py">oldValue</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">value</span>
<span class="k">if</span> <span class="p">(!</span><span class="n">beforeChange</span><span class="p">(</span><span class="n">property</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="n">value</span> <span class="p">=</span> <span class="n">value</span>
<span class="n">afterChange</span><span class="p">(</span><span class="n">property</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">fun</span> <span class="nf">getValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">?,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>):</span> <span class="n">T</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">value</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Does the ability to block property value modification like this sound familiar?</p>
<p>You guessed it; <code class="highlighter-rouge">ObservableProperty</code> is exactly how the <code class="highlighter-rouge">vetoable</code> delegate that we saw before is implemented
in the stdlib…</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">inline</span> <span class="k">fun</span> <span class="err"><</span><span class="nf">T</span><span class="p">></span> <span class="n">vetoable</span><span class="p">(</span><span class="n">initialValue</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="k">crossinline</span> <span class="n">onChange</span><span class="p">:</span> <span class="p">(</span><span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">oldValue</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">newValue</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="p">-></span> <span class="n">Boolean</span><span class="p">):</span>
<span class="n">ReadWriteProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">?,</span> <span class="n">T</span><span class="p">></span> <span class="p">=</span> <span class="kd">object</span> <span class="err">: </span><span class="nc">ObservableProperty</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="n">initialValue</span><span class="p">)</span> <span class="p">{</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">beforeChange</span><span class="p">(</span><span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">oldValue</span><span class="p">:</span> <span class="n">T</span><span class="p">,</span> <span class="n">newValue</span><span class="p">:</span> <span class="n">T</span><span class="p">):</span> <span class="n">Boolean</span> <span class="p">=</span> <span class="n">onChange</span><span class="p">(</span><span class="n">property</span><span class="p">,</span> <span class="n">oldValue</span><span class="p">,</span> <span class="n">newValue</span><span class="p">)</span>
<span class="p">}</span>
</code></pre>
</div>
<p>If you find <code class="highlighter-rouge">vetoable</code> too restrictive or find that you need to share the logic in a <code class="highlighter-rouge">vetoable</code> block accross multiple
properties then you should be looking at extending <code class="highlighter-rouge">ObservableProperty</code> to create your own delegate instead of using <code class="highlighter-rouge">vetoable</code>.</p>
<h3 id="adding-one-more-layer">Adding One More Layer</h3>
<p>Sometimes you need an extra layer of logic between your property and the creation of a delegate.
Kotlin provides a means of wrapping the creation of a delegate via an operator called <code class="highlighter-rouge">provideDelegate</code>.
This allows you to continue to use the <code class="highlighter-rouge">by</code> keyword when defining your property, but the right side of the <code class="highlighter-rouge">by</code> will
reference a class that <em>returns</em> a delegate, but is not a delegate itself.</p>
<div class="language-kotlin highlighter-rouge"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">MyDelegateFactory</span> <span class="p">{</span>
<span class="k">operator</span> <span class="k">fun</span> <span class="nf">provideDelegate</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">prop</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>):</span> <span class="n">ReadWriteProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">,</span> <span class="n">String</span><span class="p">></span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">"returning a new ReadWriteProperty delegate for ${prop.name}"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">MyDelegate</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">MyDelegate</span><span class="p">:</span> <span class="n">ReadWriteProperty</span><span class="p"><</span><span class="n">Any</span><span class="p">,</span> <span class="n">String</span><span class="p">></span> <span class="p">{</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">getValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>):</span> <span class="n">String</span> <span class="p">{</span> <span class="o">..</span><span class="p">.</span> <span class="p">}</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">setValue</span><span class="p">(</span><span class="n">thisRef</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">property</span><span class="p">:</span> <span class="n">KProperty</span><span class="p"><*>,</span> <span class="n">value</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="p">{</span> <span class="o">..</span><span class="p">.</span> <span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">DelegateDemo</span> <span class="p">{</span>
<span class="kd">var</span> <span class="py">myProp</span> <span class="k">by</span> <span class="n">MyDelegateFactory</span><span class="p">()</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Another common pattern is to hide the delegate creation behind a top-level function, like we saw with <code class="highlighter-rouge">lazy</code>, <code class="highlighter-rouge">observable</code>, etc.</p>
<h2 id="stay-tuned-more-to-come">Stay tuned! More to come!</h2>
<p>Hopefully this article provided enough information on Kotlin delegates for you to get started on building
your own, and gave you a few additional items in your tool chest for using <code class="highlighter-rouge">observable</code>, <code class="highlighter-rouge">vetoable</code>, and <code class="highlighter-rouge">notNull</code>.</p>
<p>If you would like to read more about delegates in Kotlin take a look at:</p>
<ul>
<li>The Kotlin <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/index.html">properties</a> package</li>
<li>The official <a href="https://kotlinlang.org/docs/reference/delegated-properties.html">Delegated Properties</a> docs</li>
<li>Chapter 7 in <a href="https://www.manning.com/books/kotlin-in-action">Kotlin In Action</a></li>
</ul>
<p>Again, this is the first in a series of “Advanced Kotlin” articles on the American Express Technology Blog.
Stay tuned for more!</p>
<p>Happy delegating.</p>Brent WatsonAdvanced Kotlin - DelegatesSuper-powered Search via Couchbase2019-06-18T00:00:00-04:002019-06-18T00:00:00-04:00https://americanexpress.io/super-powered-search-via-couchbase<p><img src="../_post_assets/super-powered-search-via-couchbase/img/main.jpg" alt="SuperHero Hero" class="center-block" /></p>
<h2 id="sunstone-crystal">Sunstone crystal</h2>
<p>Ok. If you get that reference, then this article is right up your alley. The Sunstone crystal came into the possession
of Superman, and was later used to create the famed Fortress of Solitude. That’s not to say that you will be on a
solitary road wielding the immense power that will be available to you at the conclusion of this article, but you will
certainly be in an elite community.</p>
<p>Beginning with Couchbase 5, you now have access to some extremely powerful tools to set your search
capabilities apart from the pack. These tools are powerful enough on their own, but when combined they possess
enough raw power to destroy the universe, or at a minimum make your search results much more accurate and intuitive.</p>
<h2 id="your-powers-tokenizers-analyzers-indexes-oh-my">Your powers: tokenizers, analyzers, indexes… oh my</h2>
<p>In the same way Superman draws his powers by basking in the rays of the fiery orb we call the Sun, the full text
search (FTS) at the heart of the Couchbase engine draws its powers from the customizability of the various tuning knobs at a
developer’s disposal. Let’s step through some of them.</p>
<h2 id="indexes">Indexes</h2>
<p>Every FTS is performed on a user-created full text index, which contains the data targets
on which searches are to be performed. Through this knob you can configure your Couchbase documents to
only expose certain pieces of information to the FTS Engine. Think of this as your first
opportunity to begin contouring the shape of your search behavior. Don’t want to expose email addresses to
the search engine? Don’t. Want to include Last Name and leave out First Name? Pow! It’s completely up
you.</p>
<h2 id="tokenizers">Tokenizers</h2>
<p>Tokenizers split input strings into individual tokens. The tokens that are created are then made into a
individual tokens as a stream for the query. Here are some popular tokenizers.</p>
<ul>
<li>
<p><strong>Letter</strong>: Creates tokens by breaking input text into subsets that consist of letters only; characters
such as punctuation marks and numbers are omitted. Creation of a token ends whenever a non-letter
character is encountered; for example, the text “Reqmnt: 7-element phrase” would return the following
tokens: <em>Reqmnt</em>, <em>element</em> and <em>phrase</em>.</p>
</li>
<li>
<p><strong>Single</strong>: Creates a single token from the entirety of the input text. For example, the text “in each
place” would return the following token: <em>in each place</em>. This may be useful for handling URLs
or email addresses, which can be prevented from being broken at punctuation or special-character
boundaries. It may also be used to prevent multi-word phrases (for example, placenames such as “Milton
Keynes” or “San Francisco”) from being broken up due to whitespace, so that they become indexed as a single term.</p>
</li>
<li>
<p><strong>Unicode</strong>: Creates tokens by performing Unicode text segmentation on word boundaries, using the segment
library.</p>
</li>
<li>
<p><strong>Web</strong>: Creates tokens by identifying and removing HTML tags.</p>
</li>
<li>
<p><strong>Whitespace</strong>: Creates tokens by breaking input text into subsets according to where whitespace occurs.
For example, the text “in each place” would return the following tokens: <em>in</em>, <em>each</em> and <em>place</em>.</p>
</li>
</ul>
<p>So now you’ve got your indexes only exposing the information you want searchable. You’ve got your tokenizers
purifying incoming query strings into a representation ideal for your context. You can now begin to combine these tools
into a formidable weapon, greater together than the sum of their parts (think Captain Planet or the Power Rangers).</p>
<h2 id="analyzers">Analyzers</h2>
<p>Analyzers take the output of the tokenizer (called a token stream) and apply a few more controls on top to
end up with the delicately crafted final representation of the search query with which to match. This is
accomplished through character filtering and token filtering. Character filtering, as the name implies, removes
unwanted characters from the input stream. Token filtering takes the token-stream output from the tokenizer and
makes some additional modifications to the tokens themselves. An easy way to think about it is that the tokenizer
tells the engine how to break up a large string into individual tokens, while the token filter further refines
each of those output tokens.</p>
<p>So the final recipe looks like this:</p>
<ul>
<li>Original Input -> Character Filter -> Tokenizer -> Token Filter = Final Query</li>
</ul>
<h2 id="boom">BOOM!</h2>
<p>Now <strong>here</strong> is where the magic happens. This highly configurable set of filters and tokenizers can be applied
at an index level! This means that if your data model looks something like this:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="p">{</span>
<span class="s2">"firstName"</span><span class="err">:</span> <span class="s2">"Clark"</span><span class="p">,</span>
<span class="s2">"lastName"</span><span class="err">:</span> <span class="s2">"Kent"</span><span class="p">,</span>
<span class="s2">"email"</span><span class="err">:</span> <span class="s2">"clark.kent@dailyplanet.example.com"</span><span class="p">,</span>
<span class="s2">"allergies"</span><span class="err">:</span> <span class="s2">"kryptonite dust"</span>
<span class="p">}</span>
</code></pre>
</div>
<p>…you can set up <em>unique</em> indexes for <code class="highlighter-rouge">firstName</code> <code class="highlighter-rouge">lastName</code>, and <code class="highlighter-rouge">email</code>. This means that you can configure completely
separate variations of filters/tokenizers/analyzers for each data attribute above.</p>
<h2 id="bring-it-all-together">Bring it all together</h2>
<p>Here’s an actual example of preparing the FTS query.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">public</span> <span class="nx">async</span> <span class="nx">ftsSearch</span><span class="p">(</span><span class="nx">searchCriteria</span><span class="p">)</span><span class="err">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="nx">any</span><span class="o">></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">searchCriteria</span>
<span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[</span><span class="sr">`~!#$%&()_|</span><span class="se">\-</span><span class="sr">=?;'",.<></span><span class="se">\{\}\[\]\\\/]</span><span class="sr">/gi</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\s</span><span class="sr">+/gi</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">val</span> <span class="o">=></span> <span class="s1">'+'</span> <span class="o">+</span> <span class="nx">val</span><span class="p">)</span>
<span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">toLowerCase</span><span class="p">();</span>
</code></pre>
</div>
<p>The <code class="highlighter-rouge">searchCriteria</code> input is being tweaked, massaged and sanitized into a more suitable context for optimal
results. Going a step further we can add something like this.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">searchCriteria</span> <span class="o">=</span> <span class="s1">'firstName:'</span>
<span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">query</span><span class="p">.</span><span class="nx">trim</span><span class="p">())</span>
<span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\s</span><span class="sr">+/gi</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\s</span><span class="sr">+/</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span>
<span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">searchCriteria</span><span class="p">);</span>
</code></pre>
</div>
<p>As shown above, you can append additional query parameters into the original search string. In this case, we’re
adding additional weight to the <code class="highlighter-rouge">firstName</code> field to ensure documents that have strong matches to <code class="highlighter-rouge">firstName</code>
are returned.</p>
<p>“With great power comes great responsibility.” Use this information to craft an unwavering search engine suitable
for the gods.</p>
<p>If you’d like more information and want to dive even deeper into the archives of ancient knowledge, check out the complete
<a href="https://docs.couchbase.com/server/6.0/fts/full-text-intro.html">Couchbase FTS documentation</a>. Godspeed, and good luck.</p>Rick BallmannIntro to React Hooks2019-02-06T00:00:00-05:002019-02-06T00:00:00-05:00https://americanexpress.io/hooks-intro<p><img src="../_post_assets/hooks-intro/img/main.jpg" alt="a goat" class="center-block" /></p>
<p>The date was October 25, 2018. The setting was Las Vegas, Nevada. Facebook shocked the React development community at
<a href="https://conf.reactjs.org/">React Conf 2018</a>. I was there to watch Sophie Alpert and Dan Abramov
as they took the stage to present the keynote address.
They were there to reveal to the crowd, over 600 people in attendance, a completely new and
exciting way of writing React components. They called it “hooks.”</p>
<p>This article will show you the fundamentals of programming React components using hooks. I’ll
discuss the basic hooks built into React, and we’ll write a simple up/down counter component built
with a custom hook.</p>
<p>But before we dive too deep into hooks, let’s review a simple class component.</p>
<h2 id="class-component">Class component</h2>
<p>We’re all familiar with writing components with classes. What’s shown below is a simple up/down
counter component. It uses a <a href="../faccs-are-an-antipattern">render prop</a> to hand over control of the
rendering details to the caller.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">class</span> <span class="nx">Counter</span> <span class="kr">extends</span> <span class="nx">Component</span> <span class="p">{</span>
<span class="nx">constructor</span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">super</span><span class="p">(</span><span class="nx">props</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="nx">props</span><span class="p">.</span><span class="nx">initialCount</span> <span class="p">};</span>
<span class="p">}</span>
<span class="nx">decrement</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">(</span><span class="nx">state</span> <span class="o">=></span> <span class="p">({</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">}));</span>
<span class="p">};</span>
<span class="nx">increment</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">(</span><span class="nx">state</span> <span class="o">=></span> <span class="p">({</span> <span class="na">count</span><span class="p">:</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}));</span>
<span class="p">};</span>
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">count</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">;</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">decrement</span><span class="p">,</span> <span class="nx">increment</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="p">({</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">decrement</span><span class="p">,</span> <span class="nx">increment</span> <span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>We store the current count on state by calling <code class="highlighter-rouge">this.setState</code>. The state is stored on an instance
of the class. This is so that multiple components don’t inadvertently share information. We can
alter the <code class="highlighter-rouge">count</code> value by calling class property methods.</p>
<p>Remember, this is the logic for keeping the current <code class="highlighter-rouge">count</code> in state, and for incrementing and
decrementing the count. It doesn’t render anything by itself—the render prop does that—and yet we
still treat it as a component (i.e., we render it with <code class="highlighter-rouge"><Counter /></code>).</p>
<p>This seemed backwards, and the React core team thought that there must be a better way.</p>
<h2 id="standing-it-on-its-head">Standing it on its head</h2>
<p>What if we could somehow reverse everything? You know, stand it on its head. Instead of the logic
calling something to render, what if we started with what you want to render, and have that call—or
use—the logic to get the data that it needs? That’s what hooks are all about.</p>
<p>With this in mind, let’s start by writing a <code class="highlighter-rouge">Counter</code> function component that uses a custom hook.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">Counter</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">initialCount</span> <span class="p">})</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">increment</span><span class="p">,</span> <span class="nx">decrement</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useCounter</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">);</span>
<span class="k">return</span> <span class="p">(</span>
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
<span class="o"><</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">decrement</span><span class="p">}</span><span class="o">></span><span class="nx">Decrement</span><span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="nx">span</span><span class="o">></span><span class="p">{</span><span class="nx">count</span><span class="p">}</span><span class="o"><</span><span class="sr">/span</span><span class="err">>
</span> <span class="o"><</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">increment</span><span class="p">}</span><span class="o">></span><span class="nx">Increment</span><span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="p">);</span>
<span class="p">};</span>
</code></pre>
</div>
<p>This is nothing more than a function component. And, as you can see, it calls <code class="highlighter-rouge">useCounter</code> to get
the current <code class="highlighter-rouge">count</code>, as well as the functions to manipulate it. It deals with nothing but rendering,
which allows you to focus on just that, rather than on how the data is collected.</p>
<blockquote>
<p><em>By convention, hooks are prefixed with <code class="highlighter-rouge">use</code>.</em></p>
</blockquote>
<h3 id="the-hook-brings-you-back">The hook brings you back</h3>
<p>Now that you understand the rendering part of our component, let’s look at the implementation of the
<code class="highlighter-rouge">useCounter</code> custom hook.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="p">{</span> <span class="nx">useState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">useCounter</span> <span class="o">=</span> <span class="nx">initialCount</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">setCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">count</span><span class="p">,</span>
<span class="na">increment</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">currentCount</span> <span class="o">=></span> <span class="nx">currentCount</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span>
<span class="na">decrement</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">currentCount</span> <span class="o">=></span> <span class="nx">currentCount</span> <span class="o">-</span> <span class="mi">1</span><span class="p">),</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="k">default</span> <span class="nx">useCounter</span><span class="p">;</span>
</code></pre>
</div>
<p>Again, the code above has absolutely nothing to do with rendering. It’s simply a function that
returns the current count and methods to manipulate the count. In other words, everything that our
component needs to render.</p>
<p>But what’s with the <code class="highlighter-rouge">useState</code>? Well, React now provides a set of built-in hooks that you can use to
build larger custom hooks. Among the most basic is <code class="highlighter-rouge">useState</code>.</p>
<h3 id="usestate"><code class="highlighter-rouge">useState</code></h3>
<p><code class="highlighter-rouge">useState</code> is roughly synonymous with <code class="highlighter-rouge">this.state</code> and <code class="highlighter-rouge">this.setState</code> in class components. But
unlike <code class="highlighter-rouge">this.setState</code>, you don’t have to use an object. You can use any JavaScript type—boolean, string,
array, object … whatever. In fact, you are encouraged to use multiple <code class="highlighter-rouge">useState</code> calls, one for each
of your state values, instead of collecting them up into one object, like we are used to doing with class
components.</p>
<p>You call <code class="highlighter-rouge">useState</code> with the initial state, and it returns an array. This array contains two
elements. The first is the current state value. The second is a “setter” function. You use this to
change the state value.</p>
<p>It is worth noting that instead of passing an initial value, you may pass a function. If you do,
<code class="highlighter-rouge">useState</code> will only call it once to compute the initial value.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">someExpensiveProcedure</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">results</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">10000000</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// do someething with results</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">results</span><span class="p">;</span>
<span class="p">};</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">value</span><span class="p">,</span> <span class="nx">setValue</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">someExpensiveProcedure</span><span class="p">);</span>
</code></pre>
</div>
<h3 id="destructuring">Destructuring</h3>
<p>I mentioned above that <code class="highlighter-rouge">useState</code> returns an array with a current value and a setter function. It is
a common practice to destructure these values directly. You will rarely, for example, ever need to
store the return value directly.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialValue</span><span class="p">);</span>
</code></pre>
</div>
<p>Instead, simply destructure it inline.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="p">[</span><span class="nx">value</span><span class="p">,</span> <span class="nx">setValue</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialValue</span><span class="p">);</span>
</code></pre>
</div>
<h3 id="no-this">No <code class="highlighter-rouge">this</code>?</h3>
<p>Another thing that should pop out at you when working with hooks is there is no reference to <code class="highlighter-rouge">this</code>.
None at all. In fact, with hooks, you may never use <code class="highlighter-rouge">this</code> again.</p>
<p>React keeps track of component instances internally, leaving you free to write function
components.</p>
<h2 id="are-class-components-going-away">Are class components going away?</h2>
<p>The short answer is “No.” But let’s talk about it further.</p>
<p>In my opinion, once you start coding with hooks, you may be hard pressed to ever
write a class component again. They support most, if not all, of the capabilities of class
components, but without all of the ceremony. In fact the built-in
<a href="https://reactjs.org/docs/hooks-reference.html#useeffect"><code class="highlighter-rouge">useEffect</code></a> hook
mimics most of the lifecycle events that we are used to.</p>
<p>The React core team made it very clear—and took a lot of effort to ensure—that class components
could live side-by-side with hook components.</p>
<p>In fact, if you look at this from the standpoint of semantic versioning, 16.8.0
means that there are no breaking changes. That is important. If hooks came out in something like
17.0.0, we might have cause for alarm.</p>
<p>That said, if a class component fits your particular use case, then use a class component.
We all like shiny new things, but at the end of the day, it’s all about whatever is best from the
standpoint of the user’s experience and code maintainability.</p>
<h2 id="when-can-i-use-them-in-prod">When can I use them in prod?</h2>
<p>Right now! React 16.8.0 was released today, February 6, 2019. Update your <code class="highlighter-rouge">package.json</code> dependencies
and away you go!</p>
<h2 id="will-hooks-replace-render-props">Will hooks replace render props?</h2>
<p>I would guess that in most cases hooks will probably end up changing the way we write components today.
And that means for your day-to-day development that yes, hooks most likely will replace render props.</p>
<p>In fact Andrew Clark (from the React core team)
<a href="https://twitter.com/acdlite/status/1088509971015262208">tweeted</a> this earlier.</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Lol remember render props? What were we thinking</p>— Andrew Clark (@acdlite) <a href="https://twitter.com/acdlite/status/1088509971015262208?ref_src=twsrc%5Etfw">January 24, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Will there still be cases where a render prop is better suited for the task?
Sure. Render props won’t go away completely, but they will become less and less the norm.</p>
<p>Once you get comfortable with hooks, I’m sure you’ll agree.</p>
<blockquote>
<p>If you want to support both hooks and render props in the same package, take a look at
this article on the <a href="../hydra">Hydra pattern</a>.</p>
</blockquote>
<h2 id="performance-considerations">Performance considerations</h2>
<p>Performance should also be a consideration when writing hooks. In my <code class="highlighter-rouge">useCounter</code> above, the
reference to <code class="highlighter-rouge">increment</code> and <code class="highlighter-rouge">decrement</code> functions will change on each render. This is becasue they
are created and returned as arrow functions. This may cause your navigation controls to render
unnecessarily.</p>
<p>If rendering performance is a concern, the solution is—you guessed it—another hook. React provides
a <code class="highlighter-rouge">useCallback</code> hook for just this reason. We can wrap our callback functions in <code class="highlighter-rouge">useCallback</code> and
React will memoize them, assuring** that they point to the same function each time.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">useCounter</span> <span class="o">=</span> <span class="nx">initialCount</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">setCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">);</span>
<span class="kr">const</span> <span class="nx">increment</span> <span class="o">=</span> <span class="nx">useCallback</span><span class="p">(()</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">currentCount</span> <span class="o">=></span> <span class="nx">currentCount</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="p">[</span><span class="nx">setCount</span><span class="p">]);</span>
<span class="kr">const</span> <span class="nx">decrement</span> <span class="o">=</span> <span class="nx">useCallback</span><span class="p">(()</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">currentCount</span> <span class="o">=></span> <span class="nx">currentCount</span> <span class="o">-</span> <span class="mi">1</span><span class="p">),</span> <span class="p">[</span><span class="nx">setCount</span><span class="p">]);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">count</span><span class="p">,</span>
<span class="nx">increment</span><span class="p">,</span>
<span class="nx">decrement</span><span class="p">,</span>
<span class="p">};</span>
<span class="p">};</span>
</code></pre>
</div>
<p>This is similar to the case we had with class components where it was more performant to place
callback functions on the instance instead of passing lamda functions to components.</p>
<blockquote>
<p>** Actually, the memoization is not guaranteed. React says that it may choose to “forget” some
of the memoization for memory allocation reasons. I still believe that it is well worth the
effort.</p>
</blockquote>
<h2 id="other-hooks">Other hooks</h2>
<p>React provides more built-in hooks that I haven’t discussed in this article; some you may never
use. Others, like <code class="highlighter-rouge">useEffect</code>, you may use quite often.</p>
<p>You can read all about the built-in hooks in the
<a href="https://reactjs.org/docs/hooks-reference.html">Hooks API Reference</a>.</p>
<h2 id="should-i-refactor-my-entire-codebase">Should I refactor my entire codebase?</h2>
<p>I’m not going to tell you what to do, but if it were me, I’d leave it alone. In other words, if it
works, don’t touch it. I’m sure you have new code that you could be writing rather than spending your
time refactoring old code to use hooks.</p>
<p>If you’re in there anyway making a change, maybe you could do the conversion. And if you’ve
written tests, you should be good to go.</p>
<p>Which brings us to…</p>
<h2 id="how-do-i-test-a-custom-hook">How do I test a custom hook?</h2>
<p>There are two answers to this question, depending on how you are distributing your hook.</p>
<p>If you are consuming your custom hook within a component and have no plans to ship it as a
stand-alone hook, you would test the component that uses the hook just as you did with a class
component (i.e., you will be testing the hook by testing the component itself—no need to
specifically test the hook).</p>
<p>However, if your custom hook will be distributed as a general-purpose solution for others to build
components with, it must be tested on its own. You might think that because it’s just a function
that you could test it as such. Maybe something like this.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">test</span><span class="p">(</span><span class="s1">'useCounter'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">decrement</span><span class="p">,</span> <span class="nx">increment</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useCounter</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">increment</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nx">decrement</span><span class="p">();</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">});</span>
</code></pre>
</div>
<p>Simple, huh? There’s only one problem. It won’t work.</p>
<p>The base hooks that React provides must be called from within the rendering of a component. If you
run the test above, you will receive this error.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>Invariant Violation: Hooks can only be called inside the body of a function component.
</code></pre>
</div>
<p>Then what do we do? The solution is to use a test helper that wraps your custom hook in a component,
but exposes what is returned from your hook to your test.</p>
<p>I’ve written such a helper that’s included in Kent C. Dodds’
<a href="https://github.com/kentcdodds/react-testing-library"><code class="highlighter-rouge">react-testing-library</code></a>. It’s called
<code class="highlighter-rouge">testHook</code>.</p>
<h3 id="testhook"><code class="highlighter-rouge">testHook</code></h3>
<p>To get started, just import it from <code class="highlighter-rouge">react-testing-library</code> as follows.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="p">{</span> <span class="nx">cleanup</span><span class="p">,</span> <span class="nx">act</span><span class="p">,</span> <span class="nx">testHook</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react-testing-library'</span><span class="p">;</span>
</code></pre>
</div>
<p>Let’s take the test from above and adapt it so that it will work. Here, we wrap the call to
<code class="highlighter-rouge">useCounter</code> in a callback funtion passed to <code class="highlighter-rouge">testHook</code>. The working test looks like this.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">test</span><span class="p">(</span><span class="s1">'useCounter'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">decrement</span><span class="p">,</span> <span class="nx">increment</span><span class="p">;</span>
<span class="nx">testHook</span><span class="p">(()</span> <span class="o">=></span> <span class="p">({</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">decrement</span><span class="p">,</span> <span class="nx">increment</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useCounter</span><span class="p">(</span><span class="mi">1</span><span class="p">)));</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">act</span><span class="p">(</span><span class="nx">increment</span><span class="p">);</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nx">act</span><span class="p">(</span><span class="nx">decrement</span><span class="p">);</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">});</span>
</code></pre>
</div>
<p>We also must place our deconstructed variables that are returned from the hook in <code class="highlighter-rouge">let</code> statements
<em>outside</em> of the callback. This is so that they are in scope of the tests. They will also be in
scope of the callback.</p>
<p>The only other thing that is a bit unsusal is that we must wrap any functions returned from the
hook in an <code class="highlighter-rouge">act</code>. If not, we will get a warning. As we aren’t passing any arguments, we can simply
pass a pointer to the function. If we were to pass arguments, we would need to use a lambda.</p>
<p>For example, if we had a function called <code class="highlighter-rouge">incrementBy</code> that required an argument,
we would need do this.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">act</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">incrementBy</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">});</span>
</code></pre>
</div>
<h2 id="conclusion">Conclusion</h2>
<p>Hooks represent a huge step forward in React component development. If you aren’t already using hooks now, I
assure you that you will be in the coming months. I hope this article provides you with enough information to get
you started on the right track.</p>Donavon WestUsing Git Bisect To Find Bugs2019-01-02T00:00:00-05:002019-01-02T00:00:00-05:00https://americanexpress.io/git-bisect<p><img src="../_post_assets/git-bisect/img/main.jpg" alt="a white geometric building" class="center-block" /></p>
<blockquote>
<p>“This thing is broken!” - your QA engineer</p>
<p>“It worked last week!” - you, probably</p>
<p>“Can you get it working then?” - everyone else</p>
</blockquote>
<p>Sound familiar? Any of you who’ve been in software engineering for more than
a few months have undoubtedly been told this by a user, someone on your QA team,
or even a coworker. You sit down at your desk, run through the steps - and sure
enough! That thing that was working last week no longer works. But why not?</p>
<p>You may be able to clearly see an issue. If not, you could consider using the
history of changes as given by your version control system. Commands like
<code class="highlighter-rouge">git log</code> are useful for figuring out why and when things changed (you are using
good commit messages, right?) but as you know things are not always that simple.
Sometimes a change from another part of the code impacts your feature in an
unexpected way and breaks things. So, having spent some time looking at
the history of the file with the new bug, you move up and pull up the history
of your whole project. Hundreds of commits. Ugh.</p>
<h2 id="good-commit-messages">Good Commit Messages</h2>
<p>Your task will be much simpler if your team is making good use of commit messages.
Hopefully the list of commits you’re looking at includes details about what is changing,
and not things like “Fixed the bug”. “Fixed the login button on the fingerprint login popup”
would be much better, and it’s easy to see how this would be more useful for someone looking
for a potential change sometime in the future. Hopefully your project also builds at each
commit - this will be useful later on while we’re searching through them trying to find
the point at which things broke.</p>
<p>There has to be a better way than blindly looking through commit messages though - and there is!
Let’s take a look at <code class="highlighter-rouge">git bisect</code>.</p>
<h2 id="git-bisect">Git Bisect</h2>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git bisect start HEAD 134237c40d6f79777a4def9a361cf12730bc5ddd
<span class="gp">$ </span><<span class="nb">test </span>your code>
<span class="gp">$ </span>git bisect bad
<span class="gp">$ </span><<span class="nb">test </span>your code>
<span class="gp">$ </span>git bisect good
<span class="gp">$ </span><span class="o">(</span>repeat<span class="o">)</span>
</code></pre>
</div>
<p>Bisect is like running a binary search on your codebase for the commit that
introduced a change. It all starts by running <code class="highlighter-rouge">git bisect start</code>. You can pass
in two commits when you <code class="highlighter-rouge">start</code> to indicate the range which you’d like to search.
In the sample above, we pass HEAD, which is the current code you know is broken,
and 134237c4…5ddd which is a commit that we know is
good. You can also pass a tag name instead of a commit SHA (Secure Hash Algorithm),
if that’s easier.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>Bisecting: 4 revisions left to <span class="nb">test </span>after this <span class="o">(</span>roughly 2 steps<span class="o">)</span>
<span class="o">[</span>48ac08bdb0576b326c6fd85c1df47e5726ca077f] Revert <span class="s2">"Renamed hello() method to hi()"</span>
</code></pre>
</div>
<p>Git will inform you that you’re bisecting and give you an indication of how many
more commits you’ll need to test before you’ve found your issue. Run your code
to see if you can reproduce your bug. If you can, use <code class="highlighter-rouge">git bisect bad</code> to tell
git that the commit is broken. If you can’t reproduce the bug use <code class="highlighter-rouge">git bisect good</code>
to give that information to git. Each time, you’ll be left on a new commit to test
with an indication of about how many more steps there are. If you need to skip a
commit for any reason, you can do that with <code class="highlighter-rouge">git bisect skip</code>.</p>
<h2 id="shortcuts">Shortcuts</h2>
<p>As I mentioned earlier, you’ll want to make sure that every commit that people are
adding to your project will compile on its own. This means that every commit you land
on while using <code class="highlighter-rouge">git bisect</code> will be able to be compiled, which you’ll need to do by
hand. You’re doing the same thing each time - compiling your project and testing it.
There’s a way to speed that up!</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>~/P/BisectDemo <span class="nv">$ </span>git bisect start HEAD 134237c40d6f79777a4def9a361cf12730bc5ddd
Bisecting: 4 revisions left to <span class="nb">test </span>after this <span class="o">(</span>roughly 2 steps<span class="o">)</span>
<span class="o">[</span>48ac08bdb0576b326c6fd85c1df47e5726ca077f] Revert <span class="s2">"Renamed hello() method to hi()"</span>
~/P/BisectDemo <span class="nv">$ </span>git bisect run ./test-for-args.sh
running ./test-for-args.sh
Building at 48ac08bdb0576b326c6fd85c1df47e5726ca077f
Bisecting: 2 revisions left to <span class="nb">test </span>after this <span class="o">(</span>roughly 1 step<span class="o">)</span>
<span class="o">[</span>7634a2192d8dcad223dccb2c0adcc5f0aa720373] Added kotlin native version to printout
running ./test-for-args.sh
Building at 7634a2192d8dcad223dccb2c0adcc5f0aa720373
Bisecting: 0 revisions left to <span class="nb">test </span>after this <span class="o">(</span>roughly 0 steps<span class="o">)</span>
<span class="o">[</span>25bd37d3125caaa3177be7cbd752856e8c2cc706] Added ability to print out and additional arguments which are passed on the CLI
running ./test-for-args.sh
Building at 25bd37d3125caaa3177be7cbd752856e8c2cc706
25bd37d3125caaa3177be7cbd752856e8c2cc706 is the first bad commit
commit 25bd37d3125caaa3177be7cbd752856e8c2cc706
Author: Matthew S. Runo <matthew@example.com>
Date: Mon Dec 3 15:40:46 2018 -0800
Added ability to print out any additional arguments which are passed on the CLI
:040000 040000 6dd3965194bf3e7665e87429bc35e57b3643edd4 56e99d23cbd924d73beb48e42dae090f11f5af38 M src
bisect run success
~/P/BisectDemo <span class="err">$</span>
</code></pre>
</div>
<p>Bisect allows you to run a command after each new checkout of the code, totally
automating the process of finding your bug. You can provide a script that uses exit
codes to communicate good or bad to git. A script that exits with code <code class="highlighter-rouge">0</code> will indicate
to git that the code is good. Your script can exit with just about any other exit code
(1 to 127, except 125) to indicate the code is bad. If you need to skip a commit, you
can return exit code 125 (but all your commits compile, right?).</p>
<p>In the above sample, my script was as simple as the following. The bug I was trying
to find is that command line arguments are being printed out on standard output -
maybe someone left in some debugging println statements.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="nb">echo</span> <span class="s2">"Building at </span><span class="k">$(</span>git rev-parse HEAD<span class="k">)</span><span class="s2">"</span>
./gradlew build &> /dev/null
<span class="nv">output</span><span class="o">=</span><span class="k">$(</span>./build/bin/macos/main/release/executable/BisectDemo.kexe <span class="nb">test</span><span class="k">)</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$output</span> <span class="o">==</span> <span class="k">*</span><span class="s2">"test"</span><span class="k">*</span> <span class="o">]]</span>; <span class="k">then
</span><span class="nb">exit </span>1
<span class="k">fi
</span><span class="nb">exit </span>0
</code></pre>
</div>
<p>All I did to find the offending commit was run the following two commands.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="c"># Start the bisect passing in HEAD and the last known good commit</span>
git bisect start HEAD 134237c40d6f79777a4def9a361cf12730bc5ddd
<span class="c"># Tell git to use my script.</span>
git bisect run ./test-for-args.sh
</code></pre>
</div>
<p>After building the project a few times, I was left on the commit that introduced
the code that added the bug. I can look at the diff for the commit, and sure
enough - it added some println statements that are printing out the command
line arguments. Oops! Looks like they forgot to revert this before opening a
pull request for their code.</p>
<h2 id="wrapping-up">Wrapping up</h2>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git bisect bad
25bd37d3125caaa3177be7cbd752856e8c2cc706 is the first bad commit
commit 25bd37d3125caaa3177be7cbd752856e8c2cc706
Author: Matthew S. Runo <matthew@example.com>
Date: Mon Dec 3 15:40:46 2018 -0800
Added ability to print out any additional arguments which are passed on the CLI
:040000 040000 6dd3965194bf3e7665e87429bc35e57b3643edd4 56e99d23cbd924d73beb48e42dae090f11f5af38 M src
bisect run success
</code></pre>
</div>
<p>Eventually you’ll be finished with the search of commits that could cause your
issue, and git will give you the exact commit that introduced your bug along with
the author and date when it was committed. You can take this information and use
it to shame your teammate - or, even better - you can look at the files changed
in the commit and see which change is relevant to your bug and resolve the issue.
This is another reason why small commits are better - imagine if you’re left on a
commit that changes 100 different files! Good luck!</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git bisect reset
Previous HEAD position was a1a43d1070... bugfix - <span class="k">if </span>session timed out, log user out
Switched to branch <span class="s1">'main'</span>
Your branch is up-to-date with <span class="s1">'origin/main'</span>.
</code></pre>
</div>
<p>Once you’re ready <code class="highlighter-rouge">git bisect reset</code> will get you back to HEAD so you can fix the issue.</p>
<h2 id="in-closing">In Closing</h2>
<p>Git bisect is a great tool when you only know that something was working last week
but the actual cause of a bug isn’t immediately clear. By helping git do a binary
search via <code class="highlighter-rouge">good</code> and <code class="highlighter-rouge">bad</code> you’ll soon be at the commit that introduced your bug.
You can speed up the process and get some time for coffee by using <code class="highlighter-rouge">run</code> and letting
a script do the work for you.</p>Matthew RunoVisibility2018-12-11T00:00:00-05:002018-12-11T00:00:00-05:00https://americanexpress.io/visibility<p><img src="../_post_assets/visibility/img/main.jpg" alt="red tulip in a field of yellow tulips" class="center-block" /></p>
<p><em>[The following was originally delivered as a presentation at the 2018 Grace Hopper Celebration</em>
<em>of Women in Computing. — Ed.]</em></p>
<h2 id="myths">Myths</h2>
<p>Many people believe one or more of the following myths about getting ahead:</p>
<ul>
<li>If you do your job well, you will be “discovered” (like a barista in Hollywood that gets
discovered by a movie director?)</li>
<li>Your work speaks for itself (Sure, to your boss, but you need a wider audience!)</li>
<li>Getting ahead requires constant self-promotion (We all know this kind of person, right?)</li>
<li>It’s all about relationships (Not if your work isn’t great.)</li>
<li>It’s all about what you deliver (Not if nobody sees or knows about it.)</li>
</ul>
<p>If the only people seeing your good work are your peers and your boss, you’re leaving so much
opportunity on the table. The fact is, <strong>doing your job well is table stakes</strong>. Don’t wait to be
discovered. Get yourself noticed and <strong>be seen doing what you do best!</strong></p>
<p>But how?</p>
<h2 id="make-yourself-visible">Make yourself visible</h2>
<p>Here are 10 tips that you can start putting to use today.</p>
<h3 id="1-be-the-messenger">1. Be the messenger</h3>
<p>The messenger of good news gets the “halo” of credit. Announce your team’s
successes (but not your own). Celebrate and promote those around you at every opportunity.</p>
<blockquote>
<p>All of those celebratory mails that get sent out for major releases actually achieve more than the
stated purpose of celebrating the team’s success. They also give positive visibility to the person
who sends the note. As a leader, I try not to be the person to send these mails,
because I want to give that credit and visibility to the team members who achieved the success. If
you’re looking to increase your visibility, find ways to announce the successes of your team
members and colleagues. Don’t do this too often, as this hand can easily be overplayed. And NEVER
be seen congratulating yourself or your own achievements – that’s not a good look on anyone.</p>
</blockquote>
<h3 id="2-speak-up">2. Speak up</h3>
<p>When you speak at meetings (and you really must) make sure what you say is
concise, on-point, and interesting. Be brief and bold!</p>
<blockquote>
<p>Some time ago, there was a meeting at American Express that brought together a collection of senior
technology leaders to listen to and interact with a well-known tech thought leader from outside of
the company. I participated in the spirited conversation that took place, and enjoyed watching my
colleagues in action, debating and sharing. An hour after that meeting, I had a one-on-one meeting
with one of the leaders in my own organization. She asked me what I thought of the conversation
that just took place, and I hadn’t even realized she was in the room.
This leader told me that she didn’t feel it was
her place to speak up among those senior leaders, and she preferred just to listen and learn. But
by not speaking up, she missed an opportunity to be seen by her peers and leaders. Opportunities
like that are rare, and you should make the most of them. When you look and
act like a leader, people treat you like a leader.</p>
</blockquote>
<h3 id="3-make-friends">3. Make friends</h3>
<p>How’s your small talk? The ability to engage strangers in conversation is one
of the best ways to expand your network.</p>
<blockquote>
<p>This was one of the hardest skills for me to work on, personally. I’m awkward and uncomfortable
with strangers. I don’t know what to talk about. I’d far rather sit in the corner and play with my
phone than engage with a room full of strangers or even colleagues. But those conversations create
the relationships you need. Each one by itself may not feel particularly important, but over the
course of a year, the dozens or hundreds of conversations end up building visibility and
followership. So, how do you practice this skill without wanting to run and hide? My coach gave me
this advice that changed the way I think about the interaction. She said, “Imagine that the person
you are talking to is a guest at YOUR dinner party. One of your friends brought a pal you’ve never
met. What is your role here? It’s to make him comfortable. You are on your turf, in your house, at
your party, and this person is a guest. Make him feel at home!” Framing the interaction this way
really helped me put the focus on the other person rather than on myself. I used to be worried
about how <em>I</em> felt, what <em>I</em> would say, what <em>I</em> looked like. But now I am focused on my “guest”.
How can I make him feel at home? Try this, and I bet you’ll be amazed at how much easier it gets to
talk to strangers.</p>
</blockquote>
<h3 id="4-sign-up">4. Sign up</h3>
<p>Volunteer for extra-credit projects that nobody else wants to take on, and then
ROCK them.</p>
<blockquote>
<p>Every company has something that needs to be done, but nobody wants to do it. Become the expert at
these kinds of assignments. Use them to demonstrate how even boring work can be made interesting.
Show off your organizational skills, your visual representations, and use this side-job to create
relationships outside of your immediate organization. If you demonstrate how you bring
enthusiasm and creativity to a boring, tedious project, you’ll more readily come to mind
when leadership has something critically important that needs the same loving care and
attention. You’ll be seen as someone dependable and who excels without oversight. That’s
what you want, right?</p>
</blockquote>
<h3 id="5-fix-it">5. Fix it</h3>
<p>Take the initiative to fix the “broken” things that people have just gotten used to.
You’ll be a hero if you succeed, and you’ll get to meet folks outside of your immediate team.</p>
<blockquote>
<p>This particular technique has worked really well for me.
So here’s my suggestion: when you notice things
that you think could be better, help people around you see what the world could be like if the problem
was fixed. There’s no need to denigrate the problem or speak negatively about how it came to be. In
fact, that’s more likely to give you a reputation as a complainer – a kind of visibility you
<strong>don’t</strong> want. Instead, build a vision, communicate that vision, and then work persistently and
respectfully to bring it about. Talk about the benefits it will bring, and find like-minded
colleagues to fight the good fight alongside you as a coalition (many voices are stronger than
one). If you fail, there’s no downside, because nobody believed you could succeed anyway. If you
succeed, you’ll develop a reputation as someone who can execute against a vision and gather and lead a
team to get things done.</p>
</blockquote>
<h3 id="6-how-am-i-doing">6. How am I doing?</h3>
<p>Ask for feedback and advice from people you admire, and then take that feedback graciously.</p>
<blockquote>
<p>Here’s a surprisingly useful tip: start asking for advice rather than feedback. Feedback is
something you give to correct someone’s behavior, but advice is something you give to friends
because you want them to be better. If you frame the question this way, it should be comfortable
for you to ask for advice from your employees, your peers, or your leaders. Often! Really often! If
you can get used to doing this frequently, you’ll be seen as someone who is interested in constant
improvement, and you’ll earn the right to give advice to others. Being specific is key here. Not
just, “Do you have any advice for me?” but rather, “How did you think that meeting with the boss went? Do
you have advice for how I might have been more convincing?”</p>
</blockquote>
<h3 id="7-share-it">7. Share it</h3>
<p>Become a subject matter expert. Find others in your company who need your
expertise and offer it freely and generously. Create a discussion channel around your interest and
invite others to discuss.</p>
<blockquote>
<p>We use a discussion forum at work, and it’s one of the very best ways to create a larger network
beyond your immediate team. Every person is a subject matter expert at <em>something</em>, or has a deep
interest and desire to learn. I have created channels for #food, #meditation, and #influence. What
is your calling? I once had an engineer on my team who was the only person in my
organization who used a particularly rare and specific technology. When she brought this to my attention, I
suggested that she create a discussion channel about this tech,
so she invited everyone we could find who was using this tech to join the channel.
After a few weeks, she had dozens of members on her channel, and they were discussing
the fine points of different implementations. Now, think about this: When she’s ready for another
role with more responsibility, don’t you think this network will be useful? She now knows every
other place in the organization where this tech is used, and by whom. Pretty much exactly the
same network she’ll need to find her next role!</p>
</blockquote>
<h3 id="8-get-help">8. Get help</h3>
<p>Ask for a mentor, career sponsor or advocate. Having one or more advocates can
help you stay aware of roles you might otherwise have missed.</p>
<blockquote>
<p>Many of the people I coach are afraid to ask someone they admire for mentoring or coaching. But
think about it: How often have you seen someone say “No” when you’ve asked them for help? It’s quite
rare. Ask for what you want, and you will very likely get it! But be prepared with a <em>specific</em>
question or problem, and once you’ve discussed it, don’t waste the rest of the
time you have with the leader. Thank them, and then go think about what they said. You’re free to
follow up in a subsequent visit. For example, I don’t set up regular meetings, but instead encourage people to
meet me on an ad-hoc basis when they actually need something.</p>
</blockquote>
<h3 id="9-speak-out">9. Speak out</h3>
<p>Look for opportunities to speak externally at meetups, schools and events.
If you’re not comfortable with speaking,
start practicing!</p>
<blockquote>
<p>Not only will it broaden your network beyond the boundaries of your team and your company, it’s also
good practice for the more senior roles you might be craving. As an example, I started sharing the information in this presentation internally at my company before I ever knew
I’d share it externally. That simple act generated a HUGE amount of visibility and goodwill across
the organization, including with product teams, engineers, colleague networks and more.</p>
<p>The positive response surprised me, even though I was following my own advice!</p>
</blockquote>
<h3 id="10-observe">10. Observe</h3>
<p>Watch the people in your organization who ARE well-known. What do they do that you
could learn from? Compare different styles.</p>
<blockquote>
<p>This last tip may sound simple, but it’s a practice you should begin now and hone over the course
of your career. When you’re fortunate enough to be in a meeting with leaders in your organization,
watch them. Watch how they act and choose a behavior or two to model yourself. Trying on behaviors
that leaders do is a way to learn how to wield that skill. See what works for you. See who moves
the room, who looks reserved, who looks like they have power or authority. Why do they look that
way, and can you integrate some of that into your own way of being? You’ll be amazed at what you
can learn!</p>
</blockquote>
<h2 id="last-words-of-advice">Last words of advice</h2>
<p>Stick with assignments you can have fun with and that you are passionate
about. Nobody likes a Grumpy Gus who is doing things just to get ahead. Make allies who agree with
you to build a coalition – they might be your peers as you move up in the organization. Don’t make
enemies, but don’t shy away from (respectfully) being on the other side of the argument when it’s
the right thing.</p>
<p><strong>And don’t take things too seriously! Have fun! It’s contagious!</strong></p>Aimee CardwellOn the Importance of Commit Messages2018-12-10T00:00:00-05:002018-12-10T00:00:00-05:00https://americanexpress.io/on-the-importance-of-commit-messages<p><img src="../_post_assets/on-the-importance-of-commit-messages/img/main.jpg" alt="magnifying glass over an old book" class="center-block" /></p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git log
commit f9d601108fd2a19ff7b5dfc62a790083b9af500c
Author: CF Frost <cf.frost@example.com>
Date: Wed Jan 17 14:08:36 2018 -0500
fixed that bug
commit 253b7e2f445e65222ef81f33cf4070660084a3dc
Author: CF Frost <cf.frost@example.com>
Date: Wed Jan 17 14:07:05 2018 -0500
tweaks to button styles
commit 7e12e77eae5e4ca80e7b3fb55db5c6d954d2cbe4
Author: CF Frost <cf.frost@example.com>
Date: Wed Jan 17 14:06:16 2018 -0500
added a new action
</code></pre>
</div>
<p>We’ve all seen Git histories like this. To some it’s no big deal, but on my team
this will get your pull request (PR) declined regardless of how your code looks.
In fact we won’t merge your PR unless your commit messages conform to a very
specific standard: <a href="https://conventionalcommits.org">Conventional Commits</a>. We
chose this standard for its readability and its ability to automate our semantic
versioning & changelog.</p>
<p>Conventional commits are structured as <code class="highlighter-rouge"><type>(<scope>):<subject></code>. (I’ll let
you read the above document for further details on the convention.) Adhering to
this structure with detailed subjects and message bodies when appropriate allows
us to create a truly meaningful history. When browsing this history we can
really see the progression of development, and when reviewing PRs we have a
brief summary of changes right in front of us. However, the real value of a
meaningful commit message may not come for months down the road.</p>
<h2 id="a-case-study">A Case Study</h2>
<blockquote>
<p>The following is based on actual events.</p>
</blockquote>
<p>Let’s say we have a software engineer named Dorcas. Dorcas’s product owner,
Throckmorton, came to her to ask, “Why doesn’t this user see the same links that
I do on the homepage?”. Dorcas didn’t know, so she told him that she would find
out and get back to him. Dorcas only took a few minutes to find the code that
was causing the issue Throckmorton had called out. She looked through the commit
history on BitBucket and saw this commit:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>commit 3b85fbfebac285745e15da57e89d591dac21a3fe
Author: Myrtle Carter <myrtle.carter@example.com>
Date: Fri Aug 4 15:58:12 2017 -0400
feat<span class="o">(</span>links<span class="o">)</span>: filtered out links <span class="k">for </span>non-premium users
Only premium users should see links to premium features.
JIRA-1337
</code></pre>
</div>
<p>Myrtle left Dorcas a gold mine of information in this commit message. Now she
can see that the reason for the filtering has to do with premium features. She
even included a message body with a bit of reasoning behind the change. There is
something else really important here that we haven’t discussed yet: a JIRA task
ID. With this, Dorcas was able to look up the JIRA task and learn even more
details about the change and why it was done. As it turns out, the given user
was not a premium user. She is able to write up a quick instant message with an
explanation and a link to the JIRA task and send it off to Throckmorton.</p>
<p>Thanks to Myrtle’s diligence in her commit messages, a great deal of time
searching is saved for Dorcas and anyone she would have had to otherwise engage
to find the answer Throckmorton needed.</p>
<h2 id="squashing-commits">Squashing commits</h2>
<p>Another key that helped Dorcas find the answer so quickly, was her team’s
practice of squashing commits before merging PRs and keeping PRs small (limited
to a single feature). This keeps “work in progress” commits out of the history,
so that each commit is more meaningful and the history as a whole is easier to
read and understand. Most hosted git solutions have a built-in option for
squashing commits when merging PRs, but it can also be done manually through a
soft reset and commit or an interactive
<a href="https://git-scm.com/docs/git-rebase">rebase</a>. For the following example, we’ll
walk through a soft reset and commit assuming that the user is making a pull
request from <code class="highlighter-rouge">feature/user-alert</code> to <code class="highlighter-rouge">main</code>.</p>
<ol>
<li>First, make sure we are up-to-date by fetch the latest from our origin repo.
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git fetch origin
</code></pre>
</div>
</li>
<li>Then we will do a soft reset to <code class="highlighter-rouge">main</code> which will make our git history
identical to that of <code class="highlighter-rouge">main</code>, and stage our changes to be committed.
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git reset --soft origin/main
</code></pre>
</div>
</li>
<li>Now we are ready to commit.
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git commit
</code></pre>
</div>
</li>
<li>After committing we’ll need to force push since we are rewriting history.
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>git push origin feature/user-alert -f
</code></pre>
</div>
</li>
</ol>
<blockquote>
<p>It is worth noting that there are rare occasions when it makes sense to have
multiple commits in a single PR, as long as each of those commits represents
an individual unit of work. Like the pirate code, this is more of a guideline
than an actual rule.</p>
</blockquote>
<h2 id="tooling">Tooling</h2>
<p>There are some great open source couple tools for JavaScript projects that can
set us up for success with our commit messages.
<a href="http://marionebl.github.io/commitlint/"><code class="highlighter-rouge">commitlint</code></a> provides a CLI for
validating commit messages. We’ll need to install this CLI and our config before
continuing.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>npm install --save-dev @commitlint/cli @commitlint/config-conventional
</code></pre>
</div>
<p>To add our config we’ll create a <code class="highlighter-rouge">commitlint.config.js</code> in the root of our
project:</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">extends</span><span class="p">:</span> <span class="p">[</span><span class="s1">'@commitlint/config-conventional'</span><span class="p">]</span>
<span class="p">};</span>
</code></pre>
</div>
<p>Using <a href="https://www.npmjs.com/package/githook-scripts"><code class="highlighter-rouge">githook-scripts</code></a> we can
easily add this into our workflow with the following <code class="highlighter-rouge">package.json</code>
configuration:</p>
<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="nt">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nt">"githook:commit-msg"</span><span class="p">:</span><span class="w"> </span><span class="s2">"commitlint --edit $GIT_PARAMS"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>A contributor could try to get past that without a valid commit message by using
the <code class="highlighter-rouge">--no-verify</code> flag when they commit, so we’ll add a test for the git
history, which we can use in our PR build process to validate all commits in the
branch that aren’t in main yet. This is recommended to be run in your <code class="highlighter-rouge">test</code>
script like so:</p>
<div class="language-json highlighter-rouge"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="nt">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nt">"test:spec"</span><span class="p">:</span><span class="w"> </span><span class="s2">"jest"</span><span class="p">,</span><span class="w">
</span><span class="nt">"test:git-history"</span><span class="p">:</span><span class="w"> </span><span class="s2">"commitlint --from main --to HEAD"</span><span class="p">,</span><span class="w">
</span><span class="nt">"test"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npm run test:spec && npm run test:git-history"</span><span class="p">,</span><span class="w">
</span><span class="nt">"githook:pre-commit"</span><span class="p">:</span><span class="w"> </span><span class="s2">"npm test"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>Now you are all set and ready to rock with your detailed & meaningful commit
messages. Though it may take some time to get used to for a team that hasn’t
enforced commit message standards before, it’s sure to save you some headaches
down the line. While this may not be for every team, it certainly has been
beneficial for mine. Many other teams within American Express have differing
approaches with their histories and still deliver quality software to
production.</p>Jamie KingSupport both Hooks and Render Props with One Simple Trick2018-11-06T00:00:00-05:002018-11-06T00:00:00-05:00https://americanexpress.io/hydra<p>Share logic in your React package with support for both custom Hooks and class components by using
the Hydra pattern.</p>
<p><img src="../_post_assets/hydra/img/main.jpg" alt="Hercules Slaying the Hydra, From the Labors of Hercules" class="center-block" /></p>
<p>Here’s a scenario I’d like you to consider…</p>
<p>You are the author of the wildly popular npm package <code class="highlighter-rouge">awesome-counter</code>. It supports all the logic
necessary to build an up/down counter. It holds the count in state and provides functions to
increment and decrement the count. And, because you are a good citizen, and want to give control of
how things are rendered to the consumer of the component, you of course support render props.</p>
<p>A sample implementation is shown here.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="o"><</span><span class="nx">Counter</span><span class="o">></span>
<span class="p">{({</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">incCount</span><span class="p">,</span> <span class="nx">decCount</span> <span class="p">})</span> <span class="o">=></span> <span class="p">(</span>
<span class="o"><></span>
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="p">{</span><span class="nx">count</span><span class="p">}</span><span class="o"><</span><span class="sr">/h1</span><span class="err">>
</span> <span class="o"><</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">decCount</span><span class="p">}</span><span class="o">></span><span class="nx">Count</span> <span class="nx">Down</span><span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">incCount</span><span class="p">}</span><span class="o">></span><span class="nx">Count</span> <span class="nx">Up</span><span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/</span><span class="err">>
</span> <span class="p">)}</span>
<span class="o"><</span><span class="sr">/Counter</span><span class="err">>
</span></code></pre>
</div>
<p>That’s great! It’s easy to use and flexible.</p>
<p>But what’s all that talk about render props being dead, now that Hooks are a thing in React 16.7?</p>
<blockquote>
<p>Note: Hooks is an experimental technology proposed by the React core team and available for use
in React 16.7.0-alpha but are NOT production ready.</p>
</blockquote>
<p>You can add support for Hooks, but you can’t just bump the major version number on <code class="highlighter-rouge">awesome-counter</code>
and drop support for render props. Well, you could, but you’d have hundreds of thousands of unhappy
users who rely on render props support.</p>
<p>There has to be a way to support both components with render props and the new custom Hooks. Well
there is, and I call it a Hydra Component.</p>
<h2 id="what-is-the-hydra-pattern">What is the Hydra pattern?</h2>
<p>A hydra is a mythical creature with multiple heads. A package that follows the Hydra pattern
contains all of the logic and state, and exports both a custom Hook, as well as a component that
accepts a render prop. It too has multiple heads, if you will.</p>
<p>Here are the requirements for a Hydra package:</p>
<ol>
<li>Export a React component as <code class="highlighter-rouge">default</code>.</li>
<li>The exported component uses a render prop.</li>
<li>Export a custom Hook as a named export. The name must begin with <code class="highlighter-rouge">use</code>.</li>
</ol>
<h2 id="converting-to-a-hydra-package">Converting to a Hydra package</h2>
<p>Here are the steps to convert a standard component that accepts a render prop to a Hydra
component.</p>
<p>First let’s take a look at the code of our <code class="highlighter-rouge">awesome-counter</code> component.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">renderProps</span> <span class="nx">from</span> <span class="s1">'render-props'</span><span class="p">;</span>
<span class="kr">class</span> <span class="nx">Counter</span> <span class="kr">extends</span> <span class="nx">Component</span> <span class="p">{</span>
<span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="na">count</span><span class="p">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">initialCount</span> <span class="p">};</span>
<span class="nx">deltaCount</span> <span class="o">=</span> <span class="nx">delta</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">(({</span> <span class="nx">count</span> <span class="p">})</span> <span class="o">=></span> <span class="p">({</span> <span class="na">count</span><span class="p">:</span> <span class="nx">count</span> <span class="o">+</span> <span class="nx">delta</span> <span class="p">}));</span>
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">count</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">;</span>
<span class="kr">const</span> <span class="p">{</span> <span class="nx">children</span><span class="p">,</span> <span class="nx">render</span> <span class="o">=</span> <span class="nx">children</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">props</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">count</span><span class="p">,</span>
<span class="na">incCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">deltaCount</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
<span class="na">decCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">deltaCount</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">renderProps</span><span class="p">(</span><span class="nx">render</span><span class="p">,</span> <span class="nx">props</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">Counter</span><span class="p">.</span><span class="nx">defaultProps</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">initialCount</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="k">default</span> <span class="nx">Counter</span><span class="p">;</span>
</code></pre>
</div>
<p>If you’ve been coding in React for any time at all, the code above should look pretty familiar. We
set up <code class="highlighter-rouge">state</code> to hold our <code class="highlighter-rouge">count</code> and update it when someone calls <code class="highlighter-rouge">incCount</code> or <code class="highlighter-rouge">decCount</code>. They
are all passed as <code class="highlighter-rouge">props</code> to the render prop function or component.</p>
<p>Now let’s extract just the logic portion of the code above and implement it as a custom Hook.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="p">{</span> <span class="nx">useState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">useCounter</span> <span class="o">=</span> <span class="nx">initialCount</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">setCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">);</span>
<span class="kr">const</span> <span class="nx">deltaCount</span> <span class="o">=</span> <span class="nx">delta</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">count</span> <span class="o">=></span> <span class="nx">count</span> <span class="o">+</span> <span class="nx">delta</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">count</span><span class="p">,</span>
<span class="na">incCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">deltaCount</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
<span class="na">decCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">deltaCount</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="p">{</span> <span class="nx">useCounter</span> <span class="p">};</span>
</code></pre>
</div>
<p>Now that’s impressive! Notice how the same logic can implemented with so few lines of code. Because
it’s a custom Hook, it’s just a function and not a component. Remember, Hooks don’t render
anything—they are strictly concerned with the data. The component that uses the Hook will handle all
aspects of rendering.</p>
<p>But what if we wanted to export both a <code class="highlighter-rouge">Counter</code> component and <code class="highlighter-rouge">useCounter</code>? We wouldn’t want the
two pieces of code to sit side-by-side. That would mean duplicating code in both implementations,
which would be a maintenance nightmare.</p>
<p>Instead, we can have our <code class="highlighter-rouge">Counter</code> component call the <code class="highlighter-rouge">useCounter</code> Hook, then pass the data to the
render prop, like this.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">const</span> <span class="nx">Counter</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">initialCount</span><span class="p">,</span> <span class="nx">children</span><span class="p">,</span> <span class="nx">render</span> <span class="o">=</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=></span>
<span class="nx">renderProps</span><span class="p">(</span><span class="nx">render</span><span class="p">,</span> <span class="nx">useCounter</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">));</span>
</code></pre>
</div>
<p>That’s very little overhead with no code duplication. It’s almost <em>too</em> easy.</p>
<p>The entire implementation of our <code class="highlighter-rouge">awesome-counter</code> that supports the <code class="highlighter-rouge">useCounter</code> custom Hook and
<code class="highlighter-rouge">Counter</code> component is as follows.</p>
<div class="language-js highlighter-rouge"><pre class="highlight"><code><span class="kr">import</span> <span class="p">{</span> <span class="nx">useState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">renderProps</span> <span class="nx">from</span> <span class="s1">'render-props'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">useCounter</span> <span class="o">=</span> <span class="nx">initialCount</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">count</span><span class="p">,</span> <span class="nx">setCount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">);</span>
<span class="kr">const</span> <span class="nx">deltaCount</span> <span class="o">=</span> <span class="nx">delta</span> <span class="o">=></span> <span class="nx">setCount</span><span class="p">(</span><span class="nx">count</span> <span class="o">=></span> <span class="nx">count</span> <span class="o">+</span> <span class="nx">delta</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">count</span><span class="p">,</span>
<span class="na">incCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">deltaCount</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
<span class="na">decCount</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="nx">deltaCount</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span>
<span class="p">};</span>
<span class="p">};</span>
<span class="kr">const</span> <span class="nx">Counter</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">initialCount</span><span class="p">,</span> <span class="nx">children</span><span class="p">,</span> <span class="nx">render</span> <span class="o">=</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=></span>
<span class="nx">renderProps</span><span class="p">(</span><span class="nx">render</span><span class="p">,</span> <span class="nx">useCounter</span><span class="p">(</span><span class="nx">initialCount</span><span class="p">));</span>
<span class="nx">Counter</span><span class="p">.</span><span class="nx">defaultProps</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">initialCount</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="k">default</span> <span class="nx">Counter</span><span class="p">;</span>
<span class="kr">export</span> <span class="p">{</span> <span class="nx">useCounter</span> <span class="p">};</span>
</code></pre>
</div>
<h2 id="the-tldr-of-it-all">The TL;DR of it all</h2>
<p>To convert your existing render props component package into one that supports both a custom Hook
and a component with render props, you:</p>
<ol>
<li>Convert your existing component’s logic to a custom Hook.</li>
<li>Export the custom Hook as a named export, prefixed with <code class="highlighter-rouge">use</code>.</li>
<li>Create a function component that uses the custom Hook and calls a render prop.</li>
<li>Export the component as <code class="highlighter-rouge">default</code>.</li>
</ol>
<p>So just like the mythical Hydra creature, our <code class="highlighter-rouge">awesome-counter</code> package is multi-headed and can
support our new Hook savvy users, as well as our current customer base that uses render props.</p>Donavon West