<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ryan Oglesby]]></title><description><![CDATA[Ryan Oglesby]]></description><link>http://ryanogles.by</link><generator>RSS for Node</generator><lastBuildDate>Thu, 06 Jan 2022 02:41:38 GMT</lastBuildDate><item><title><![CDATA[The Life and Death of a Pipeline Master]]></title><description><![CDATA[Originally posted in late 2015 or early 2016 as an internal blog post. It tells the story of
introducing and later abandoning a strategy for…]]></description><link>http://ryanogles.by/the-life-and-death-of-a-pipeline-master/</link><guid isPermaLink="false">http://ryanogles.by/the-life-and-death-of-a-pipeline-master/</guid><pubDate>Mon, 12 Nov 2018 00:17:42 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Originally posted in late 2015 or early 2016 as an internal blog post. It tells the story of
introducing and later abandoning a strategy for improving build pipeline culture. The setting is a
100+ person program, distributed between India and USA, maybe 10 teams, dozens of services and apps,
doing trunk-based development on a Java monorepo.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Beginnings&lt;/h2&gt;
&lt;p&gt;The time was July, 2015. It was a different time then. A wild west of sorts. We had a build
pipeline, but it was horribly untrustworthy. Our user journey tests failed often, both because of
broken functionality and because of our own deficiencies with asynchronous testing. The underlying
infrastructure was extremely unstable. Dropped database connections happened multiple times a day.&lt;/p&gt;
&lt;p&gt;These problems contributed to a growing cultural disease of inattention to the information coming
out of our build pipeline. Developers often committed on a red build, whether it was because they
did not trust it, because they felt like they could not fix it anyway, or because they assumed that
someone else must be working on it. Gradually, the team was developing bad habits.&lt;/p&gt;
&lt;p&gt;So, we felt that establishing a rotating role would give us more organization and discipline around
our build pipeline hygiene. The role would be the go-to person for build hygiene issues. The
Pipeline Masters were responsible for ensuring that a broken build was fixed in a timely manner,
though they were not necessarily responsible for doing the actual work to fix it. Their core value
was as an organizer, communicator, and enforcer. They would help identify trends of common problems
so that the teams could prioritize the most important. And their power even extended as far as being
able to revert any check ins when they were committed on top of an already red build.&lt;/p&gt;
&lt;h2&gt;Deterioration&lt;/h2&gt;
&lt;p&gt;What started out with good intentions began to devolve within a few rotations. One of the first
things we noticed was inconsistent hand-offs from one Pipeline Master to the next, resulting in a
loss of context and continuity. The tracking of persistent problem areas and common fixes died off
soon.&lt;/p&gt;
&lt;p&gt;Instead of a more ideal scenario of shared responsibility for the build pipeline, a culture began to
take shape around reliance on the Pipeline Masters to enforce hygiene. Because the Pipeline Masters
would send out an email titled “Build Broken - Don’t Commit,” we got into the practice of relying on
that to tell us if the build is healthy instead of using radiators or other notification tooling.
Not to mention, that produced a lot of extra noise in our already busy email inboxes!&lt;/p&gt;
&lt;h2&gt;All Things Come to an End&lt;/h2&gt;
&lt;p&gt;Over time, people began to ask why we needed the Pipeline Masters more and more. Shouldn’t proper
build etiquette be a contract shared amongst everyone on the project? Eventually, other duties even
started to creep into the Pipeline Master role. “They are already in charge of the build, so they
can just do this other kind-of-pipeline-related thing too.”&lt;/p&gt;
&lt;p&gt;What started as a way to reset build pipeline behavior had reached a point where it was no longer
realizing the advertised benefits, and even becoming detrimental to the account culture. The role
was also being replaced by better alternatives. We turned on build radiators. People started being
more disciplined about using &lt;a href=&quot;https://www.gocd.org/&quot;&gt;GoCD&lt;/a&gt; comments when the build was broken. The
underlying infrastructure became a bit more stable. Our tests got more reliable. We even built a
script that checked that status of all gating builds, which anyone could run locally before pushing.&lt;/p&gt;
&lt;p&gt;Though our build pipeline etiquette is not perfect, we are exhibiting much more collective
ownership. We have published a wiki entry with the expectations of all developers that outlines the
expected contract: following the
“&lt;a href=&quot;http://codebetter.com/jeremymiller/2005/07/25/using-continuous-integration-better-do-the-check-in-dance/&quot;&gt;Check In Dance&lt;/a&gt;,”
placing comments in GoCD for communication, assuming ownership especially after checking in code,
and ensuring the build is not red at the end of the day.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;In retrospect, it is hard to say whether we would have ended up at the same place now if we had
never implemented the Pipeline Masters. From time to time, suggestions get raised of other ways of
“forcing” proper build etiquette, such as a pre-commit script that will not let you push if builds
are green. I believe that these types of ideas are anti-patterns, and instead we should be focusing
on the culture of the teams. It’s a people issue, not a technology issue.&lt;/p&gt;
&lt;p&gt;Green builds for all!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Software Development is a Team Sport]]></title><description><![CDATA[What does it mean to be a member of a “software development team?” Is the team a single collective,
or a collection of individuals? When…]]></description><link>http://ryanogles.by/software-development-is-a-team-sport/</link><guid isPermaLink="false">http://ryanogles.by/software-development-is-a-team-sport/</guid><pubDate>Sat, 21 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What does it mean to be a member of a “software development team?” Is the team a single collective,
or a collection of individuals?&lt;/p&gt;
&lt;p&gt;When team members act like individuals who happen to be working on the same codebase at the same
time, it leads to tensions that lower the team’s overall productivity and lessen the average
individual’s fulfillment. A team of software developers is most effective when they value the team
over the individual.&lt;/p&gt;
&lt;p&gt;Everyone has preferences for the way they like to work and write code. That’s human. But, putting
those preferences over the needs of the team is selfish and unprofessional.&lt;/p&gt;
&lt;h2&gt;Code style&lt;/h2&gt;
&lt;p&gt;Having your own code style on a software team doesn’t make sense. Code style isn’t about your
preference. You don’t format code so &lt;em&gt;you&lt;/em&gt; can write it, and you don’t format code so &lt;em&gt;you&lt;/em&gt; can read
it. You format code so &lt;em&gt;others&lt;/em&gt; can read it. You’ll write it once, and then it will be read a
thousand times by people who are not even on the team yet.&lt;/p&gt;
&lt;p&gt;Tools that apply formatting to code automatically, such as &lt;a href=&quot;https://prettier.io/&quot;&gt;prettier&lt;/a&gt; or
&lt;a href=&quot;https://golang.org/cmd/gofmt/&quot;&gt;gofmt&lt;/a&gt;, fit perfectly into the team sport mindset. Some people
complain, saying “I don’t like the style that prettier applies.” The point is that the style doesn’t
matter. What matters is that the code will be of the same style, and that you don’t have to think
about it anymore. A codebase that looks like it was written by a single entity is easier to read and
understand. And when you spend less time thinking and talking about code style, you can spend more
time focusing on architecture, performance, and the domain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A team values a unified code style over individual preference.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Trunk-Based development&lt;/h2&gt;
&lt;p&gt;Long-lived feature branches is a sign of a collection of individuals who call themselves a “team.”
The tendency to want to work on your own isolated branch for a long period of time signifies a
mindset of “this is my code over here, and that is your code over there.” Furthermore, when
developers of this mindset submit their code to merge into the mainline, they tend to think “I’m
done with that and now its someone else’s responsibility, time for me to work on something else”. It
becomes easy to lose sight of what others are doing and what else is going on in the codebase. It
can also lead to specialized knowledge silos, which further separates the team members and is a risk
to the success of the project.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://trunkbaseddevelopment.com/&quot;&gt;Trunk-Based Development&lt;/a&gt; supports the idea that there is one
codebase that every member of the team owns equally. There is no mine and yours. There is no
hand-off and change of responsibility. It is much easier to see what else is happening in the
codebase simultaneously. Large scale refactoring is safer and easier. Merge hell is less likely, as
long as integration with trunk is frequent. Having only one long-lived code branch provides an
anchor for the team to rally around.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A team values collective code ownership over individual pride.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Pair programming&lt;/h2&gt;
&lt;p&gt;Pairing has a lot of benefits: code review happens immediately, new team members can be brought on
board quickly, knowledge silos are less likely, and so on. Pairing is also taxing. Not everyone has
the mental and emotional energy to pair program day in and day out. Experienced developers often
don’t want to pair because they feel that they are more productive when working alone.&lt;/p&gt;
&lt;p&gt;The interesting part is that most of the reasons is support of pair programming relate to team
optimizations, while most of the reasons against it speak to the individual. While pair programming
is a positive thing for most teams, it is possible to over do it, to the detriment of the happiness
of the humans. So, rather than treating pair programming as an all or nothing dogma, the critical
concept is that the team is in a constant state of collaboration in one way or another.&lt;/p&gt;
&lt;p&gt;Teams that don’t prioritize the overall shared knowledge of the team perpetuate the rockstar coder
stereotype that is too prevalent in the industry. By not working in a culture of collaboration,
individuals are put on pedestals, seen as invaluable, and rewarded. This only hurts the team. What
happens to all their specialized knowledge when they are sick, or worse, they leave the team? How
long does it take new team members to ramp up when the most experienced dev is always working alone?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A team values shared knowledge over individual productivity.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Values over practices&lt;/h2&gt;
&lt;p&gt;The most productive and happy teams I’ve worked on have operated as a team, not as individuals.
Those teams built a set of values shared among the team members, and derived practices in support of
them.&lt;/p&gt;
&lt;p&gt;I like being on teams that value collaboration, feedback, openness, trust, purpose, and flexibility.
Those values tend to lead to practices such as Agile methodologies, Trunk-Based Development, pair
programming, code quality, and face-to-face communication, but those specific practices are less
important to me.&lt;/p&gt;
&lt;p&gt;What is more important is that the team operates as a team, optimizing for its effectiveness while
not sacrificing the humanity of the individuals.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Exposing CSS Hidden Complexities with React]]></title><description><![CDATA[When we create web applications we use style sheets to describe presentation, and we use JavaScript
to manage all the bits of state and…]]></description><link>http://ryanogles.by/exposing-css-hidden-complexities-with-react/</link><guid isPermaLink="false">http://ryanogles.by/exposing-css-hidden-complexities-with-react/</guid><pubDate>Sat, 18 Nov 2017 00:17:42 GMT</pubDate><content:encoded>&lt;p&gt;When we create web applications we use style sheets to describe presentation, and we use JavaScript
to manage all the bits of state and logic. Unfortunately, we often end up with style sheets full of
complexity, such as stateful pseudo-classes, style rule overrides through media queries, and
deceivingly complicated animations. But what if we could leverage the expressiveness of React to
take control of all of this?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Complexity is a concern better handled with JavaScript, not style sheets. If we push complexity
from style sheets into JavaScript, then it becomes more obvious and predictable, thus easier to
deal with.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This post is an exploration of this hypothesis applied to 3 common CSS features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pseudo-classes&lt;/li&gt;
&lt;li&gt;Media queries&lt;/li&gt;
&lt;li&gt;Animations&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;I’ve also created an accompanying
&lt;a href=&quot;https://github.com/ryanoglesby08/exposing-css-hidden-complexities&quot;&gt;Github repo&lt;/a&gt; with full, working
examples of all the snippets shown in this post.&lt;/em&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;While evaluating CSS-in-JS libraries for my current project recently, I did a
&lt;a href=&quot;https://github.com/ryanoglesby08/react-native-web-poc&quot;&gt;deep dive&lt;/a&gt; on
&lt;a href=&quot;https://github.com/necolas/react-native-web&quot;&gt;React Native for Web&lt;/a&gt;. The library’s philosophy and
direction really resonated with me, and like many CSS-in-JS implementations it has many benefits
over traditional CSS at scale. If you haven’t seen it yet check it out!&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/necolas/react-native-web/blob/master/docs/guides/style.md#faqs&quot;&gt;Style FAQs&lt;/a&gt;
in the documentation caught my eye:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Media Queries may not be most appropriate for component-based designs. React Native provides the
Dimensions API and onLayout props. If you do need Media Queries, using the matchMedia DOM API has
the benefit of allowing you to swap out entire components, not just styles.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Pseudo-classes like :hover and :focus can be implemented with events (e.g. onFocus).
Pseudo-elements are not supported; elements should be used instead.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Because React Native for Web relies on React Native implementations to be cross-platform compatible,
it eschews some CSS features in favor of JavaScript implementations. This makes a lot of sense even
if you are not trying to build a cross-platform app. So, I decided to explore this concept further,
without using React Native for Web.&lt;/p&gt;
&lt;h2&gt;A “simple” button&lt;/h2&gt;
&lt;p&gt;Here is the example I’ll be using, a “simple” button component and its accompanying style sheet.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Button.css */&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #2892d7&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; background-color 0.5s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;button:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #1d70a2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 767px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./Button.css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;em&gt;Full component:
&lt;a href=&quot;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/CssButton&quot;&gt;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/CssButton&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Goodbye pseudo-classes, hello setState&lt;/h2&gt;
&lt;p&gt;First up is the &lt;code class=&quot;language-text&quot;&gt;:hover&lt;/code&gt; pseudo-class. One of the key tenants of React and other UI libraries is
that they pull state out of the DOM and into your components so that it is easier to reason about.
CSS Pseudo-classes are a direct contradiction to this advantage. In order for the button to change
it’s background color, something must know whether or not the mouse is currently “hovering” over the
button. The DOM is doing that. The DOM is managing an implicit state of “mouse is over the button”
or “mouse is not over the button”. The component should be managing that state, not the DOM.&lt;/p&gt;
&lt;p&gt;So, I’ll refactor the Button component to use the &lt;code class=&quot;language-text&quot;&gt;onMouseEnter&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;onMouseLeave&lt;/code&gt; events and
React’s &lt;code class=&quot;language-text&quot;&gt;setState&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Button.css */&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token property&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; background-color 0.5s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 767px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Component &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./Button.css&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bgColors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#2892d7&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  hover&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#1d70a2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    hover&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function-variable function&quot;&gt;toggleHover&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; hover&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hover &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button
        onMouseEnter&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toggleHover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        onMouseLeave&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toggleHover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hover &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; bgColors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hover &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bgColors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;em&gt;Full component:
&lt;a href=&quot;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/HoverButton&quot;&gt;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/HoverButton&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;A more power media query&lt;/h2&gt;
&lt;p&gt;Media queries suffer from the same contradiction as pseudo-classes. There is an implicit state of
“the media query is matched” or “the media query is not matched” that should be managed by
JavaScript.&lt;/p&gt;
&lt;p&gt;While pure CSS media queries are powerful, they tend to result in overriding of previously defined
style values, which can often cause unwanted side effects and mistakes due to specificity errors. As
the React Native for Web docs point out, they also are constrained to adjusting styles only. They
can’t be used to swap out entire components.&lt;/p&gt;
&lt;p&gt;Next, I’ll move the media queries out of the style sheet, preferring the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;window.matchMedia&lt;/code&gt;&lt;/a&gt; DOM API
instead. &lt;a href=&quot;https://github.com/reacttraining/react-media&quot;&gt;react-media&lt;/a&gt; is a nice little package that
provides a component interface for &lt;code class=&quot;language-text&quot;&gt;window.matchMedia&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Button.css */&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; background-color 0.5s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.inline&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.fullWidth&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Component &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Media &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-media&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./Button.css&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// same as previous Button.js snippet&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Media query&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; maxWidth&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;767&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;matches &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
      matches &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Button className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;fullWidth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Button className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;inline&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Media&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;em&gt;Full component:
&lt;a href=&quot;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/ResponsiveButton&quot;&gt;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/ResponsiveButton&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Animations as components&lt;/h2&gt;
&lt;p&gt;The final thing to tackle here is the &lt;code class=&quot;language-text&quot;&gt;transition&lt;/code&gt;. For all but the most experienced CSS wizards out
there, CSS animations or transitions can be really challenging. Moreover, they require the
combination of multiple style rules working together.&lt;/p&gt;
&lt;p&gt;In this case, &lt;code class=&quot;language-text&quot;&gt;transition: background-color 0.5s&lt;/code&gt; describes a state change of the property
&lt;code class=&quot;language-text&quot;&gt;background-color&lt;/code&gt;. When the &lt;code class=&quot;language-text&quot;&gt;background-color&lt;/code&gt; property of the button changes to another value,
either through a class being added or removed, or a style property being edited, the background will
shift from its previous value to its new value over a timespan of 0.5 seconds. It’s pretty complex,
and this is a very simple transition.&lt;/p&gt;
&lt;p&gt;Finally, I’ll bring the transition into the component with the
&lt;a href=&quot;https://reactcommunity.org/react-transition-group/&quot;&gt;react-transition-group&lt;/a&gt; package, which lets you
describe a transition from one component state to another over time with a simple declarative API.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// BgColorShift.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Transition &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-transition-group&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;defaultStyle&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;startBgColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  transition&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`background-color &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;timeout&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ms`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; startBgColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;transitionStyles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; endBgColor &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    entering&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; endBgColor &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    entered&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; endBgColor &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; children&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;rest &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Transition &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;rest&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; styles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defaultStyle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transitionStyles&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;styles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Transition&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Component &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; BgColorShift &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./BgColorShift&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./Button.css&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bgColors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#2892d7&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  hover&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#1d70a2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... setState stuff&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; className&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; children &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;props

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;BgColorShift
        timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        start&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;bgColors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        end&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;bgColors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;bgColorStyles &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button
            onMouseEnter&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toggleHover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            onMouseLeave&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toggleHover&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;bgColorStyles&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;BgColorShift&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// export default with the Media query component&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;em&gt;Full component:
&lt;a href=&quot;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/AnimatedButton&quot;&gt;https://github.com/ryanoglesby08/exposing-css-hidden-complexities/tree/master/src/components/AnimatedButton&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;I can write tests for this stuff now!&lt;/h2&gt;
&lt;p&gt;One of the big wins as I moved complexity into JavaScript was the increased level of testability.
There weren’t any tests that really made sense when all the UI behavior was implemented in a style
sheet. Writing tests for these things takes some of the burden off of manual visual checks, creates
documentation of the visual language, and helps prevent future regressions.&lt;/p&gt;
&lt;p&gt;Here are some of the tests:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Button.spec.js&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;changes background color on hover&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Press me&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;simulate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mouseEnter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveStyle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;backgroundColor&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#1d70a2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;simulate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;mouseLeave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveStyle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;backgroundColor&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#2892d7&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;is full width on small viewports&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Setup mock for `window.matchMedia` because test is running in jsdom&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; matchMedia &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  matchMedia&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockImplementation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    matches&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    addListener&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    removeListener&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchMedia &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; matchMedia

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Press me&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;button&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toHaveClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fullWidth&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;My insights&lt;/h2&gt;
&lt;p&gt;Maybe the most obvious “downside” here is that the total amount of code has increased, by a lot.
I’ve written less CSS, but much more JavaScript, and I’ve added 2 third-party libraries… just to
make a button.&lt;/p&gt;
&lt;p&gt;Let’s be clear here, my stated goal was not to create the most clever, most terse button. It was to
expose complexities hidden in CSS so that I could identify complexity, reason about it more easily,
control it, and test it. React actually has similar goals. React has never said that it’s goal is to
produce solutions with minimal lines of code. Rather, it aims for declarative components,
predictability, and JavaScript-controlled logic (&lt;a href=&quot;https://reactjs.org/&quot;&gt;https://reactjs.org/&lt;/a&gt;). The most clever solution
is often the least understandable.&lt;/p&gt;
&lt;center&gt;
	&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;This is what good real world React code often looks like. Nothing wrong with it being verbose and explicit. Don’t mistake terse for clean! &lt;a href=&quot;https://t.co/qjB685FnuJ&quot;&gt;https://t.co/qjB685FnuJ&lt;/a&gt;&lt;/p&gt;&amp;mdash; Dan Abramov (@dan_abramov) &lt;a href=&quot;https://twitter.com/dan_abramov/status/931333632572252160?ref_src=twsrc%5Etfw&quot;&gt;November 17, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;/center&gt;
&lt;h3&gt;Pros and cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you regularly use your browser’s dev tools to debug/play with the styles of your components,
the JavaScript approach changes that a bit. For example, most dev tools let you trigger a
pseudo-class such as &lt;code class=&quot;language-text&quot;&gt;:hover&lt;/code&gt;. That will no longer have a visible effect. Instead, use the
&lt;a href=&quot;https://github.com/facebook/react-devtools&quot;&gt;React dev tools&lt;/a&gt; to programmatically interact with
your components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-61e7c.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 57.41239892183289%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABm0lEQVQoz5WSW27UQBBFvRLYCmwJiWWwhWwD/uGH/CChTEIensxM/Ohuv8bjR7vt2IeyM0FIRChj6bqqXN23blXZg4mbpOXbpuL8oea74Kv4N4llzo3TxHQCPLnFxy8hbz6teH92x7uzW96K/+FzMKeeCHn94zGNbNKKlWq4Nu2i9lI3hGW3KJxOVTiOI2PvXqx2KtlCOL/6fsD1PV3/SDdM2H5kGE9p9K+WrbUkJhEYkvyALhrirKasLcMgRZyj6zrc0fZS+Nl/xszxdKbDi6IIkxhipVCCKAxIJQ6CgCAM0VoJNIl8UyqWfEgqsT6ez7IMI2KUydBJgTeri2O1KNxt7jFKs88LlFyMpViaFpRlRVGUFPsDuZD0eY5tW+q6Xua2zPsIL91Ju7eGbLNGBz5R5BOGd6L6gao6kKQN5cGx3zsK2Xy83WHLEtt1/yyOeSk60Kx/+PjnV2wvVmx//cS/v8JfX7IWG6gtuYnJdCg2wr1E9CcWhc71mLXBXMfsQ8MgQx+GgUfbMnRWluBwtsG1NV1TLbn//VK/ARHPTCu9chJqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Using the React Dev Tools&quot;
        title=&quot;&quot;
        src=&quot;/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-fb8a0.png&quot;
        srcset=&quot;/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-1a291.png 148w,
/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-2bc4a.png 295w,
/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-fb8a0.png 590w,
/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-526de.png 885w,
/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-fa2eb.png 1180w,
/static/react-dev-tools-7bfc801bba635d0d25dc86d77acf53bf-61e7c.png 1484w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I get really nervous when I see CSS or Sass that has a lot of nesting and overriding of style
rules. I like how the final CSS file I ended up with was flat. All style rules are static, there
is no nesting, and nothing is overridden by another class. Ahhhhh, peace.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I’m pretty excited about encapsulating common visual concerns into reusable components with a
single responsibility. In this exploration I identified a reusable media query component and an
animation component that could be extracted. In another project I’ve started extracting layout
components such as &lt;code class=&quot;language-text&quot;&gt;Box&lt;/code&gt; to control spacing, and &lt;code class=&quot;language-text&quot;&gt;Flexbox&lt;/code&gt; to control 1-dimensional layout. Check
out these libraries for more: &lt;a href=&quot;https://sapegin.github.io/react-spaceman/&quot;&gt;https://sapegin.github.io/react-spaceman/&lt;/a&gt; and
&lt;a href=&quot;https://github.com/jxnblk/reflexbox&quot;&gt;https://github.com/jxnblk/reflexbox&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, I was not able to write a test for the transition that I was completely satisfied with.
Transitions and animations are inherently time based, which does not play nicely with unit
testing. The best I could do was take before and after snapshots and then rely on manual visual
checks to make sure the transition looked proper while it was running. But, with a reusable
&lt;code class=&quot;language-text&quot;&gt;BgColorShift&lt;/code&gt; component now at my disposal, I can now trust it’s behavior, making future
transitions easier to implement.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[The State of CSS]]></title><description><![CDATA[It’s no secret that we are currently experiencing a Cambrian explosion of innovation by the
JavaScript community. But what you may not be…]]></description><link>http://ryanogles.by/the-state-of-css/</link><guid isPermaLink="false">http://ryanogles.by/the-state-of-css/</guid><pubDate>Thu, 25 May 2017 16:34:35 GMT</pubDate><content:encoded>&lt;p&gt;It’s no secret that we are currently experiencing a Cambrian explosion of innovation by the
JavaScript community. But what you may not be aware of are the equally evolutionary innovations
under development by the CSS community.&lt;/p&gt;
&lt;p&gt;CSS has quietly been improving by leaps and bounds lately. So much so, that you may not even
recognize it much anymore. While you weren’t looking, the CSS community has developed real solutions
to many of the oddities, hacks, and deficiencies that made CSS the black sheep of the front end
family in the past.&lt;/p&gt;
&lt;p&gt;In this post I’ll reveal 5 old-fashioned CSS things that you don’t need to do anymore, and what you
should do instead.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You don’t need a naming convention.&lt;/li&gt;
&lt;li&gt;You don’t need float.&lt;/li&gt;
&lt;li&gt;You don’t need a grid framework.&lt;/li&gt;
&lt;li&gt;You don’t need a preprocessor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You don’t need CSS.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- more --&gt;
&lt;h2&gt;You don’t need naming conventions.&lt;/h2&gt;
&lt;p&gt;And we begin with the number one problem with CSS, especially at scale: everything is global.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/global-css-8ec23da8da2902dc9c22b4f033972e16-5d9c9.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 75.07692307692308%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABcSAAAXEgFnn9JSAAABsklEQVQ4y61U226CQBBF8IoBrApyB+PtwRugqMSnNj74/z90ujMKTZvUGtOHydndmT1zZmZBkiQJ/2yPA6IoxHq1QhiGMHT9OcJarYZ6vQ5FUdgajQYb+eI4QpamuFwusEcWyniykuTHXkKz2cR4PBYqAriuhyAgdBEKdaZlvlYyKQpEWbP5nMsjnE6nnKyMUVUVrueyfzKZsJGQ+WLBseSvCNvtNmzbhi/UeZ7Ha1mWv2VvtVoYjWwmMgyDk9EZ3SW8x39l932PM8ZxLIYRQRdD0DStIqQLmqYLUqvq8a8lq90ukxAhYeD7jI7jvNbDsmQayCOSnxP+lbDT6YiSfW5uFEaYzWaC3H/tYdMb7Pf76PV6GAwGvH57u+113UC3q3I/y56S0ZoGU57T+60IPc/H6VRgt9shyzJstwnSNMNms0GeH5AkWxyOR+z3+7t/y5gfcj6je8Ph8IuQNpZlwTRN7uMNHQzu56SoL5SXPssi/6iKp4+A1FaEjvg6KMtyuRRKj0JVLhTssF6vcT6f8f7xgev1iqIohPKUFZaYJAlOxYkFPPVzoN6QClIqy8qfQ/kEDchc4+UNd2sAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Problems with CSS at scale&quot;
        title=&quot;&quot;
        src=&quot;/static/global-css-8ec23da8da2902dc9c22b4f033972e16-fb8a0.png&quot;
        srcset=&quot;/static/global-css-8ec23da8da2902dc9c22b4f033972e16-1a291.png 148w,
/static/global-css-8ec23da8da2902dc9c22b4f033972e16-2bc4a.png 295w,
/static/global-css-8ec23da8da2902dc9c22b4f033972e16-fb8a0.png 590w,
/static/global-css-8ec23da8da2902dc9c22b4f033972e16-5d9c9.png 650w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
     &lt;small&gt;Source:
&lt;a href=&quot;https://speakerdeck.com/vjeux/react-css-in-js&quot;&gt;https://speakerdeck.com/vjeux/react-css-in-js&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Because all selectors exist in the same global namespace, over time it becomes very likely that
you’ll run into unexpected side effects such as selectors targeting elements that you didn’t intend,
or selectors being overridden by other selectors. So, we have side-stepped these issues with
methodologies (&lt;a href=&quot;http://oocss.org/&quot;&gt;OOCSS&lt;/a&gt;, &lt;a href=&quot;https://smacss.com/&quot;&gt;SMACSS&lt;/a&gt;, or the more popular
&lt;a href=&quot;http://getbem.com/&quot;&gt;BEM&lt;/a&gt;) that define naming conventions to help us avoid class name collisions.&lt;/p&gt;
&lt;p&gt;While we can’t discount the importance of these methodologies, they are merely a workaround. They
don’t actually solve the problems. We needed something more. And then
&lt;a href=&quot;https://medium.com/seek-blog/the-end-of-global-css-90d2a4a06284&quot;&gt;this&lt;/a&gt; happened.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-46413.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 67.37309019221291%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC4klEQVQ4y5WPz28iZRjH51/x7NHozbpZV1oKtSyFwszA/AKGAWZgOgOUeFo1mjT+AR42MXpooWjdrGnV9eRp9eLJxD+gFy+mSyuBFqZ8fGGz2qtP8sn3+ZXv+z7S6OIvfvvjT37+5XcuL0eMpxHj8ZjpdMoyFovFv/oq/69+mUfRLZPpnJtZhDSZTBhPrnkxumQ2m4nmnOvr65XhfD5b9Zb1anZzs8qXzOfz1c6yH0UR09XOHGk5iKI5i9tbzs/PGY1ecHV1Kfibq/F0ZXKXu4ZLs6W+IhJI3Innz3/l4mLErThFXEG04H+HdHJyzOnTIaffDfnx7Jifvh/y7GzID6fHnD0drHgm8tMnfb4ZDBgc9fn88SGPvzjkyUmfr4d9vvzqkP7REd+eDJDeXIuT2EpQkLcoG0m8SgK3vEndjOMYcWxtA0ffQM/FSMTWeeOt+7z2+j3W7r1LfidGKhnjnbUHbG2us5uOI729KZPKqFi6xs6uQsUs0KwX6LRUur6y0iV7dZVcVubBeoZYPIuS36Vhy9imTMWQcW0Vt1pASjxUSO2opHdV7icV4ilRZ1WcSpHQK9LxhbmvErgqJU3BLCjkMjK6KmMZCl6twJ6n4Xs6oW8gFQs6iqqT2tVIZopspIskshpbGY2CZojfmoRNbWUeeAZ+w8K2dDbFw8m0KmqDoGXSCSzagYmk6GXyxTLbcom0WiIl9P2cRTxjsp0voWolanaZhmOxH1bohQ6WWSL+UMexS/iumItZU+heq4y0rdXZLtZ4T3aEOiilOla1Qc5wSBWqyKZDXq+ynq2gGjYtr4rjOMKkJk6sUTQqyFoFv1Wn220gqfWAvO2TsppsFOskBUrZpeZ6OA2Xct1FFw+oFZes6WI6Lq7n0RB4zSZ2w6PX82l3fTrdFlK53aMUvqTz0QH7Hx8QPDqgJ/SDTz6j/ehTwg8PMJsd3KBNsN/BckOMRkDQbdPpiX4YUtsLxazNPzgry2FvhvLJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;A screenshot of The End of Global CSS article on Medium&quot;
        title=&quot;&quot;
        src=&quot;/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-fb8a0.png&quot;
        srcset=&quot;/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-1a291.png 148w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-2bc4a.png 295w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-fb8a0.png 590w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-526de.png 885w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-fa2eb.png 1180w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-08f6a.png 1770w,
/static/end-of-global-css-d523ceb2e7229ffd640053a7d6be5f96-46413.png 2029w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
     &lt;small&gt;Source:
&lt;a href=&quot;https://medium.com/seek-blog/the-end-of-global-css-90d2a4a06284&quot;&gt;https://medium.com/seek-blog/the-end-of-global-css-90d2a4a06284&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/markdalgleish&quot;&gt;Mark Dalgleish&lt;/a&gt; and others have since pioneered the concept of
&lt;strong&gt;locally scoped CSS&lt;/strong&gt;, which led to the development of
&lt;a href=&quot;https://github.com/css-modules/css-modules&quot;&gt;CSS Modules&lt;/a&gt;, and which has now been incorporated into
modern tooling, most notably webpack’s
&lt;a href=&quot;https://github.com/webpack-contrib/css-loader#modules&quot;&gt;css-loader&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// webpack.config.js&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  test&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;/\.css$/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  use&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      loader&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;css-loader&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      options&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        modules&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        localIdentName&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;[path][name]__[local]--[hash:base64:5]&apos;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This is huge. When using CSS Modules, name your classes however you like. &lt;strong&gt;At build time, all local
selectors are replaced by unique identifiers, completely removing the need for a global naming
convention.&lt;/strong&gt; Check out the docs above for CSS Modules for a deeper dive.&lt;/p&gt;
&lt;p&gt;While this technology was born from component-oriented front-end development (think
&lt;a href=&quot;http://www.reactjs.com&quot;&gt;React&lt;/a&gt;), you can also get support for CSS Modules
&lt;a href=&quot;https://github.com/css-modules/postcss-modules&quot;&gt;everywhere&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;You don’t need float.&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://css-tricks.com/all-about-floats/&quot;&gt;Float&lt;/a&gt; has managed to become both the positioning
property of choice and the bane of many a developer’s existence by weaseling its way into everything
from &lt;a href=&quot;http://getbootstrap.com/css/#helper-classes-floats&quot;&gt;helper classes&lt;/a&gt; to
&lt;a href=&quot;https://unsemantic.com/demo-responsive&quot;&gt;entire grid systems&lt;/a&gt;. While occasionally using float to
push an element left or right doesn’t get you into too much trouble, pervasive use of it for full
page layouts leads to odd behavior that is a pain to figure out and fix, often requiring hacks.
Pretty soon you find yourself copying the admittedly elegant, yet unintuitive
&lt;a href=&quot;https://css-tricks.com/snippets/css/clear-fix/&quot;&gt;“clearfix”&lt;/a&gt; onto every element and hoping for the
best.&lt;/p&gt;
&lt;p&gt;Thankfully, CSS3 introduced a new layout module called flexible boxes, or
&lt;a href=&quot;https://www.w3schools.com/css/css3_flexbox.asp&quot;&gt;Flexbox&lt;/a&gt; for short. Flexbox is a mostly
1-dimensional layout system that ensures elements behave predictably on various screen sizes and
devices. It also solves the common, yet previously frustrating task of vertical and horizontal
centering. &lt;strong&gt;When you switch to Flexbox, you no longer have any use for float.&lt;/strong&gt;&lt;/p&gt;
&lt;p data-height=&quot;320&quot; data-theme-id=&quot;0&quot; data-slug-hash=&quot;GmbYjd&quot; data-default-tab=&quot;result&quot; data-user=&quot;ryanoglesby08&quot; data-embed-version=&quot;2&quot; data-pen-title=&quot;GmbYjd&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/ryanoglesby08/pen/GmbYjd/&quot;&gt;GmbYjd&lt;/a&gt; by Ryan Oglesby (&lt;a href=&quot;https://codepen.io/ryanoglesby08&quot;&gt;@ryanoglesby08&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While Flexbox is &lt;a href=&quot;http://caniuse.com/#feat=flexbox&quot;&gt;fully supported by all modern browsers&lt;/a&gt;, you
will run into issues on older ones. So, if you have to support IE &amp;#x3C; 10 you will likely still need to
fall back to floats, tables, or some other layout method.&lt;/p&gt;
&lt;p&gt;Some browsers also need vendor prefixes, so I recommend using
&lt;a href=&quot;https://github.com/postcss/autoprefixer&quot;&gt;Autoprefixer&lt;/a&gt; to get the most coverage.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;You don’t need a grid framework.&lt;/h2&gt;
&lt;p&gt;Everyone uses a grid. It’s a crucial part of every CSS codebase, letting you build complex full-page
layouts by aligning elements along rows and columns. While rolling your own simple grid using
traditional techniques is &lt;a href=&quot;https://css-tricks.com/dont-overthink-it-grids/&quot;&gt;fairly straightforward&lt;/a&gt;,
no one does it. Instead, we reach for one of the many grid frameworks, such as the original
&lt;a href=&quot;https://960.gs/&quot;&gt;960gs&lt;/a&gt; or the Sass-based &lt;a href=&quot;http://neat.bourbon.io/&quot;&gt;Bourbon Neat&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, as of March 2017, most browsers added support for the
&lt;a href=&quot;https://css-tricks.com/snippets/css/complete-guide-grid/&quot;&gt;CSS Grid Layout&lt;/a&gt;, a 2-dimensional layout
system built directly into CSS. Since most traditional grid frameworks still rely on float, CSS Grid
is an attractive alternative. CSS Grid makes it easy to define your own grid without the help of a
framework by providing an intuitive interface for defining the number and sizes of rows and columns,
the gutter spacing, alignment of elements within the grid, named areas, and more.&lt;/p&gt;
&lt;p data-height=&quot;253&quot; data-theme-id=&quot;0&quot; data-slug-hash=&quot;pwzNdB&quot; data-default-tab=&quot;css&quot; data-user=&quot;ryanoglesby08&quot; data-embed-version=&quot;2&quot; data-pen-title=&quot;pwzNdB&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;https://codepen.io/ryanoglesby08/pen/pwzNdB/&quot;&gt;pwzNdB&lt;/a&gt; by Ryan Oglesby (&lt;a href=&quot;https://codepen.io/ryanoglesby08&quot;&gt;@ryanoglesby08&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://caniuse.com/#feat=css-grid&quot;&gt;At the time of writing this article&lt;/a&gt;, CSS Grid is supported by
all modern browsers, with partial support on IE if you use vendor prefixes (use
&lt;a href=&quot;https://github.com/postcss/autoprefixer&quot;&gt;Autoprefixer&lt;/a&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;You don’t need a preprocessor.&lt;/h2&gt;
&lt;p&gt;Undeniably, CSS language extensions such as &lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; and
&lt;a href=&quot;http://lesscss.org/&quot;&gt;Less&lt;/a&gt; brought game-changing features to CSS, including data reuse with
variables, better organization with nesting, and property reuse with mixins. But, these languages
didn’t change anything about the core language of CSS; they added a layer of abstraction on top of
it. In the case of Sass, you also need an &lt;a href=&quot;http://sass-lang.com/libsass&quot;&gt;additional binary&lt;/a&gt; to
compile the Sass files into CSS. When using one of these preprocessors, you now have to learn CSS
&lt;em&gt;and&lt;/em&gt; the preprocessor specific syntax.&lt;/p&gt;
&lt;p&gt;But, while most developers were blissfully coupling to their preprocessors, CSS was quietly
progressing. Modern browsers now have native support for
&lt;a href=&quot;https://www.w3.org/TR/css-variables/&quot;&gt;CSS variables&lt;/a&gt; and
&lt;a href=&quot;https://www.w3.org/TR/css3-values/#calc&quot;&gt;calc()&lt;/a&gt;. Other features such as
&lt;a href=&quot;https://drafts.csswg.org/css-color/#modifying-colors&quot;&gt;color modifications&lt;/a&gt;, and
&lt;a href=&quot;http://tabatkins.github.io/specs/css-apply-rule/&quot;&gt;mixins&lt;/a&gt; are not far behind.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;--spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.5em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* declaring a variable */&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* declaring a mixin */&lt;/span&gt;
  &lt;span class=&quot;token selector&quot;&gt;--base-colors:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #fff&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;#fff &lt;span class=&quot;token function&quot;&gt;shade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+80%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* modifying a color */&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.some-class&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--spacing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;100% - &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--spacing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* dynamically calculating a value */&lt;/span&gt;
  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@apply&lt;/span&gt; --base-colors&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Fortunately for CSS, the JavaScript community has already had the problem of browsers not supporting
new features fast enough, which led to &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt;, giving JavaScript developers
everywhere access to “next generation JavaScript, today.” Similarly, &lt;a href=&quot;http://postcss.org/&quot;&gt;PostCSS&lt;/a&gt;
is a “tool for transforming CSS with JavaScript”, which gets its power from the extensive list of
community maintained &lt;a href=&quot;https://github.com/postcss/postcss/blob/master/docs/plugins.md&quot;&gt;plugins&lt;/a&gt;. CSS
developers can even “use tomorrow’s CSS syntax, today” with the &lt;a href=&quot;http://cssnext.io/&quot;&gt;cssnext&lt;/a&gt;
PostCSS plugin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writing plain CSS and transforming it with PostCSS plugins produces more future-proof CSS with
less cognitive and technical overhead than old preprocessors.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;You don’t need CSS.&lt;/h2&gt;
&lt;p&gt;Ok, so that’s not entirely true. While CSS remains the only document styling language that browsers
understand, &lt;strong&gt;you can style web applications without ever writing a single .css file&lt;/strong&gt;. With the
help of UI libraries such as React or Vue.js, modern web application architecture has embraced
loosely coupled, highly cohesive components that often co-locate HTML, CSS, and JavaScript in the
same file. Interestingly, this idea is in direct contradiction to previously held best practices
around separation of these concerns.
(&lt;a href=&quot;https://www.youtube.com/watch?v=x7cQ3mrcKaY&quot;&gt;This conference talk&lt;/a&gt;, called “Rethinking best
practices” gives a great explanation.)&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-a4141.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 60.57196436943273%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABcSAAAXEgFnn9JSAAACZUlEQVQoz12TS2gTURSGZ6XbQgl1ocb6QK0tXYjFnbhzoTvBhWi1hqJiES216caCCD6Qio1oatI8GkLA4COLLqyCIK5UXKRJTIxYsJaahpAmTeZxZ+783nsnk0QP/HPOzJz7nTn3npHA7PfyMlKpNLK5HPL5H/i5tIRsNotf7Dk30zSFl2UZ6UwGyeSiyP2ez+Mby8uxuFqtihzJTtxgDxS5DlWRQTQVcr0GTVWbQC5KKaqVCgqFAtbW1lAqlVAsFhmsAl3XLaBdnV8VYkDRjYanwtsge4FhtolanqU2C0uEAbjNLCxi06kn6Bryw3Hej46zz+C8GMJKqSbea4QIfyfxEdfm3mA89k5oLPoWN+PvoTU4km5Y+MiHDJyXfOgbDaP3egj7rgZxyB3FatkCKpom/I34C5zxB+AKRZjmMBQM40o0BtVuWadWEEgH0entxM7gLnQHurF1dht6IgewWlsFWE1ZVUSee2Eagy8nMZy4LeR6fQsj8/cZ0CooEYOIDQylgtjy1IG9gd3YM8ugvu3oD/daQNaNospiQXDejanYIDzxYaFHz13wvhoB0a0DlCjbG842ExHQoztAT/SDHu8DPbYf9OQAUPwD3gM/fW5J3xg+3TuNL1MXhD4/OIevnsswSANosL3Z4MCYF+jZDBzuAgYcwMEO4IgTKKzwjkEaLVdCd1F+OIr1xxNY90ygPD2OyswkTKK15tA6cgrT0JmMf8StfWw4WGNzSxRFiMcqm1l7/CR7aE0bjJbZcTuwzgDVWk2IsII1ds/VBKIRCP+fmkPPvNH4Wh7X2R/Fi9jFWl2a+AvO1Ub2ehUzhAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Separation of concerns with HTML, CSS, and JS&quot;
        title=&quot;&quot;
        src=&quot;/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-fb8a0.png&quot;
        srcset=&quot;/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-1a291.png 148w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-2bc4a.png 295w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-fb8a0.png 590w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-526de.png 885w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-fa2eb.png 1180w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-08f6a.png 1770w,
/static/separation-of-concerns-17290be36e6368e126f1ffc54da3e044-a4141.png 2133w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
     &lt;small&gt;Source:
&lt;a href=&quot;https://speakerdeck.com/didoo/let-there-be-peace-on-css&quot;&gt;https://speakerdeck.com/didoo/let-there-be-peace-on-css&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;From a CSS perspective, this rethinking has even been given a catchy name:
&lt;a href=&quot;https://speakerdeck.com/vjeux/react-css-in-js&quot;&gt;CSS-in-JS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At first, CSS-in-JS libraries used the HTML “style” attribute to attach styles onto elements, a
flawed approach because the “style” attribute can’t do everything CSS can do. Now, most libraries
generate real style sheets with the full power of CSS, eschewing use of the “style” attribute for
the most part.&lt;/p&gt;
&lt;p&gt;Writing CSS using JavaScript addresses most of the other points I’ve brought up in this article.
Most new libraries scope styles automatically, make reuse of classes easy and efficient, identify
and inline critical-path CSS for faster initial load times, and enable real modular sharing of
open-source CSS packages.
&lt;a href=&quot;https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660&quot;&gt;This must-read article&lt;/a&gt;
outlines the architectural benefits for CSS-in-JS and is the best I’ve read so far.&lt;/p&gt;
&lt;p&gt;As this space is new and exciting, there has been an
&lt;a href=&quot;https://github.com/MicheleBertoli/css-in-js&quot;&gt;explosion of libraries&lt;/a&gt; (this list is even slightly
old now). This is a good thing. It will take some time to settle down as the community discovers
best practices, such as avoidance of the “style” attribute, proper support for media queries, and
the ability to use proper CSS syntax instead of a JavaScript object.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://cssinjs.org/&quot;&gt;JSS&lt;/a&gt; is a very popular choice, with an active community and a stable
interface; but I’m especially excited about the direction of
&lt;a href=&quot;https://www.styled-components.com/&quot;&gt;styled-components&lt;/a&gt;, which cleverly attaches CSS to components
via
&lt;a href=&quot;https://www.styled-components.com/docs/advanced#tagged-template-literals&quot;&gt;tagged template literals&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/styled-components-937c594b557f9956693c6a9351af1466-cf391.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 45.9915611814346%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABq0lEQVQoz5WRS2/TQBRGvUcI2hKgediJ3fgxTmynpAT4BQghBKI0TaGCJYIiVNoQgsrfgkXZsEJIdMGfqKB5uFRAIME+TIwQSLSoXOnozuY7c++M0m5t0Gw+ZX2tzXqzzeMnG6w+anF/ZZWVB2vcvfeQVvsZ4U6XYbjHoBPybe8Tg/c9ui/e0Nt8S+f5awbbXSJAMQ0Xu+Cg6wZ5U+PktMrEVJbjk2nZMxw5mkIvlulsf4DPXxNp9EX27kfCl1vsvnpHuLnFcGeXcSnVyjlqfg2/WqY85+J4Ai3vJBQMQSZXpDJ7gV4YJoGYgyuOYxS/VKVke4jAwTtrIyoWM45FoWiR02xOp3W8oEav109CURQlwYTv0W/in1cpjnsGx/Uxbbm6CHC9gFLZxSgKKbT+Ev4KHlSK7QZyMoE3J3B8gVUSmI6NKmVq3v5/oSWnyqommvyYsSCn2smq43NeF6SzMwSz5/dfeR8UywmYzhhMnsgylcr9gUrqlMaxibR8Dv/wEzYat1lauEVdsrC4zI36MvX5Ja5fW+TylXkuXrpK4+Yd+v1+IhuORoz+wQ+8he8TgaNGaQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Styled Components example&quot;
        title=&quot;&quot;
        src=&quot;/static/styled-components-937c594b557f9956693c6a9351af1466-fb8a0.png&quot;
        srcset=&quot;/static/styled-components-937c594b557f9956693c6a9351af1466-1a291.png 148w,
/static/styled-components-937c594b557f9956693c6a9351af1466-2bc4a.png 295w,
/static/styled-components-937c594b557f9956693c6a9351af1466-fb8a0.png 590w,
/static/styled-components-937c594b557f9956693c6a9351af1466-526de.png 885w,
/static/styled-components-937c594b557f9956693c6a9351af1466-fa2eb.png 1180w,
/static/styled-components-937c594b557f9956693c6a9351af1466-08f6a.png 1770w,
/static/styled-components-937c594b557f9956693c6a9351af1466-cf391.png 1896w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
     &lt;small&gt;Source:
&lt;a href=&quot;https://www.styled-components.com&quot;&gt;https://www.styled-components.com&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;CSS is dead. Long Live CSS.&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You don’t need naming conventions because &lt;em&gt;locally-scoped styles by default are now baked-in to
libraries&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You don’t need float because &lt;em&gt;Flexbox is more powerful and less hacky&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You don’t need a grid framework because &lt;em&gt;there’s one built into CSS&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You don’t need a preprocessor because &lt;em&gt;CSS has more advanced features now&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You don’t need CSS because &lt;em&gt;writing styles in JavaScript enables more architectural and community
benefits&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m excited about the large-scale adoption of modern JavaScript techniques and UI libraries,
especially React. But, I’m frustrated at the same time because those same codebases continue using
dated, flawed CSS techniques and technologies instead of embracing modernity. It’s time we recognize
the importance of these new developments in the CSS community and find a way out of our old,
comfortable habits.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Conceptualizing How a Modern Single Page App is Served]]></title><description><![CDATA[I’ve noticed some confusion in how Single Page Applications are served among developers who are new
to these apps. This post is a short…]]></description><link>http://ryanogles.by/conceptualizing-how-a-modern-single-page-app-is-served/</link><guid isPermaLink="false">http://ryanogles.by/conceptualizing-how-a-modern-single-page-app-is-served/</guid><pubDate>Thu, 11 May 2017 13:30:08 GMT</pubDate><content:encoded>&lt;p&gt;I’ve noticed some confusion in how Single Page Applications are served among developers who are new
to these apps. This post is a short explanation of how a Single Page Application gets from the web
server to a user’s web browser.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;First, what is a Single Page Application?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A Single Page Application (SPA) is a web application or web site that fits on a single web page,
with the goal of providing a user experience similar to that of a desktop application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All necessary code – HTML, JavaScript, and CSS – is retrieved with one page load. The page does not
reload at any point, nor does control transfer to another page. As the user navigates around the
application, the URL shown in the browser can be updated to provide the perception and navigability
of separate logical pages in the application, but no more page loads occur unless the user forces
one by clicking the browser’s refresh button or by typing a new address into the URL bar and
pressing the &amp;#x3C;enter&gt; key.&lt;/p&gt;
&lt;h2&gt;What might this look like?&lt;/h2&gt;
&lt;p&gt;This is the only HTML file for the entire application, and the only file returned to a client who
requests the application. Both the &lt;code class=&quot;language-text&quot;&gt;app.css&lt;/code&gt; file and the &lt;code class=&quot;language-text&quot;&gt;app.js&lt;/code&gt; file contain all the necessary
CSS and JavaScript that any part of the app needs.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- index.html --&gt;&lt;/span&gt;

&lt;span class=&quot;token doctype&quot;&gt;&amp;lt;!DOCTYPE html&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;A single page app&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app_root&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;app.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;In this example, &lt;code class=&quot;language-text&quot;&gt;app.js&lt;/code&gt; could be a &lt;a href=&quot;https://facebook.github.io/react/&quot;&gt;React&lt;/a&gt; application that
produces rest of the DOM elements when it is evaluated.&lt;/p&gt;
&lt;h2&gt;What about interaction with the web server?&lt;/h2&gt;
&lt;p&gt;The sequence diagram below shows how and when the front end SPA interacts with the back end web
server.&lt;/p&gt;
&lt;p&gt;The UI server below has one and only one job: deliver the single page and all assets that the
application needs when a browser requests them. Therefore, the UI server must be configured as
follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serve static assets. Handle any request for a static file, such as a JavaScript file, a CSS file,
an image, or a font file, by loading it from the filesystem and returning it.&lt;/li&gt;
&lt;li&gt;Match all other routes. The UI server uses a “match all” strategy so that any received request
that does not match a static asset will be handled by returning the single page of the
application, usually called index.html. This is necessary because the user could force a page load
while on a specific URL within the application, as shown in the diagram below.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-445ad.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 160.1815823605707%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAIAAACdAM/hAAAACXBIWXMAAAsSAAALEgHS3X78AAAEMElEQVQ4y5VV2W7bRhTVp7cPfS5QpOhL/dAAie3EFpAYTeG0cOwkduRNlkXRsnaKq7gOxdmHW4einaa14qAXxAUlzJm599xzho1wOGYQlWVZrKJ8EPWffTN8pZhv+s6L0/6eor9SrdbUa0TmIuXi80KZWBLqg6PQHpVFGZpd+S4IMvTZaefP4/bRh8vjS+Ww1fmro1w2QBCCMAQRiIIwBqDIC06QO7uFIJAbJYHjGaMiFQPd3js9+/28vddW/rhovz69OLkZNHLKOSKcUI6JIDRjvMwKFkEUJ3maZoSnhMtduhZ43nN2bpydsS/zc9U50sNGzkWR51/2KJ+U0TwV1XteeLplzGYfbybbit7s6bsDp6nqW8r8veY9BFeRkhzDAkIOggA5QZllXSvc6upN1ViBjS1F/ze4qDKOr6z5z/PBE0//CQbvGBIpr8ruWdFj4GIFRqCnjTbG6q+33Se2tp9z2cIKbEfbivH1k7+Y6tKJYh8TlEo6geVSBFtD/enZoKmaj4HrUSMvFqygnAnGiBeVQnQM/3lntvbk4p7nUhDf0TZnvY1R+4lrdAXNspWE1pedIgIqecRRGEIIQbiI3K4zbQHvmlNQZGUNVtYSJiDG8RInsH4oInJphkXdfJFmmUi/CmYJcuaGbZi2briW41o2imOxhPXkiuwebEcSsKbsSpsyGM/SVHAu13OEI8+Xagd+ENiLZRiej4wXl9Nmz9gdOjLfE5ZmdYV5LrW8iixlCFOIKCEykwTljLXH1rOz4W598o251TMqsJxTDZYYjDGlEkIwwpI8TAiCSIbg7HxiPW2Pd29Wc+5bW6r5fiYJw2QZRnEE4jBaAkl6xAnLMb0j7L7nu1H1/tMzZZUZZZadE8oIkatxAALHjfyAxZAmSJJ3bfjbiv6ISP5RWS54zXZlybm5suR0zckP5FklATkCHEIm2SY+uBvVN12VhCfT2+8m6g/m9Huw2GP4zpLK45asLYGXE2v+eqru9K9+M6eHOUslKTX425ast4DukmE5+LLgAtgeRej/WNINKSQIY8k/9qKC847uba6xpJDar3SSr7bgeKGPNibdX4btH12jk4kiE7UlwXbvAdvSVZJSeWNLJSfLBISeocmLvr0EmuBQilfex7Kea93futaq2/PWlvkejAjDhDNWP4wyWThPcOSGkReEzsK37CQIjq+Hm+fDZme2q+rNi/F2Z7YCJ8iezs2pZky1hW7a2tyzbBHBunkpkjyt2una8bOu/VJ1Xo78Fz1Hvh9qYQO4HsUkFUKaUWbZP4xcc3Acu1qZl5HVt4atlJL5XDtpH364+Hh02Tq9/iA/Wldqt+Hc9BlCX+orpciz1Ni35K8kkOUoGaOjufH26tN++/zNxcVB93z/qvWp12vQIM4+fyXXRV3+2F3uD/13k+Bg4h9Mgrcj/8oEfwP97Mi9N2hP2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Single-page app sequence diagram&quot;
        title=&quot;&quot;
        src=&quot;/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-fb8a0.png&quot;
        srcset=&quot;/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-1a291.png 148w,
/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-2bc4a.png 295w,
/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-fb8a0.png 590w,
/static/spa-sequence-diagram-78425283014cbef910dd508eadc9bb33-445ad.png 771w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;It’s important to remember that while the SPA is primarily written in JavaScript, there is no
requirement that necessitates a JavaScript-based UI server. Any web server that is able to handle
the configurations described above will work fine, such as
&lt;a href=&quot;https://access.redhat.com/solutions/67298&quot;&gt;Apache&lt;/a&gt;,
&lt;a href=&quot;https://www.nginx.com/resources/admin-guide/serving-static-content/&quot;&gt;NGINX&lt;/a&gt;, or even
&lt;a href=&quot;https://keita.blog/2015/11/24/hosting-a-single-page-app-on-s3-with-proper-urls/&quot;&gt;Amazon S3&lt;/a&gt;!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[An Exploration of JavaScript Builders]]></title><description><![CDATA[Builders seems to be a popular topic for me, as I’ve
 blogged about the builder pattern before .
This time, however, I look at builders…]]></description><link>http://ryanogles.by/an-exploration-of-javascript-builders/</link><guid isPermaLink="false">http://ryanogles.by/an-exploration-of-javascript-builders/</guid><pubDate>Fri, 03 Mar 2017 09:40:44 GMT</pubDate><content:encoded>&lt;p&gt;Builders seems to be a popular topic for me, as I’ve
&lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-i&quot;&gt;blogged about the builder pattern before&lt;/a&gt;.
This time, however, I look at builders through a JavaScript lens. In this post I’ll explore three
techniques for modeling builders in JavaScript, specifically ES6, utilizing some of the interesting
features of the modern language.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;All the examples I show in this post show builders that are &lt;strong&gt;only&lt;/strong&gt; for testing purposes. While
the builder pattern can be used in production code, the builders shown below are not appropriate for
production code because they contain pre-canned default values. Leave these in your test suite.&lt;/em&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;The Classic&lt;/h2&gt;
&lt;p&gt;I start with a simple, recognizable builder that uses “withers” to build up the object’s state.
Returning &lt;code class=&quot;language-text&quot;&gt;this&lt;/code&gt; from each “wither” enables chaining. The &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt; method will return the final plain
JavaScript object.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A Product&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;category &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;withPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; price
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;withCategory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;category&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;category &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; category
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;category&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withCategory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;book&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Harry Potter&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      price: 9.99,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      category: &apos;book&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Simple. Familiar. But wordy. With only three fields our builder is already quite large, and needs a
lot of boilerplate. The size of the builder grows linearly with the number of fields.&lt;/p&gt;
&lt;p&gt;While this technique is fine, it takes a very Java-esque approach, ignoring other powerful
JavaScript features. Let’s investigate those.&lt;/p&gt;
&lt;h2&gt;Generate Builders with Metaprogramming&lt;/h2&gt;
&lt;p&gt;Let’s address some of the shortcomings of the previous example, namely the repetition of the
“withers.” Rather than manually typing out each “wither” method, let’s generate them automatically.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A metaprogrammed product&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;category &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Generate &quot;wither&quot; methods for each property&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; witherName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`with&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;witherName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Get an array of all non-function properties of this builder&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; keysNoWithers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Transform the array of keys into an object&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; keysNoWithers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;returnValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withCategory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;book&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Harry Potter&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      price: 9.99,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      category: &apos;book&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This pattern produces an equivalent result as the first example. In the constructor, we
automatically generate all the “wither” methods from the properties of the object. Then, in the
&lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt; method, we use the properties of the object again to produce the resulting object. Some of
the cool JavaScript features we use are
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys&quot;&gt;Object.keys&lt;/a&gt;,
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce&quot;&gt;reduce&lt;/a&gt;,
and the proposed &lt;a href=&quot;https://github.com/sebmarkbage/ecmascript-rest-spread&quot;&gt;object rest spread&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While at first this may seem overly complicated (for a single builder, yes, it is), the real power
is truly recognized when you have many builders. We can easily extract the generalized parts of this
into a common superclass, making it extremely easy to create new builders.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; witherName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`with&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;witherName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; keysNoWithers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;function&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; keysNoWithers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;returnValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A metaprogrammed product&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;category &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SandwichBuilder&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BaseBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;meat &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ham&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cheese &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;swiss&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withCategory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;book&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SandwichBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withMeat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Roast Beef&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withCheese&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Havarti&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Harry Potter&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      price: 9.99,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      category: &apos;book&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    }&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Roast Beef&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      cheese: &apos;Havarti&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;By adopting this standard structure built on top of
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes&quot;&gt;ES6 inheritance&lt;/a&gt;, we
benefit from the predictability of the common interface and from the simplicity in creating new
builders. Our builders are also still open for extension, as we can easily insert additional methods
to add custom functionality as needed.&lt;/p&gt;
&lt;p&gt;But, we are still following the verbose “wither” syntax. This approach is inherently object
oriented. While there is nothing wrong with OOP, JavaScript is flexible and adopts multiple
paradigms. What if we approach builders using a more functional programming technique?&lt;/p&gt;
&lt;h2&gt;Just Use Functions&lt;/h2&gt;
&lt;p&gt;Let’s get rid of the classes. Let’s get rid of the “withers”. Let’s model our builder as a function
instead.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildProduct&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A functional product&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;overrides &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;buildProduct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;book&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Harry Potter&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      price: 9.99,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      category: &apos;book&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;That’s it! Here, we rely heavily on the awesome object rest spread proposal to perform merging of
two objects.&lt;/p&gt;
&lt;p&gt;While elegant, the most obvious deficiency is that there is no control over the contents of the
&lt;code class=&quot;language-text&quot;&gt;overrides&lt;/code&gt; object, which could lead to mistakes. In the above example, if I were to do
&lt;code class=&quot;language-text&quot;&gt;buildProduct({nme: &amp;#39;Harry Potter&amp;#39;})&lt;/code&gt; I would end up with a product with the default name, &lt;em&gt;and&lt;/em&gt; an
additional property “nme.” This is not ideal and could be frustrating at the least. Let’s fix that.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; difference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildProduct&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A functional product&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Prevent extra keys from being introduced by the overrides&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; extraOverrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;extraOverrides&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`Invalid builder! &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;extraOverrides&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;overrides&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;buildProduct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;book&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    keyThatDoesNotExist&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;oops&apos;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt; Error: Invalid builder! keyThatDoesNotExist&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;By using the &lt;a href=&quot;https://lodash.com/docs#difference&quot;&gt;lodash library’s array diffing utility&lt;/a&gt;, we can
prevent this problem. And, as with other bits of reusable code, we could extract this into a
function used by many builders.&lt;/p&gt;
&lt;p&gt;In all of these examples the product object is a toy. With a larger, more complex object containing
multiple levels of nested objects, this functional technique could get out of control is not
properly modeled. While you could go for deep merging, I would shy away from that as it will hard to
reason about. Instead, I recommend composing many builders together.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; difference &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;preventExtraOverrides&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; extraOverrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;extraOverrides&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`Invalid builder! &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;extraOverrides&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildProductName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A product&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    description&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A product description&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;preventExtraOverrides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;overrides &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildProductPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    taxRate&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.08&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;preventExtraOverrides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;overrides &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;buildProduct&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;overrides &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildProductName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildProductPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    category&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;other&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;preventExtraOverrides&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; overrides&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;overrides &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;buildProduct&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildProductName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Harry Potter&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildProductPrice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; price&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9.99&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// =&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    name: {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      name: &apos;Harry Potter&apos;,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      description: &apos;A product description&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    },&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    price: {&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      price: 9.99,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      taxRate: 0.08&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    },&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//    category: &apos;other&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//  }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;By composing builders we can easily reason about our object because we have broken it down into
small, independent pieces. Each builder follows a similar pattern, but is self contained, which
allows for customization in specific situations when needed.&lt;/p&gt;
&lt;h2&gt;So which one is best?&lt;/h2&gt;
&lt;p&gt;Well, it depends. Yep, not what you wanted to hear right? Of course it’s never that easy. Your
unique situation may make some patterns more desirable than others. Are you on a team full of
ex-Java devs who are not used to JavaScript semantics yet? Maybe starting with the classic approach
and moving towards the metaprogramming technique eventually will suit you. Is your team ga-ga over
functional paradigms? Reach for the functional approach.&lt;/p&gt;
&lt;p&gt;Overall, remember that JavaScript is a multi-paradigm language, capable of flexing to suit many
needs. Enjoy!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[It's not magic, you just don't understand it yet]]></title><description><![CDATA[Dev 1 : “Wait, how did it do that?”  
 Dev 2 : “I have not clue, it’s Spring *  magic.”  
 Dev 1 : “Oh well, as long as it just works…]]></description><link>http://ryanogles.by/its-not-magic-you-just-dont-understand-it-yet/</link><guid isPermaLink="false">http://ryanogles.by/its-not-magic-you-just-dont-understand-it-yet/</guid><pubDate>Sat, 19 Nov 2016 14:09:35 GMT</pubDate><content:encoded>&lt;!-- prettier-ignore --&gt;
&lt;p&gt;&lt;strong&gt;Dev 1&lt;/strong&gt;: “Wait, how did it do that?” &lt;br/&gt;
&lt;strong&gt;Dev 2&lt;/strong&gt;: “I have not clue, it’s Spring* magic.” &lt;br/&gt;
&lt;strong&gt;Dev 1&lt;/strong&gt;: “Oh well, as long as it just works!”&lt;br/&gt;
* &lt;em&gt;substitute Spring for any library or framework&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Every time I hear (or, admittedly, say) something like this, I cringe.&lt;/p&gt;
&lt;p&gt;When we refer to code as magic, we perpetuate the mindset that some code is unaccessible. That we
don’t need to know &lt;em&gt;how&lt;/em&gt; something works, only that is &lt;em&gt;does&lt;/em&gt; work. This is not the mindset of a
true craftsman. A craftsman seeks to understand the tools she uses, because she knows that she will
be able to use them more effectively, and will be more able to deal with inevitable failures.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Of course it is natural to think that something you have not yet understood is magic. Language
features such as Metaprogramming in Ruby or Java’s Reflection API are advanced features that are
often called magical. However, under examination they can be understood and are usable, important
parts of those languages. If we write-off things we don’t understand, or have not tried to
understand, as magic, we are doing ourselves a disservice.&lt;/p&gt;
&lt;p&gt;A real consequence of this is the reflex to grab a library/plugin/framework for everything. Many
times the simplest and most flexible thing to do is implement something yourself. At some point you
may realize that you need a library to avoid having to maintain a lot of code yourself, and when
that happens, switch to it. But now you will have a good understanding of what it provides. Just the
other day I had a conversation with a couple developers on my team who were fixing the formatting of
currency values in our JavaScript app. They had found a library online for it. Instead, I encouraged
them to start with using &lt;code class=&quot;language-text&quot;&gt;toFixed&lt;/code&gt;, a native JavaScript method. Some day we may want the library,
but until then the devs know a simple way for formatting a JavaScript number using fixed-point
notation, and our app does not pull in yet another dependency.&lt;/p&gt;
&lt;p&gt;Seek to understand how magic bits of code actually work. The easiest thing to do is to read the
docs! I’m constantly surprised at how many developers breeze over documentation, missing key
features. Take time to go through documentation, you’ll likely find some great things in there that
you have not been doing.&lt;/p&gt;
&lt;p&gt;Another way to understand is to imagine the simplest version of a library of framework. Take away
all the bells and whistles and get to the core of what the library does. How do you think it works
in its most basic form? Could you code a bare-bones version of it? Give it a shot! Don’t worry about
“getting it right” or producing the most efficient, elegant solution. Just see if you can get
something working, even a little bit. This is one of the most powerful ways to reveal the magic ways
of a library or framework. You will likely be pleasantly surprised at the simplicity of your
solution. And, you will likely learn a thing or two along the way.&lt;/p&gt;
&lt;p&gt;So, in the process of writing this post, I decided to do just that. I took a stab at implementing a
simple version of
&lt;a href=&quot;http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html&quot;&gt;Spring’s autowired&lt;/a&gt;
dependency injection facility. I spent a few hours on it, and managed to learn a few things in the
process.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Detecting classes on the classpath is hard. I thought there was a simple Java API for doing this,
but there does not seem to be. I ended up using some code I found online for this part so I
wouldn’t have to re-implement it myself.&lt;/li&gt;
&lt;li&gt;I got a refresher in Java Reflection as my solution needed to be able to detect the presence of
specific annotations, get constructor parameters, and dynamically construct objects.&lt;/li&gt;
&lt;li&gt;The simplest solution I could do did all the dependency injection right away, though I’m not sure
if Spring actually does it this way or not. I am assuming it takes a lazy approach, which could
be more efficient for program start up. Spring may even allow you to configure the dependency
injection as eager or lazy.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is my solution: &lt;a href=&quot;https://github.com/ryanoglesby08/spring-autowired-revealed&quot;&gt;https://github.com/ryanoglesby08/spring-autowired-revealed&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Try to avoid using the term “magic” when talking about code. Remember, there is no magic. Just code.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[On Injecting a JavaScript Environment]]></title><description><![CDATA[Updated 2017-02-12 : Added a strategy for loading configuration at initial page load, using an
“env.js” file. Recently, I needed to inject…]]></description><link>http://ryanogles.by/on-injecting-a-javascript-environment/</link><guid isPermaLink="false">http://ryanogles.by/on-injecting-a-javascript-environment/</guid><pubDate>Fri, 04 Nov 2016 16:44:20 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Updated 2017-02-12&lt;/strong&gt;: Added a strategy for loading configuration at initial page load, using an
“env.js” file.&lt;/p&gt;
&lt;p&gt;Recently, I needed to inject some configuration variables into my client-side app. Because Googling
for it turned up a lot of “well, you could maybe do this…” I decided to write down what I see as
the 3 main options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best in show:&lt;/strong&gt; Load configuration at &lt;em&gt;run time&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prize for simplest solution:&lt;/strong&gt; Build your application with configuration variables as constants
at &lt;em&gt;compile time&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Runner up: Use server-side templating to inject configuration at &lt;em&gt;render time&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- more --&gt;
&lt;h2&gt;So, what do I want to do again?&lt;/h2&gt;
&lt;p&gt;First, let’s define the problem clearly. Handling configuration variables is something most
applications need. For server-side applications, there are plenty of options out there. Most involve
loading properties from files and then overriding values with environment variables injected at run
time - such as the &lt;a href=&quot;https://www.npmjs.com/package/config&quot;&gt;config package&lt;/a&gt; for node servers.&lt;/p&gt;
&lt;p&gt;Client-side applications present some challenges. Because the app is delivered to the client web
browser, loading files from the server does not work as easily. Specifying values with environment
variables is also different, because the “environment” in a client app is the user’s web browser. We
don’t have access to that JavaScript environment to inject values.&lt;/p&gt;
&lt;p&gt;Finally, I want to follow the recommendations for configuration of the
&lt;a href=&quot;https://12factor.net/config&quot;&gt;Twelve-Factor app&lt;/a&gt;, which boil down to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“strict separation of config from code”&lt;/li&gt;
&lt;li&gt;“…stores config in environment variables” rather than environment specific config files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, let’s examine the options, and consider the pros and cons of each.&lt;/p&gt;
&lt;h2&gt;Load configuration at &lt;em&gt;run time&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;This is strategy I went with, and seems to be working well. With this approach, the client app loads
configuration from a remote server on initial page load.&lt;/p&gt;
&lt;p&gt;Because we do not have to bake in the configuration values to the compiled JavaScript, (one of the
other options) we get to build our application only once. This means we deploy the exact same code
to all environments. Score.&lt;/p&gt;
&lt;p&gt;We also do not have to use any server side templating, which gives us more freedom in how we deploy
and serve our application. We can serve our application as static files if we want to.&lt;/p&gt;
&lt;p&gt;The trick here is to build a little bit of smarts into our web server, so that it converts an
injected set of environment variables to a JavaScript file on startup, and then serves it as a
static file.&lt;/p&gt;
&lt;p&gt;Here is the gist:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In your &lt;code class=&quot;language-text&quot;&gt;index.html&lt;/code&gt; file, add a script tag for an “env.js” file, which does not exist. (yet)&lt;/li&gt;
&lt;li&gt;In your application server code, write the “env.js” file on startup using an environment variable
as the contents. Then statically serve the directory containing the “env.js” file.&lt;/li&gt;
&lt;li&gt;Make the environment variable available to the server when running it.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- 1. index.html --&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/env.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/app.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 2. server.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;fs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;__dirname&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/config/env.js`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`var config = &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CLIENT_ENV&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;;`&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/dist&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/config&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;index.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 3. running the server&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;export&lt;/span&gt; CLIENT_ENV&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;{API_URL: &quot;http://dev.my-api.some-domain.com&quot;}&apos;&lt;/span&gt;
node server.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;One of the downsides here is that we are creating global state, the &lt;code class=&quot;language-text&quot;&gt;config&lt;/code&gt; variable, which is
something that is generally frowned upon and avoided in modern JavaScript apps (and most
applications for that matter). There are a few ways to address this, with the simplest being to
agree not to read from the &lt;code class=&quot;language-text&quot;&gt;config&lt;/code&gt; variable directly, and create a function that your application
always uses to access it. This way, the only place in your codebase where the config variable is
touched is that function. You should also &lt;strong&gt;never&lt;/strong&gt; modify the config variable. Treat it as read
only.&lt;/p&gt;
&lt;h3&gt;An experiment - asynchronous configuration loading&lt;/h3&gt;
&lt;p&gt;Along similar lines, I also played with loading configuration from a remote server with an
XMLHttpRequest. This feels like a cool approach, but the wrench here is that introducing
asynchronous network calls introduces un-necessary complexity. Now, all of a sudden your config
properties are not available until that call comes back. This can cause some awkward uses based on
how/when you need your environment config.&lt;/p&gt;
&lt;p&gt;To play with this idea, I wrote this &lt;em&gt;unreleased&lt;/em&gt; npm package. Check it out if you are interested
and provide feedback or make a pull request!
&lt;a href=&quot;https://github.com/ryanoglesby08/xhr-env-provider&quot;&gt;xhr-env-provider&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Build your application with configuration variables as constants at &lt;em&gt;compile time&lt;/em&gt;.&lt;/h2&gt;
&lt;p&gt;This is probably the most straight-forward option, and uses your build tool to inject constants into
your code as global variables at compile time. The
&lt;a href=&quot;https://github.com/webpack/docs/wiki/list-of-plugins#defineplugin&quot;&gt;DefinePlugin&lt;/a&gt; is the best way to
do this if you are bundling your app with webpack.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;## building your app&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;export&lt;/span&gt; API_URL&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://dev.my-api.some-domain.com&quot;&lt;/span&gt;
webpack --define process.env.API_URL&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&apos;&lt;span class=&quot;token variable&quot;&gt;$API_URL&lt;/span&gt;&apos;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// inside your application code&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; apiUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_URL&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http://localhost:8080&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The downside with this approach is that if your configuration varies for each deployed environment
(which it surely will), you will have to build multiple versions of your app. This is less than
ideal, as it adds extra steps to your build and deploy process. It also means that the asset you use
in lower environments (dev) is not the same as the asset you use in production, because you have
re-compiled it.&lt;/p&gt;
&lt;p&gt;However, it is likely that you will compile different versions of your app anyway. For example, you
probably won’t enable source maps for your production build. Webpack support this concept.
&lt;a href=&quot;http://webpack.github.io/docs/cli.html#development-shortcut-d&quot;&gt;http://webpack.github.io/docs/cli.html#development-shortcut-d&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This technique is best suited for externalizing configuration that does not change throughout your
build and deploy process. Turning console logging on/off, for example. Locally, you may want console
logging to be on, but in all deployed environments you may not want to be doing that.&lt;/p&gt;
&lt;h2&gt;Use server-side templating to inject configuration at &lt;em&gt;render time&lt;/em&gt;.&lt;/h2&gt;
&lt;p&gt;In other words, just throw some globals into the &lt;code class=&quot;language-text&quot;&gt;window&lt;/code&gt; object when the page is initially
rendered. Here is an example using &lt;a href=&quot;https://pugjs.org&quot;&gt;Pug&lt;/a&gt; (formerly known as Jade)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-pug&quot;&gt;&lt;code class=&quot;language-pug&quot;&gt;&lt;span class=&quot;token markup&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- views/index.pug --&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token doctype&quot;&gt;doctype html&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;html&lt;span class=&quot;token attributes&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;head&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;token plain-text&quot;&gt;My App&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;body&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;div&lt;span class=&quot;token attributes&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token tag&quot;&gt;script&lt;span class=&quot;token attributes&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token multiline-script&quot;&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#{API_URL}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;script&lt;span class=&quot;token attributes&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt; src&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/app.js&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// server.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/public&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/assets&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;view engine&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pug&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;index&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_URL&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# running the server&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;export&lt;/span&gt; API_URL&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://dev.my-api.some-domain.com&quot;&lt;/span&gt;
node server.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app.js&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The API_URL is: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Two things here that are not so great. First, we are creating global state again. Second, we have to
introduce a dependency on a templating engine. This means we can no longer just serve our client
application as static assets. With option #1, we could have used something like Amazon S3 to deliver
our client app, while now we have to maintain our own server in order to do the templating.&lt;/p&gt;
&lt;p&gt;This approach has more of an old-school feel to it with the server-side templating and the global
window variable.&lt;/p&gt;
&lt;p&gt;It might be fine for you though if you are already using server-side templating. This is pretty much
the way I did it in the last Rails app I worked on (back in 2014).&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think being able to injecting env properties at runtime is the way to go for large-scale
production applications, as it gives you the most flexible options for local development and
deployments. But, if you want a quick win for a side-project or small app, injecting at compile time
is super easy. I probably wouldn’t use the server-side templating unless I was working on an
application that was already doing that.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Harmonious Stylesheets and Inline Styles in React]]></title><description><![CDATA[Styling React components seems to be one of those things where there are a lot of solutions
( libraries )
emerging that try to solve the…]]></description><link>http://ryanogles.by/harmonious-stylesheets-and-inline-styles-in-react/</link><guid isPermaLink="false">http://ryanogles.by/harmonious-stylesheets-and-inline-styles-in-react/</guid><pubDate>Sat, 15 Oct 2016 14:28:00 GMT</pubDate><content:encoded>&lt;p&gt;Styling React components seems to be one of those things where there are a lot of solutions
(&lt;a href=&quot;https://github.com/FormidableLabs/radium/blob/master/docs/comparison/README.md&quot;&gt;libraries&lt;/a&gt;)
emerging that try to solve the problem of how to use &lt;em&gt;only&lt;/em&gt; inline styles in JavaScript sustainably.
To me, it seems that this problem has been invented and can easily be avoided; and introducing a new
library or tool is only adding to the complexity and cognitive overhead of your app. Many times it
really is just better to stick with plain ol CSS stylesheets.&lt;/p&gt;
&lt;p&gt;Both traditional stylesheets and inline styles have their place within React applications. By using
them harmoniously you can have the best of both worlds.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;What is style anyway?&lt;/h2&gt;
&lt;p&gt;The first thing to realize is that “style” is actually a few related concepts. I like to break it
down into 2 main categories: presentational styles and behavioral styles.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Presentational&lt;/strong&gt; styles describe the appearance of your application as a whole, and are rarely
specific to a particular component. Instead, presentational styles define how elements look in
relation to each other, and play the main role in the overall look-and-feel of the application. They
are also always static. Base font styles, the color palette, and your grid system are all examples
of presentational styling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Behavioral&lt;/strong&gt; styles describe how individual elements of your application look and behave in a
given state. They are dynamic, requiring logic to determine. For example, if an element changes
background colors when some state in the app is reached, then that is a behavioral style.&lt;/p&gt;
&lt;h2&gt;Prefer traditional stylesheets for presentational styling&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;For all the presentational styling needs of your application, stick with simple, traditional CSS
stylesheets.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This will allow you to use modern CSS tools/languages such as &lt;a href=&quot;http://sass-lang.com&quot;&gt;Sass&lt;/a&gt; or
&lt;a href=&quot;http://lesscss.org&quot;&gt;LeSS&lt;/a&gt; and third party libraries such as &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt;
or &lt;a href=&quot;http://bourbon.io/&quot;&gt;Bourbon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, some CSS features such as media queries are at best painful and at worst impossible to
do with inline styles alone.&lt;/p&gt;
&lt;p&gt;Finally, for teams with non-developers such as Designers contributing to the styles, there is a high
chance that they will be more comfortable and productive working with traditional stylesheets than
inlined CSS inside of JavaScript files.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-scss&quot;&gt;&lt;code class=&quot;language-scss&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Example of some presentational styles (Sass)&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;html &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;@include&lt;/span&gt; base-font&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;.button &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$light-blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$gray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token parent important&quot;&gt;&amp;amp;&lt;/span&gt;:hover &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$dark-blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;Prefer inline styles for behavioral styling&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Because behavioral styles are determined by application state, which will be held in JavaScript,
keep them co-located with the component as inline styles.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This makes conditional state classes totally unnecessary. No more “is-complete” or “has-ratings”
type of class names anymore.&lt;/p&gt;
&lt;p&gt;Behavioral styles can and should be unit tested. This isn’t perfect though, even though your
assertion that a particular style is applied passes, the component still may not render exactly the
way you want it in the browser.&lt;/p&gt;
&lt;p&gt;Here is a working example of a &lt;code class=&quot;language-text&quot;&gt;Nav&lt;/code&gt; component whose behavior is to slide out from the left side of
the screen when opened. The dynamic state is &lt;code class=&quot;language-text&quot;&gt;sliderMenuVisible&lt;/code&gt;, which changes the &lt;code class=&quot;language-text&quot;&gt;left&lt;/code&gt; css
property, triggering an animation. Notice the use of the &lt;code class=&quot;language-text&quot;&gt;nav&lt;/code&gt; class name for presentational styling
concerns too.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Nav.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; styles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  transition&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;left 0.5s&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;Nav&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sliderMenuVisible&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; toggleNavSliderMenu &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sliderMenuVisible&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    styles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;styles&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nav className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;nav&quot;&lt;/span&gt; style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;styles&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Link to&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/browse&quot;&lt;/span&gt; onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;toggleNavSliderMenu&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            Browse
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Link&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Link to&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/orders&quot;&lt;/span&gt; onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;toggleNavSliderMenu&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            Past Orders
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Link&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;ul&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nav&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;A Problem&lt;/h2&gt;
&lt;p&gt;The big problem here is that you cannot easily share code between CSS stylesheets and JavaScript
inline styles. If you have defined a Sass variable &lt;code class=&quot;language-text&quot;&gt;$dark-red&lt;/code&gt; and also want to use that same color
in a behavioral style, you would be forced to hard code the color value into the JavaScript too.&lt;/p&gt;
&lt;p&gt;But, I have not seen this as a huge problem yet, and I don’t think this would be a hard problem to
solve if it gets un-maintainable in your project.&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/26882177/react-js-inline-style-best-practices&quot;&gt;http://stackoverflow.com/questions/26882177/react-js-inline-style-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/the-debate-around-do-we-even-need-css-anymore/&quot;&gt;https://css-tricks.com/the-debate-around-do-we-even-need-css-anymore/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jamesknelson.com/why-you-shouldnt-style-with-javascript/&quot;&gt;http://jamesknelson.com/why-you-shouldnt-style-with-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Homogeneous Pipelines with Docker]]></title><description><![CDATA[Continuous Integration Build Pipelines 
are a dirty, nasty place. What usually starts out as a couple of simple tasks or bash scripts…]]></description><link>http://ryanogles.by/homogeneous-pipelines-with-docker/</link><guid isPermaLink="false">http://ryanogles.by/homogeneous-pipelines-with-docker/</guid><pubDate>Mon, 26 Sep 2016 09:55:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://martinfowler.com/articles/continuousIntegration.html&quot;&gt;Continuous Integration Build Pipelines&lt;/a&gt;
are a dirty, nasty place. What usually starts out as a couple of simple tasks or bash scripts
inevitably ends up as a heap of scripts, Gradle/Rake/Maven/(insert build tool here) tasks, and
manually configured jobs held together with a thin layer of Elmer’s glue and Scotch tape.&lt;/p&gt;
&lt;p&gt;Why? Partly because modern applications are complex; even simple stacks use multiple languages and
tools. And partly because developers are lazy, and sometimes hesitant to “mess with the pipeline.” I
don’t often see the amount of rigor in cleanliness applied to them as to other parts of the
codebase, leading to unnecessarily complex and unfortunately tangled build pipelines.&lt;/p&gt;
&lt;p&gt;So, my current team attacked this head-on using a great piece of technology:
&lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt;! Using Docker as our sole interface to running things in our build
pipeline, we sped it up, simplified it, and lived happily ever after.&lt;/p&gt;
&lt;p&gt;To give credit where credit is due, the implementation of this pattern was spearheaded by my
colleague &lt;a href=&quot;https://twitter.com/amber_ht&quot;&gt;Amber Houle&lt;/a&gt;.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Anatomy of a Pipeline&lt;/h2&gt;
&lt;p&gt;This is pretty much what our build pipeline looked like in the time before Docker. Notice the amount
of variation in what is being invoked in each step! (All these steps could be wrapped up in bash
scripts, but I’ve unravelled them here.)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“client” is a JS front-end application. “api” is a Java-based API.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# pipeline.yaml&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;build_client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install       &lt;span class=&quot;token comment&quot;&gt;# Install JS dependencies&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm run webpack   &lt;span class=&quot;token comment&quot;&gt;# Compile to JS&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;build_api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gradle build      &lt;span class=&quot;token comment&quot;&gt;# Compile Java&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;test_client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install       &lt;span class=&quot;token comment&quot;&gt;# Install JS dependencies..... again&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm test          &lt;span class=&quot;token comment&quot;&gt;# Run JS tests&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;test_api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; systemctl start postgresql.service  &lt;span class=&quot;token comment&quot;&gt;# Start up Postgres&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; flyway migrate                      &lt;span class=&quot;token comment&quot;&gt;# Migrate the database using Flyway&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gradle test                         &lt;span class=&quot;token comment&quot;&gt;# Run Java tests (unit and integration)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; systemctl stop postgresql.service   &lt;span class=&quot;token comment&quot;&gt;# Stop Postgres&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;package_client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install       &lt;span class=&quot;token comment&quot;&gt;# Install JS dependencies once again :(&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm run package   &lt;span class=&quot;token comment&quot;&gt;# Package up the JS into a .zip or .tar&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &amp;lt;push JS code to artifact repository&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;package_api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gradle package    &lt;span class=&quot;token comment&quot;&gt;# Create an executable .jar&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &amp;lt;push Java code to artifact repository&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;deploy_to_qa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &amp;lt;pull code from artifact repo and deploy&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Let’s first examine a build pipeline that you might find using any of the modern open-source
distributed build and deploy tools such as &lt;a href=&quot;https://jenkins.io/&quot;&gt;Jenkins&lt;/a&gt;,
&lt;a href=&quot;https://www.go.cd/&quot;&gt;Go.cd&lt;/a&gt;, or &lt;a href=&quot;https://travis-ci.com/&quot;&gt;TravisCI&lt;/a&gt;. It’s broken down into a series
of stages or jobs, which could be run sequentially or in parallel. Because these tools usually run
as a &lt;a href=&quot;https://jenkins.io/doc/book/architecting-for-scale/&quot;&gt;master/agent architecture&lt;/a&gt;, the server
will delegate the actual work of each stage to an available build agent.&lt;/p&gt;
&lt;h3&gt;Pipeline complexities&lt;/h3&gt;
&lt;p&gt;While this architecture is scalable and flexible, it creates complexities that &lt;strong&gt;you&lt;/strong&gt; have to
manage. Since each stage in your pipeline has a different job to do, all your agents must be
configured to perform all needed actions. Some stages need a JavaScript runtime, some need Java,
while others need a Postgres database. Traditionally, this calls for provisioning your agents with
all the appropriate software ahead of time. And herein lies a dilemma. Manually provisioning might
work fine if you only have 1 or 2 agents, but that quickly becomes tedious as the number of
dependencies you have increases or the number of agents you need increases. Automated provisioning
using Chef or Puppet is an option, but this creates one more piece of code to build, manage, test,
and debug.&lt;/p&gt;
&lt;p&gt;As each agent picks up a stage to run, it’s going to need some input, which is often just a copy of
your source code at a specific revision. Because any agent could be picking up any job at any time,
the sequence is usually 1) start with a clean workspace 2) checkout the code 3) install
dependencies 4) do stuff. All these steps take time, especially installing dependencies. (There are
3 &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt; commands in the pipeline shown above)&lt;/p&gt;
&lt;h2&gt;Docker as the Pipeline Interface&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Docker containers wrap a piece of software in a complete filesystem that contains everything
needed to run: code, runtime, system tools, system libraries – anything that can be installed on a
server. &lt;br/&gt; &lt;cite&gt;&lt;a href=&quot;https://www.docker.com/what-docker&quot;&gt;https://www.docker.com/what-docker&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What if we extend this statement to say that containers contain everything needed to run… &lt;strong&gt;and
build and test&lt;/strong&gt;? Instead of provisioning build agents with all the individual pieces of software
and dependencies that our pipeline needs, let’s provision them with only the Docker Engine. Now, the
sequence of steps for any stage becomes 1) Pull down a Docker image 2) Execute &lt;code class=&quot;language-text&quot;&gt;docker run&lt;/code&gt;
&lt;a href=&quot;https://docs.docker.com/engine/reference/run/&quot;&gt;https://docs.docker.com/engine/reference/run/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To pull this off, we first need to create some Docker images with &lt;strong&gt;everything our application needs
to build and test itself&lt;/strong&gt;, which we specify with a
&lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Dockerfile&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-docker&quot;&gt;&lt;code class=&quot;language-docker&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Dockerfile for Java API&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;8

&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; build.gradle ./
&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; src ./src/

&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; gradle jar

&lt;span class=&quot;token keyword&quot;&gt;ENTRYPOINT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gradle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-docker&quot;&gt;&lt;code class=&quot;language-docker&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Dockerfile for database migrations&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; shouldbee/flyway

&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; ./src/main/resources/db/migration/*.sql ./sql/

&lt;span class=&quot;token keyword&quot;&gt;ENTRYPOINT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;flyway&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-docker&quot;&gt;&lt;code class=&quot;language-docker&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Dockerfile for JS client&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;6.4.0

&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; package.json ./
&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; npm install
&lt;span class=&quot;token keyword&quot;&gt;COPY&lt;/span&gt; src ./src/
&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; npm run webpack

&lt;span class=&quot;token keyword&quot;&gt;ENTRYPOINT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;run&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;And this is pretty much what our pipeline evolved into after transitioning to Docker…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# pipeline.yaml&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;build_client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker build &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;t client&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; ./client  &lt;span class=&quot;token comment&quot;&gt;# Build Docker image&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker push client&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;               &lt;span class=&quot;token comment&quot;&gt;# Push it to the container registry&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;build_api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker build &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;t api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; ./api
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker build &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;t migrations&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; ./api

  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker push api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker push migrations&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;test_client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker pull client&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker run client&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; test   &lt;span class=&quot;token comment&quot;&gt;# Run `npm run test` inside of the client container&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;test_api&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker pull api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker pull migrations&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker run migrations&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; migrate  &lt;span class=&quot;token comment&quot;&gt;# Run `flyway migrate` inside of the migrations container&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; docker run api&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;PIPELINE_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; test            &lt;span class=&quot;token comment&quot;&gt;# Run `gradle test` inside of the api container&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h3&gt;Complexities simplified&lt;/h3&gt;
&lt;p&gt;Overall, this had a number of positive effects on our build pipeline. First, &lt;strong&gt;speed&lt;/strong&gt;: the time
from pipeline start to ready to deploy to a QA environment dropped from ~12 minutes to ~4 minutes!
This was largely due to no longer checking out the entire code base, installing dependencies, and
re-compiling in each step of the pipeline. Second, &lt;strong&gt;simplicity.&lt;/strong&gt; Configuring new build agents is
now easy, as they only need Docker Engine. The single command interface is also cognitively simple.
Each call to &lt;code class=&quot;language-text&quot;&gt;docker run [COMMAND]&lt;/code&gt; in the pipeline acts as a proxy to the task runner already in
use in the codebase (e.g &lt;code class=&quot;language-text&quot;&gt;gradle [COMMAND]&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;npm run [COMMAND]&lt;/code&gt;), making it work just like local
development without Docker.&lt;/p&gt;
&lt;p&gt;The main possible issue I see with this is that the Docker container has a large surface area, which
kind of goes against the advice from Docker to keep images as slim and trim as possible. I normally
would not include all my test code into the deployable artifact that will eventually end up on my
production server. Instead we have copied &lt;strong&gt;all&lt;/strong&gt; the source and test code into the image. This
could introduce dependency issues, such as security holes that may exist in libraries pulled in by
test code. I have not observed this in practice though.&lt;/p&gt;
&lt;p&gt;You will also notice that we push the Docker image to the registry right away. This ensures that the
artifact that passes down the pipeline is exactly the same all the way through build, test, and
deploy. But, it also means we are creating an artifact for un-verified code. What if the tests fail
for a certain commit, but we have already created and pushed the Docker image? Do we leave it in the
registry? Remove it? So far, we have just left them there, so not sure how this will play out in the
long term.&lt;/p&gt;
&lt;p&gt;Overall, this pattern has worked well for the team! Would love to hear your opinions and experiences
with Docker in a build pipeline.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How your 'Mother' can help you 'Build' cleaner unit tests - Part III]]></title><description><![CDATA[We ended  Part II  with an inner
Builder for  , which forced us to revert to specifying seemingly arbitrary values in each
test that needed…]]></description><link>http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-iii/</link><guid isPermaLink="false">http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-iii/</guid><pubDate>Sun, 26 Jun 2016 21:28:58 GMT</pubDate><content:encoded>&lt;p&gt;We ended &lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-ii&quot;&gt;Part II&lt;/a&gt; with an inner
Builder for &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt;, which forced us to revert to specifying seemingly arbitrary values in each
test that needed to build an &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What I’ve usually seen at this point is pulling the Address objects into constants in each test
class. As the test suite grows, the number of &lt;code class=&quot;language-text&quot;&gt;private static final Address WHATEVER_ADDRESS = ...;&lt;/code&gt;
grows and grows. Doing that makes it hard to keep control over your test data, especially in a large
codebase. A minor change to Address, such as a new invariant or an added field, could cause
cascading changes to keep all those objects valid.&lt;/p&gt;
&lt;p&gt;To avoid that, the next step is actually a very simple one, and boils down to centralizing the
definition and creation of an &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; with an Object Mother.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;4) Introducing an Object Mother&lt;/h2&gt;
&lt;p&gt;An &lt;a href=&quot;http://martinfowler.com/bliki/ObjectMother.html&quot;&gt;Object Mother&lt;/a&gt; is a type of Factory used to
create example objects for testing. Let’s see it in action:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ... no change, still using inner Builder&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// Test only class&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddressMother&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder &lt;span class=&quot;token function&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123 Main St.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineTwo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Chicago&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder &lt;span class=&quot;token function&quot;&gt;hawaiianAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123 Hawaii St.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineTwo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Honolulu&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HI&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; AddressMother&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingServiceTest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shipsToTheAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Address shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDeliveryAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cannotShipToHawaii&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hawaiianAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertFalse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFailureReason&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cannot ship to Hawaii.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The Mother controls the values that constitute an example &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt;. Now, when a test needs an
&lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; it asks the Mother for one. Your Mother could return fully initialized &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; objects,
but instead we have chosen to have it return Builders. This powerful variation allows a test to get
a basic example object, and then modify it depending on what it is testing.&lt;/p&gt;
&lt;p&gt;Give your Mother class the ability to build objects with various states as appropriate. In our case,
we currently have the need for a basic, valid address, and a Hawaiian address. But, be wary of
creating a different factory method for every example object you need. That may be a bit overkill.
I’d say to only create factory methods for things that represent core use cases and not one for each
edge case that you test. For example, if I wanted to test what happens when &lt;code class=&quot;language-text&quot;&gt;state&lt;/code&gt; is empty, I’d do
&lt;code class=&quot;language-text&quot;&gt;address().state(&amp;quot;&amp;quot;).build()&lt;/code&gt; over creating an &lt;code class=&quot;language-text&quot;&gt;addresWithoutAState()&lt;/code&gt; factory method in the Mother.&lt;/p&gt;
&lt;h2&gt;The End&lt;/h2&gt;
&lt;p&gt;Whew, that’s it! Thanks for making it this far. If you skipped Parts
&lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-i&quot;&gt;I&lt;/a&gt; or
&lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-ii&quot;&gt;II&lt;/a&gt;, I’d recommend going back to
see the entire journey. We teased out a nice pattern for managing test data using the Builder
pattern + Object Mothers. In doing so, we improved the design of our production code by making
&lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; immutable and avoiding a sketchy constructor with a lot of parameters.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How your 'Mother' can help you 'Build' cleaner unit tests - Part II]]></title><description><![CDATA[In  Part I , we created a separate
Builder class in an attempt to move away from a constructor with too many parameters. In the
process, the…]]></description><link>http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-ii/</link><guid isPermaLink="false">http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-ii/</guid><pubDate>Sat, 25 Jun 2016 14:20:26 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-i&quot;&gt;Part I&lt;/a&gt;, we created a separate
Builder class in an attempt to move away from a constructor with too many parameters. In the
process, the separate Builder ended up taking on the additional responsibility of supplying default
values, blurring the line between a Builder and Factory.&lt;/p&gt;
&lt;p&gt;Though a step in the right direction, it didn’t actually fix any of the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; constructor’s
original problems, unfortunately. Oops. Other classes can still call it directly, meaning all of the
risks of having a method with multiple parameters of the same type are still there, and we have
another class in our system to maintain.&lt;/p&gt;
&lt;p&gt;What we need is a strictly controlled way of creating &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; objects that can be accessed by test
code &lt;em&gt;and&lt;/em&gt; prod code that is decoupled from the current constructor and it’s baggage.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;3) Pulling the Builder inside Address&lt;/h2&gt;
&lt;p&gt;Let’s remodel the Builder as a static inner class within the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Prevent other objects from calling the constructor&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ... other methods omitted for brevity&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Builder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; Builder &lt;span class=&quot;token function&quot;&gt;lineOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineOne&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; Builder &lt;span class=&quot;token function&quot;&gt;lineTwo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ... city() and state() builder methods omitted for brevity&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; Address &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Builder builder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; builder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; builder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;city &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; builder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; builder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingServiceTest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder shippingAddressBuilder&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Before&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    shippingAddressBuilder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Builder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123 Main St.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineTwo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Chicago&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;IL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shipsToTheAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Address shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shippingAddressBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDeliveryAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cannotShipToHawaii&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    Address shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shippingAddressBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HI&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertFalse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFailureReason&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cannot ship to Hawaii.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Looking good&lt;/th&gt;
      &lt;th&gt;Needs improvement&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;p&gt;
          We have coupled the Builder to the &lt;code&gt;Address&lt;/code&gt; class more tightly, which is good. They must change together.
        &lt;/p&gt;
        &lt;p&gt;
          Also, we have finally gotten rid of the public all-args constructor with too many parameters!
        &lt;/p&gt;
        &lt;p&gt;
          To take it even further, we removed &lt;em&gt;all&lt;/em&gt; public constructors. The &lt;a href=&quot;http://www.javapractices.com/topic/TopicAction.do?Id=40&quot;&gt;Private Constructor pattern&lt;/a&gt; tells collaborators that object construction is internal and explicitly controlled by the class itself. The Builder is now the only way to construct an &lt;code&gt;Address&lt;/code&gt;.
        &lt;/p&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;p&gt;
          However, the dual responsibilities of the separate Builder class have reared their ugly head. In order to prevent leaking test code (the default values) into our prod code (the inner Builder), we had to remove them altogether for now and go back to specifying them in the test class itself.
        &lt;/p&gt;
        &lt;p&gt;
          This means we go back to the problem of confusing arbitrary values appearing in our tests.
        &lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Next up, &lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-iii&quot;&gt;Part III&lt;/a&gt; - where we
truly divide the responsibilities for object construction into a Builder and a Factory, removing the
arbitrary default values from the test itself.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How your 'Mother' can help you 'Build' cleaner unit tests - Part I]]></title><description><![CDATA[Over the past few months on my project, a pattern emerged for using Builders and Object Mothers to
build-up objects for unit testing. We…]]></description><link>http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-i/</link><guid isPermaLink="false">http://ryanogles.by/how-your-mother-can-help-you-build-cleaner-unit-tests/part-i/</guid><pubDate>Thu, 23 Jun 2016 13:34:08 GMT</pubDate><content:encoded>&lt;p&gt;Over the past few months on my project, a pattern emerged for using Builders and Object Mothers to
build-up objects for unit testing. We were able to keep our tests minimal and clean, decouple test
code from production code, and solve some design issues such as constructors with too many
parameters. In this multi-part series, I will take you through the evolution of the pattern over a
series of refactorings.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;The Scenario:&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Note: This is contrived for simplicity&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The basics:&lt;/strong&gt; We are building a system that schedules shipments of widgets to a specified address.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The interesting bit:&lt;/strong&gt; We have an &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; class that we use quite often in our tests. By “use”,
I mean instantiate one with some valid data to either exercise it or assert against it.&lt;/p&gt;
&lt;h2&gt;1) Initial Code&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineOne&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;city &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ... other methods omitted for brevity&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingServiceTest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; Address shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Before&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123 Main St&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chicago&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shipsToTheAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDeliveryAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cannotShipToHawaii&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HI&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertFalse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFailureReason&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cannot ship to Hawaii.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The two hot spots here are the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; constructor and the customization of the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; fields
in the tests.&lt;/p&gt;
&lt;p&gt;Let’s talk about the constructor:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;It has &lt;a href=&quot;http://c2.com/cgi/wiki?TooManyParameters&quot;&gt;too many parameters&lt;/a&gt;&lt;/strong&gt; - four! (And you could
imagine a real &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; object having at least a couple more) And, multiple parameters in a row
of the same type is even worse. If I accidentally swap &lt;code class=&quot;language-text&quot;&gt;state&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;city&lt;/code&gt; my program will still
compile as both parameters are Strings, but it will probably fail at an unexpected time later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The arbitrary values used to construct the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; do not reveal intention.&lt;/strong&gt; Why “123 Main
St”? Why “IL”? Could I change that to be any state? Which values are effecting the outcome of
each test and which are completely arbitrary?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional parameters.&lt;/strong&gt; &lt;code class=&quot;language-text&quot;&gt;lineTwo&lt;/code&gt; seems to be optional because of the empty String. Should we
overload the constructor instead? Provide a setter?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And customizing the &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; fields for each test:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prefer immutable state.&lt;/strong&gt; The &lt;code class=&quot;language-text&quot;&gt;setState&lt;/code&gt; method makes &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; mutable. Before that, we had a
nice, happy immutable object, as you can see by the presence of the &lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt; keyword on the other
instance fields. &lt;br/&gt; Because we were using the same &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; object in many tests and we
needed a different value for only one field, we added a setter instead of calling the constructor
again. On the upside though, at least this test reveals its intention - that this test only cares
about the &lt;code class=&quot;language-text&quot;&gt;state&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep test-only code out of production code.&lt;/strong&gt; It’s very likely that &lt;code class=&quot;language-text&quot;&gt;setState&lt;/code&gt; was added for
this one test, and is not called by any production code. This is a smell that should be avoided.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;2) Introducing a Builder&lt;/h2&gt;
&lt;p&gt;First, we attempt to give &lt;code class=&quot;language-text&quot;&gt;Address&lt;/code&gt; it’s immutability back and avoid adding telescoping constructors
by introducing a &lt;a href=&quot;http://c2.com/cgi/wiki?BuilderPattern&quot;&gt;Builder&lt;/a&gt;. The Builder allows us to separate
the steps for constructing an object from the final representation of it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineOne&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String city&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; String state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;city &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; city&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ... other methods omitted for brevity&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// Test only builder class&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddressBuilder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;123 Main St&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String city &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chicago&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; String state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IL&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; AddressBuilder &lt;span class=&quot;token function&quot;&gt;lineOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineOne&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineOne &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineOne&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; AddressBuilder &lt;span class=&quot;token function&quot;&gt;lineTwo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String lineTwo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineTwo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lineTwo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ... other methods omitted for brevity&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; Address &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lineOne&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lineTwo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; city&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingServiceTest&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; Address shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Before&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddressBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shipsToTheAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDeliveryAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cannotShipToHawaii&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ShippingService service &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShippingService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    shippingAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AddressBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;HI&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    Shipment shipment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shipTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;assertFalse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;wasSuccessful&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shipment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFailureReason&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cannot ship to Hawaii.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Looking good&lt;/th&gt;
      &lt;th&gt;Needs improvement&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;p&gt;
          The Builder lets tests construct &lt;code&gt;Address&lt;/code&gt; instances without invoking the public constructor, reducing the coupling to it.
        &lt;/p&gt;
        &lt;p&gt;
          The addition of default values to the Builder pulls that arbitrary data out of the tests themselves, which further helps to highlight any tests that need a specific value, and without needing a setter.
        &lt;/p&gt;
        &lt;p&gt;
          &lt;code&gt;Address&lt;/code&gt; is immutable. :)
        &lt;/p&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;p&gt;
          This is yet another class to maintain.
        &lt;/p&gt;
        &lt;p&gt;
          By making the Builder a separate object, we still need &lt;code&gt;Address&lt;/code&gt;&apos;s public all-args constructor. Any other test could easily bypass the builder. And, because the constructor is still there, all the problems from before remain.
        &lt;/p&gt;
        &lt;p&gt;
          Additionally, our Builder actually has two responsibilities. First is &lt;em&gt;how&lt;/em&gt; to construct the &lt;code&gt;Address&lt;/code&gt;, as in, which parameters to pass into the constructor. Second, &lt;em&gt;what&lt;/em&gt; to construct it with, because the Builder has default values.
        &lt;/p&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;a href=&quot;/how-your-mother-can-help-you-build-cleaner-unit-tests/part-ii&quot;&gt;Part II&lt;/a&gt; will look at moving the
Builder into a static inner class to fix the constructor with too many parameters issue.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[YAGNI a'int a Design Principle]]></title><description><![CDATA[You Ain’t Gonna Need It  is an XP practice that
encourages developers to focus on the requirements at hand right now. It warns against the…]]></description><link>http://ryanogles.by/yagni-aint-a-design-principle/</link><guid isPermaLink="false">http://ryanogles.by/yagni-aint-a-design-principle/</guid><pubDate>Fri, 12 Feb 2016 13:21:24 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://c2.com/cgi/wiki?YouArentGonnaNeedIt&quot;&gt;You Ain’t Gonna Need It&lt;/a&gt; is an XP practice that
encourages developers to focus on the requirements at hand right now. It warns against the tendency
to over-engineer by developing features based on what you &lt;strong&gt;think&lt;/strong&gt; you will need later. Easy in
theory. Hard in practice.&lt;/p&gt;
&lt;h2&gt;YAGNI Blinders&lt;/h2&gt;
&lt;p&gt;I’ve noticed that developers, especially those just starting out, tend to apply YAGNI
narrow-sightedly. I often see it being strictly adhered to at face-value only, by developers always
choosing to do what seems to be the most obvious and straightforward thing at the time, without
putting any thought into the design implications of their choices. When suggesting other options
that seem to be less simple on the surface, they YAGNI argument gets used. “Oh, that’s YAGNI.”&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;YAGNI encourages simplicity. But many developers read simple as easy, which can lead to design
problems with their code that easily have been avoided. An easy solution doesn’t require any thought
or skill. A simple solution involves elegance, is purposeful, and is built with extensibility and
evolvability in mind. &lt;em&gt;(Rich Hickey, the creator of Clojure, gave a wonderful talk along these same
lines in 2011. &lt;a href=&quot;http://www.infoq.com/presentations/Simple-Made-Easy&quot;&gt;Simple Made Easy&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As an example of YAGNI Blinders, take internationalization (i18n) of a web-app. Usually, the first
requirement is to support only a single language, with support for other languages pretty far down
the line. A classic YAGNI solution here: hard coding everything in the HTML files. Done. (I’ll come
back to this soon….)&lt;/p&gt;
&lt;h2&gt;See the Light!&lt;/h2&gt;
&lt;p&gt;The YAGNI argument breaks down because it does not take critical design characteristics such as
readability, flexibility, and loose coupling into account. A purely YAGNI-based solution does not
necessarily imply those things. By sticking to a YAGNI-only solution, you make it harder to quickly
move forward later, because extensive refactoring or rewriting would be needed first. By considering
simplicity along with many other design principles, you will end up with better factored code.&lt;/p&gt;
&lt;p&gt;The most obvious choice is not always the right one. YAGNI does not mean to plow headfirst into the
first solution you think of. Good design trumps. But figuring out how to satisfy the requirements at
hand, while building a simple, flexible solution without gold-plating, over-engineering, or solving
for unknown future requirements is hard! Good. Glad our job isn’t boring. :)&lt;/p&gt;
&lt;p&gt;Back to i18n, instead of hard coding all the strings in the HTML, we can introduce a simple lookup
mechanism. We store all our strings in a JSON file, and create a simple module that loads that file
into a map structure, so that strings can be looked up by a key.&lt;/p&gt;
&lt;p&gt;Yes, this is not the absolute easiest solution. However, it is simple, and a better design. We have
better separation of concerns. We have pushed configuration (the strings) out of code, allowing them
to change independently as they may change at a different rate than the application code. We could
extend the lookup mechanism without changing the strings or keys. Event If we never get a
requirement to add another language, this is still a better design, and we did not have to build a
complex architecture involving locales, multiple languages, unicode character support, or any of the
other myriad of problems that come with i18n. Not easy, but simple.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You always need good design. If you find yourself with a pair of YAGNI blinders on, ignoring
design and code quality for purely YAGNI arguments, take a step back and remember that YAGNI ain’t
a design principle.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded></item><item><title><![CDATA[You're a Champion]]></title><description><![CDATA[Recently, my team embarked on a strategy/experiment designed to distribute the effort of driving
features from inception through completion…]]></description><link>http://ryanogles.by/youre-a-champion/</link><guid isPermaLink="false">http://ryanogles.by/youre-a-champion/</guid><pubDate>Sat, 23 Jan 2016 14:04:06 GMT</pubDate><content:encoded>&lt;p&gt;Recently, my team embarked on a strategy/experiment designed to distribute the effort of driving
features from inception through completion more evenly across the team. We noticed that both myself
(Tech Lead) and our BA were overloaded. Too many features. Too little time. What’s worse, our
developers were feeling out of the loop most of the time. They wanted more insight into what goes on
before a story gets to development and more say in the direction of the team.&lt;/p&gt;
&lt;p&gt;Thus, Feature Champions were born.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A Feature Champion is the champion of a feature throughout its entire lifecycle, naturally
becoming the knowledge expert in that feature.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A Champion can be anybody on the team, though we chose to limit our Champions to the developers and
QAs. It may sound like a lot of pressure, but that’s why the word champion is important. &lt;strong&gt;Champion
!= owner&lt;/strong&gt;. Championing is &lt;strong&gt;not&lt;/strong&gt; meant to introduce silos of knowledge or eliminate roles.
Championing does &lt;strong&gt;not&lt;/strong&gt; leave the champion alone to do the entire feature in isolation. Above all
else, the Champion is a collaborative role that works closely with other team members and
stakeholders.&lt;/p&gt;
&lt;p&gt;So, what does a feature champion actually do?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;engages with team/feature stakeholders to gather requirements and priority&lt;/li&gt;
&lt;li&gt;takes guidance from BAs/QAs to help with business and quality analysis&lt;/li&gt;
&lt;li&gt;works with the PM/IM to track the progress and scope of the feature&lt;/li&gt;
&lt;li&gt;participates in architecture and technical discussions with the tech lead or architects&lt;/li&gt;
&lt;li&gt;presents the feature to the team as the knowledge expert&lt;/li&gt;
&lt;li&gt;acts as a touch person for questions about the feature from other teams&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice the big thing that is not in this list: Does all the development on the feature themselves.
No! You are a Feature Champion, not a Feature Owner. You guide the feature throughout its wonderful
life, but rely heavily on support from the entire team along the way.&lt;/p&gt;
&lt;h2&gt;The Road Ahead&lt;/h2&gt;
&lt;p&gt;Some developers have taken to this exceptionally well - researching, scheduling meetings with
stakeholders, writing stories, and asking tons of questions. Others have struggled with the less
structured role. Championing some features involves much more than coming into work and writing code
all day. Learning new skills is always difficult. It has forced us to prioritize our work. Now, a
dev might be wearing many hats throughout the day, coding on a story for awhile, then doing analysis
for a feature for awhile.&lt;/p&gt;
&lt;p&gt;To outsiders looking in, it may seem like the team’s velocity would take a hit. While we have not
done this long enough to tell for sure, I don’t think this will happen in the long term. I see the
team ending up with more shared knowledge about the product, and more understanding of other roles.
So, when the BA or Tech Lead win the lottery, the rest of the team already has the experience to
step up and fill that gap.&lt;/p&gt;
&lt;p&gt;Finally, I see Feature Championing as being a great way to build up less experienced devs in a safe
way. They are learning what goes into analyzing a feature and interacting with non-technical
stakeholders. They are thinking at a higher level technically about architecture and system design.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Database Migrations Best Practices]]></title><description><![CDATA[Only once have I worked on a project that did not interact directly with a relational database.
(Awww, those were the days) In every other…]]></description><link>http://ryanogles.by/database-migrations-best-practices/</link><guid isPermaLink="false">http://ryanogles.by/database-migrations-best-practices/</guid><pubDate>Sat, 15 Aug 2015 15:53:23 GMT</pubDate><content:encoded>&lt;p&gt;Only once have I worked on a project that did not interact directly with a relational database.
(Awww, those were the days) In every other case, I used database migrations to apply small changes
to a database over time. Using migrations provides an incremental path towards building the current
state of a database. In my opinion it’s the only way to do it.&lt;/p&gt;
&lt;p&gt;Database migrations are nothing new, and over the years I have come to follow a few best practices:&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;1 Migration - 1 Change - 1 Commit&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Each migration should execute a single unit of work on the database.&lt;/strong&gt; This comes from the Agile
software development principle of introducing
&lt;a href=&quot;https://en.wikipedia.org/wiki/Agile_software_development#Iterative.2C_incremental_and_evolutionary&quot;&gt;small, incremental changes&lt;/a&gt;.
Small migrations are easier to read and understand.&lt;/p&gt;
&lt;p&gt;For example, if I need to create a customers table and accounts table, I would create one migration
to create the customers table and a second migration to create the accounts table. Two migrations.
Two commits.&lt;/p&gt;
&lt;p&gt;By keeping each migration contained in its own commit, it is easy for automated build systems to
apply them 1-by-1 in later environments. And if a migration turns out to be malformed, you make it
easy to revert just that change if necessary.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I always try to commit a migration with no code changes attached.&lt;/em&gt; This isolation ensures that the
migration is fully compatible with the application code both before and after it. Your Database
Administrators will also thank you for making it easier to notice the migration when its all by
itself.&lt;/p&gt;
&lt;h2&gt;Never modify a previously committed migration&lt;/h2&gt;
&lt;p&gt;(This is the one that seems to be unintuitive for less experienced developers.)&lt;/p&gt;
&lt;p&gt;Once a commit has left my local machine, it is effectively locked! If I notice afterwards that there
is a typo in a column name or some other mistake, I create another migration that fixes it rather
than modifying the bad one.&lt;/p&gt;
&lt;p&gt;Why? Imagine this interaction between 2 developers, Patrick and Molly:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Patrick&lt;/th&gt;
      &lt;th&gt;Molly&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1. Patrick commits migration #8, which creates a table with a column &quot;product_typ&quot; (misspelled it, oops)&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;2. Molly pulls new code and applies migrations, which gives her the new table with the misspelled column name&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3. Patrick realizes his mistake, so he rolls back migration #8 locally, dropping the table. He then modifies the migration to fix the typo, then applies migration #8 again.&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4. Patrick pushes his changes.&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;5. Molly pulls new code and applies migrations again. But this time no change is made to her database because she already applied migration #8 and no new migrations were added. She is stuck with the typo. :(&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td colspan=&quot;2&quot; class=&quot;center&quot;&gt;6. Patrick&apos;s and Molly&apos;s database schemas are now out of sync.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The only way Molly can fix her database now is to drop it and start over. Depending on the migration
and what was changed, she may not be able to rollback for a quick fix. Want a scarier scenario? What
if Molly was actually the production database… Oops indeed.&lt;/p&gt;
&lt;p&gt;Save yourself the pain. Just don’t do it.&lt;/p&gt;
&lt;h2&gt;Avoid using your application code (such as models) in migrations&lt;/h2&gt;
&lt;p&gt;Some migration tools allow you to use application code in your migration files, especially if you
are using the ActiveRecord pattern
&lt;a href=&quot;http://guides.rubyonrails.org/v3.2.8/migrations.html#using-models-in-your-migrations&quot;&gt;(I’m looking at you Rails)&lt;/a&gt;.
The use case for this could be an easy way to do some data manipulation, or inserting seed data.&lt;/p&gt;
&lt;p&gt;I avoid doing this because you cannot guarantee that your code will keep the same API forever. Even
the first migration could be run at any point in the future (say a new dev joins and runs them all
for the first time), you can’t assume those same methods could be called. (And I don’t change
previously run migrations)&lt;/p&gt;
&lt;p&gt;P.S. Rails 4 no longer even mentions this as an option. The link above from Rails Guides actually
warns against this practice too. :)&lt;/p&gt;
&lt;h2&gt;Keep migrations abstract&lt;/h2&gt;
&lt;p&gt;Try not to use database-specific operations. This couples you to that database technology. Most
migration tools/frameworks attempt to abstract the database away for you, so by using
database-specific concepts or operations, you break that abstraction layer.&lt;/p&gt;
&lt;p&gt;However, this rule is often broken since each database speaks its own version of SQL.&lt;/p&gt;
&lt;h2&gt;Think about the data&lt;/h2&gt;
&lt;p&gt;I often see developers overlooking the data stored in their databases. Migrations don’t just effect
the schema, they also effect the stored data - a thats the important part! This happens a lot
because our local development databases may not have very production-like data.&lt;/p&gt;
&lt;p&gt;Example: Consider a migration that applies a not null constraint to a column.&lt;/p&gt;
&lt;table class=&quot;blog-table even&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Local DB&lt;/th&gt;
      &lt;th&gt;Production DB&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
employees
&lt;pre&gt;
id | name       | phone_number
---------------------------
1 | foo         | 5555555555
2 | l33t haxor  | 1234567890
&lt;/pre&gt;
      &lt;/td&gt;
      &lt;td&gt;
employees
&lt;pre&gt;
id | name   | phone_number
---------------------------
1 | Patrick | 5554567890
2 | Molly   | null
&lt;/pre&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ALTER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; employees &lt;span class=&quot;token keyword&quot;&gt;MODIFY&lt;/span&gt; phone_number &lt;span class=&quot;token keyword&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This migration would be fine in development, but that migration would fail in prod. A better
migration would actually be 3 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Insert a value into every row where &lt;code class=&quot;language-text&quot;&gt;phone_number&lt;/code&gt; is currently null&lt;/li&gt;
&lt;li&gt;Add a default value for future inserts (if applicable)&lt;/li&gt;
&lt;li&gt;Introduce the not null constraint.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Consider changing a column’s data type from a floating point precision to an integer. Maybe you are
converting your money column to be stored as cents so you can avoid floating point mathematical
errors. What would happen to the precision when the migration is applied? Would the database
truncate it? Round it? Something else?&lt;/p&gt;
&lt;p&gt;A more pragmatic approach may actually require many steps: introduce another column
&lt;code class=&quot;language-text&quot;&gt;amount_in_cents&lt;/code&gt;; move all the current data to the new column and perform the format change; drop
the &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt; column; finally, rename the &lt;code class=&quot;language-text&quot;&gt;amount_in_cents&lt;/code&gt; column to &lt;code class=&quot;language-text&quot;&gt;amount&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These are only two scenarios I’ve seen lately, but there are many more.&lt;/p&gt;
&lt;h2&gt;Moar&lt;/h2&gt;
&lt;p&gt;Check out &lt;a href=&quot;http://databaserefactoring.com/&quot;&gt;Database Refactoring&lt;/a&gt; for a lot of good database
refactoring patterns.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hackathons for the Enterprise]]></title><description><![CDATA[A few months ago I helped to plan and execute a Hackathon for my project team. Though it was not the
first team Hackathon I have…]]></description><link>http://ryanogles.by/hackathons-for-the-enterprise/</link><guid isPermaLink="false">http://ryanogles.by/hackathons-for-the-enterprise/</guid><pubDate>Sun, 26 Jul 2015 10:30:04 GMT</pubDate><content:encoded>&lt;p&gt;A few months ago I helped to plan and execute a Hackathon for my project team. Though it was not the
first team Hackathon I have participated in, it was the most successful. Everyone on the team had a
great time and learned a lot. Some of the hacks have even been turned into production solutions for
the product or team!&lt;/p&gt;
&lt;p&gt;I decided to take this experience and share it with a wide audience by contributing to the
&lt;a href=&quot;http://www.thoughtworks.com/insights&quot;&gt;ThoughtWorks Insights&lt;/a&gt; blog. This is extremely exciting for
me, as its my first time to be featured alongside so many of my brilliant colleagues! :)&lt;/p&gt;
&lt;p&gt;Check out my article &lt;a href=&quot;http://www.thoughtworks.com/insights/blog/hackathons-enterprise&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Watching the Watchers in AngularJS]]></title><description><![CDATA[I have been doing quite a bit of AngularJS performance tweaking on my latest project. It is no
secret that Angular performance can quickly…]]></description><link>http://ryanogles.by/watching-the-watchers-in-angularjs/</link><guid isPermaLink="false">http://ryanogles.by/watching-the-watchers-in-angularjs/</guid><pubDate>Tue, 07 Apr 2015 08:43:55 GMT</pubDate><content:encoded>&lt;p&gt;I have been doing quite a bit of AngularJS performance tweaking on my latest project. It is no
secret that Angular performance can quickly degrade due to the implementation of its
&lt;a href=&quot;https://docs.angularjs.org/guide/scope&quot;&gt;digest cycle&lt;/a&gt;. I’ll avoid Angular bashing here because this
is well-documented and blogged about to death (Google it). You’re welcome.&lt;/p&gt;
&lt;p&gt;Instead, I want to share a few learnings that I have picked up while attacking the performance
problems with having too many bindings and watchers in any Angular application.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Should I even be worried?&lt;/h2&gt;
&lt;p&gt;The first step is actually knowing if you have a problem. Eventually, on my project, we could feel
the responsiveness of our application start to slip. Rendering seemed to slow down. Interactions
started to feel sluggish. You would click a toggle, it would wait a tick, and then change states.
Things like that. Even if you aren’t noticing anything this drastic, its still a good idea to get
some insight and follow best practices though.&lt;/p&gt;
&lt;p&gt;In order to help pinpoint the hotspots in your Angular app, I developed this
&lt;a href=&quot;https://chrome.google.com/webstore/detail/angularjs-inspect-watcher/gdfcinoagafkodbnkjemaajfahnmfkhg&quot;&gt;Chrome extension&lt;/a&gt;
to count how many watchers different sections of your app contain.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://docs.angularjs.org/guide/expression#one-time-binding&quot;&gt;Bind once&lt;/a&gt; is your friend&lt;/h2&gt;
&lt;p&gt;This one is the easiest and has a big ROI. When using the normal binding syntax
&lt;code class=&quot;language-text&quot;&gt;{{ &amp;lt;expression&amp;gt; }}&lt;/code&gt;, Angular sets up a two-way binding so that the view can be automatically upated
when the underlying data changes. However, there are probably some static data in your app, which
makes the two-way binding both redundant and costly because Angular re-evaluates that expression
during every digest cycle to update your view with any changes. The bind once syntax eliminates
that. Quick win.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{{ ::item.name }}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;em&gt;Note: only available in Angular 1.3 and later&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Avoid excess use of ng-show/ng-hide&lt;/h2&gt;
&lt;p&gt;These directives are easy to abuse. When you have multiple elements that need to be hidden or shown
based on similar conditions, you can often combine multiple &lt;code class=&quot;language-text&quot;&gt;ng-show/ng-hides&lt;/code&gt; into a single
&lt;code class=&quot;language-text&quot;&gt;ng-class&lt;/code&gt; and sprinkle in some targetted CSS rules to achieve the same behavior with fewer
watchers.&lt;/p&gt;
&lt;p&gt;So this, which contains 3 &lt;code class=&quot;language-text&quot;&gt;ng-show/ng-hide&lt;/code&gt; watchers…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-hide&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.isSoldOut()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Price: $49.99&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-show&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.isSoldOut()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Not in Stock&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ ::item.name }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-hide&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.isSoldOut()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    Ships within 3-5 business days
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Can be turned into this, which contains 1 watcher - the &lt;code class=&quot;language-text&quot;&gt;ng-class&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-css item.css&quot;&gt;&lt;code class=&quot;language-css item.css&quot;&gt;.item .show-when-sold-out {
  display: none;
}

.item.sold-out .show-when-sold-out {
  display: block;
}
.item.sold-out .hide-when-sold-out {
  display: none;
}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{sold-out: item.isSoldOut()}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hide-when-sold-out&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Price: $49.99&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;show-when-sold-out&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Not in Stock&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ ::item.name }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hide-when-sold-out&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    Ships within 3-5 business days
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;Beware the ng-repeat&lt;/h2&gt;
&lt;p&gt;A = How many watchers does each element of your &lt;code class=&quot;language-text&quot;&gt;ng-repeat&lt;/code&gt; contain?&lt;br/&gt; B = How many elements will
you be iterating over?&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;if(A * B &amp;gt; 3000) { console.log(&amp;quot;Houston we have a problem&amp;quot;); }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On my current project, we were blindly using &lt;code class=&quot;language-text&quot;&gt;ng-repeat&lt;/code&gt; on elements that contained over 50 watchers
each. This was fine for some users who only had a few items in the list. But when we hit some users
who loaded over 400 elements into that list, (50 * 400 = 20,000), our digest cycle slowed to a
crawl and we even crashed the browser sometimes. (Especially mobile browesers.) Oops.&lt;/p&gt;
&lt;p&gt;Besides using the other tips listed on this page to reduce the overall number of watchers, my advice
is to think about the user experience of your app. Do you really need to render all those elements
in one big list? Enter pagination. Enter filtering and searching.&lt;/p&gt;
&lt;p&gt;We went with a hand-rolled pagination solution because the available plugins didn’t quite fit our
needs.&lt;/p&gt;
&lt;h2&gt;Lazy evaluation of DOM elements&lt;/h2&gt;
&lt;p&gt;Take this example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-header&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{{ ::item.name }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.expand()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-info&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-show&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.isExpanded()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ item.description }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-submit&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.addComment(comment)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-model&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comment&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- More bindings and watchers --&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Even though the elements in &lt;code class=&quot;language-text&quot;&gt;div.item-info&lt;/code&gt; are hidden, the watchers and bindings on those elements
will still be evaluated by Angular during the digest cycles. There is actually no point in compiling
and linking all the DOM elements in the hidden &lt;code class=&quot;language-text&quot;&gt;div.item-info&lt;/code&gt; section until the user actually
clicks the expansion trigger. We found that we could get a huge performance boost by taking
advantage of templates and changing the structure of our HTML a bit. So when the user clicks on the
expansion trigger, we grab the appropriate template, compile and link it with the data, and insert
that into the DOM!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-header&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ ::item.name }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item.expand()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item-info&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/ng-template&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;expandedItem.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;description &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;form ng&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;submit&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;item.addComment(comment)&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt; ng&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;model&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;comment&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt; More bindings and watchers &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The one caveat here is that once the user has expanded the item, all the watchers and bindings from
the expanded item are now part of the digest cycle. The more elements you expand, the more watchers
you end up with. This worked on my application because we expect the user to only expand a few
elements out of a long list - a big savings. If you expect the user to quickly show all the elements
you were initially hiding, this may not help much. In any case, it should at least help with initial
page load time because the &lt;code class=&quot;language-text&quot;&gt;ng-templates&lt;/code&gt; are not compiled until you explicity tell Angular to.&lt;/p&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;I read a lot of blog articles and documentation while messing around with all of this. One that I
found particularly useful was &lt;a href=&quot;http://ng.malsup.com/&quot;&gt;Ng Nuggets&lt;/a&gt;. Thanks!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Easing into Rubocop with git]]></title><description><![CDATA[Dropping Rubocop into an existing codebase We (my team) recently introduced  rubocop  to a Rails app and a
Sinatra app to encourage (aka…]]></description><link>http://ryanogles.by/easing-into-rubocop-with-git/</link><guid isPermaLink="false">http://ryanogles.by/easing-into-rubocop-with-git/</guid><pubDate>Wed, 25 Feb 2015 20:08:31 GMT</pubDate><content:encoded>&lt;h2&gt;Dropping Rubocop into an existing codebase&lt;/h2&gt;
&lt;p&gt;We (my team) recently introduced &lt;a href=&quot;https://github.com/bbatsov/rubocop&quot;&gt;rubocop&lt;/a&gt; to a Rails app and a
Sinatra app to encourage (aka enforce) us to follow established Ruby style and semantics. This was
my first experience with dropping a static code analyzer into an established codebase. Just for
reference, our Rails app is not huge - 16 controllers, 25 models, 10 services, and a smattering of
other files.&lt;/p&gt;
&lt;p&gt;Even so, the first run of &lt;code class=&quot;language-text&quot;&gt;bundle exec rubocop&lt;/code&gt; on the entire application revealed about 2,500
warnings. Whomp whomp. Thankfully, Rubocop comes with a handy-dandy autocorrect feature. A quick
&lt;code class=&quot;language-text&quot;&gt;bundle exec rubocop --auto-correct&lt;/code&gt; fixed almost half of them. Good, but not quite there yet.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Incremental Rubocoping&lt;/h2&gt;
&lt;p&gt;We wanted to Rubocop to execute as part of our pre-commit task, and we wanted it to fail the task if
it produced warnings or errors. So, our options were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Have someone sit down with a case or two of Red Bull and don’t stop until everything is fixed.&lt;/li&gt;
&lt;li&gt;Use the “Automatically Generated Configuration” from Rubocop, which generates a config file for
you from all the warnings with all those cops turned off, letting you choose when to enable them.&lt;/li&gt;
&lt;li&gt;Configure Rubocop to only run on a subset of files or directories. Fix all those warnings before
adding more files, rinse and repeat until the entire app is added.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We went with… kind of 3. We liked the idea of incrementally rubocop-ing our app as we worked on
it. So our solution is based on the
&lt;a href=&quot;http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule&quot;&gt;Boy Scout Rule&lt;/a&gt; - strive
to always leave any code you touch in a better state than when you found it. Applying that to
Rubocop means every time you commit, Rubocop gets run ONLY on the files you have touched in that
commit. Over time, we should cover more and more of the app until eventually we can run Rubocop on
the entire app with every commit! Boom!&lt;/p&gt;
&lt;p&gt;The one caveat is that you must remember to run the task BEFORE you do &lt;code class=&quot;language-text&quot;&gt;git commit&lt;/code&gt; in order for the
task to pick up your changed files. I’m sure we could put in some more effort to account for that,
but haven’t done so yet.&lt;/p&gt;
&lt;h2&gt;The Gist of it&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;embed:easing-into-rubocop-with-git/git_rubocop.ruby&lt;/code&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Support Apprentices on an Agile Development Team]]></title><description><![CDATA[Recently, my team was tasked with figuring out how to introduce what we chose to call “Apprentice
Developers” into the team in order to help…]]></description><link>http://ryanogles.by/how-to-support-apprentices-on-an-agile-development-team/</link><guid isPermaLink="false">http://ryanogles.by/how-to-support-apprentices-on-an-agile-development-team/</guid><pubDate>Mon, 26 Jan 2015 19:39:06 GMT</pubDate><content:encoded>&lt;p&gt;Recently, my team was tasked with figuring out how to introduce what we chose to call “Apprentice
Developers” into the team in order to help on board new talent into the company. How would our
day-to-day interactions and development practices have to change in order for less experienced team
members to grow while being productive? I was pretty excited about this initiative, as I enjoy
mentoring others to become better software developers and being part of effective, high-performing
teams.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Our definition for Apprentice Developer: &lt;br /&gt; Entry-level Dev. Probably none or less than a year
of full-time professional experience in software development.&lt;/p&gt;
&lt;p&gt;First some background, in the past few months we have been supporting a couple Apprentice-level
developers with various amounts of success. Until now, the development team had been a bit loose in
adhering to XP practices, such as pairing. Sometimes we would, sometimes we wouldn’t. Sometimes we
would switch pairs every day or so, but there was no real cadence to it. Being a small agile team (7
devs), this kind of thing was fine for awhile, but we could easily see that adding more
less-experienced devs would require a tad more structured of an environment.&lt;/p&gt;
&lt;p&gt;Our first step was to take on honest look at our dev team culture and how everyone was responding to
it. We discussed the worries that the team had and we solicited feedback from the current Apprentice
developers centered around how the team had supported them, and what areas there might be for
improvement.&lt;/p&gt;
&lt;p&gt;We came to the conclusion that we would identify five new development practices that promote a more
supportive and safe environment for Apprentice-level developers. So we carved out about two hours to
come up with them, which I facilitated. To start things off, we narrowed our focus just a bit by
creating a few categories that we thought would have challenges from the initial group discussion
notes and feedback. From here, we took about five minutes to do some divergent thinking and come up
with as many ideas as we could for addressing anything in any of the categories. After reviewing,
clarifying, and grouping similar ideas, we each used five votes to start converging on the ones that
we wanted to take further. It looked like this.&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-9b0e7.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 119.16666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAIBAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAfbvC8NJLzsjQP8A/8QAGhAAAgMBAQAAAAAAAAAAAAAAAAECEBESE//aAAgBAQABBQLRnnCujZCeir//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAZEAABBQAAAAAAAAAAAAAAAAAQABEgMTL/2gAIAQEABj8CGEwuH//EABsQAQADAAMBAAAAAAAAAAAAAAEAESExQWFx/9oACAEBAAE/IbYNK91EAX3AzQxeVtwW8geSzTHyULJ65lz/2gAMAwEAAgADAAAAEAzAQP/EABgRAAIDAAAAAAAAAAAAAAAAAAAQESFB/9oACAEDAQE/EKwh/wD/xAAZEQEAAgMAAAAAAAAAAAAAAAAAASERUYH/2gAIAQIBAT8Qzt1KKp//xAAdEAEAAwEAAgMAAAAAAAAAAAABABEhMUFxUWGh/9oACAEBAAE/EL7SH3nupbCtXZle5uC+eQ1U0Nh2GqABj1n7FSEWg8QD7VZE1eFrUx5n/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Dev team practices brainstorm&quot;
        title=&quot;&quot;
        src=&quot;/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-f8fb9.jpg&quot;
        srcset=&quot;/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-e8976.jpg 148w,
/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-63df2.jpg 295w,
/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-f8fb9.jpg 590w,
/static/dev_practices_brainstorming-13db928f4cafe63a953a6a3622efe2ec-9b0e7.jpg 600w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;Next, we discussed the ideas one-by-one in descending order of votes, with the outcome of each
discussion being a tangible, immediately-implementable practice for the team. Here is what we came
up with:&lt;/p&gt;
&lt;p&gt;
  &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-9b0e7.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
  
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 590px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 93.16666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAeoyxl1sqqhIA//EABcQAQEBAQAAAAAAAAAAAAAAAAAREiD/2gAIAQEAAQUC00qqvH//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAUEAEAAAAAAAAAAAAAAAAAAAAw/9oACAEBAAY/Ah//xAAaEAABBQEAAAAAAAAAAAAAAAAAARARICFB/9oACAEBAAE/IWd9FMq//9oADAMBAAIAAwAAABAo4H7/xAAVEQEBAAAAAAAAAAAAAAAAAAARIP/aAAgBAwEBPxBj/8QAFREBAQAAAAAAAAAAAAAAAAAAESD/2gAIAQIBAT8QI//EABsQAQEAAwADAAAAAAAAAAAAAAEAESExEEFx/9oACAEBAAE/EB9XBGvfu7skTU5YR7ZZ8f/Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Five new dev team practices&quot;
        title=&quot;&quot;
        src=&quot;/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-f8fb9.jpg&quot;
        srcset=&quot;/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-e8976.jpg 148w,
/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-63df2.jpg 295w,
/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-f8fb9.jpg 590w,
/static/five_dev_practices-88b89320d06535c6e9f5f14d0c0bab33-9b0e7.jpg 600w&quot;
        sizes=&quot;(max-width: 590px) 100vw, 590px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  
  &lt;/a&gt;
    &lt;/p&gt;
&lt;p&gt;As facilitator, the most obvious feedback for myself is that I was not an impartial outside
facilitator. I had my own ideas and biases. Though I consciously tried not to let them interfere
with any discussions, I’m sure that happened a little bit. That is probably unavoidable and a big
reason why an outside facilitator for exercises such as this one is preferable.&lt;/p&gt;
&lt;p&gt;I also could have watched the time a little better. It took over 2 hours, which I feel was way long.
We got off track quite a few times. And the discussions after voting may have been a bit too open
ended. Looking back, having a set time box for each post-vote discussion may have provided just
enough time pressure to spur the group to create something tangible a bit quicker.&lt;/p&gt;
&lt;p&gt;At the end of it all though, the team agreed upon five new practices to enact right away. The
underlying goal was to help support new Apprentice developers, but I think the entire team,
regardless of experience or skill level, will benefit from them. I’m looking forward to seeing how
it goes and how the team grows!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Testing JavaScript Web Workers with Jasmine]]></title><description><![CDATA[JavaScript
 Web Workers  have
been around for awhile now, but I had not needed them until recently. Without going into too much
domain…]]></description><link>http://ryanogles.by/testing-jasvascript-web-workers-with-jasmine/</link><guid isPermaLink="false">http://ryanogles.by/testing-jasvascript-web-workers-with-jasmine/</guid><pubDate>Fri, 29 Aug 2014 15:48:00 GMT</pubDate><content:encoded>&lt;p&gt;JavaScript
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers&quot;&gt;Web Workers&lt;/a&gt; have
been around for awhile now, but I had not needed them until recently. Without going into too much
domain specific info about the actual use case, I decided to go with Web Workers to handle map
reduce style statistic calculations on a data set in the browser.&lt;/p&gt;
&lt;p&gt;I was stoked to find the Web Worker API small and straightforward, making it super easy to get up
and running. The only real speed bump while getting started was the lack of support in older
browsers (IE8 and IE9 you ruin everything). However, turns out there is already a polyfill that
works great. :) &lt;a href=&quot;https://code.google.com/p/ie-web-worker/&quot;&gt;https://code.google.com/p/ie-web-worker/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I am a big proponent of testing my code. After some Googling, I didn’t find anything talking about
testing JavaScript Web Workers, hence, this article.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;First Attempt:&lt;/h2&gt;
&lt;p&gt;A long running background worker would be difficult to properly unit test, but my case was a bit
simpler. I was posting data to the worker and letting it spit a result back out. I decided to just
try the simplest &lt;a href=&quot;http://jasmine.github.io/&quot;&gt;Jasmine&lt;/a&gt; test first:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: This is just an example with a similar structure as my actual app.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sum_foo.js&lt;/span&gt;

&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; array &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sum_foo_spec.js&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sums the values of foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum_foo.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Surprising to me, this didn’t work! :( The test seemed to pass, but there was a Jasmine error.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Uncaught TypeError: Cannot read property &amp;#39;expect&amp;#39; of null&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;What seemed to be going on is that, since this is an asynchronous test, by the time the execution of
the test reached the expectation, the jasmine environment was no longer valid or able to perform the
assertion.&lt;/p&gt;
&lt;h2&gt;UPDATE:&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;So in the process of writing this I discovered a more correct solution to my problem, which I have
included here. But I decided to keep around the whole post because of the Rails intricacies and my
overall problem solving thought process.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Turns out that Jasmine already has support for these type of asynchronous operations with the use of
a &lt;code class=&quot;language-text&quot;&gt;done()&lt;/code&gt; function, that Jasmine will use to know when an asynchronous test has finished.
&lt;a href=&quot;http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support&quot;&gt;http://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sum_foo.js_spec&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sums the values of foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;done&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum_foo.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This is the solution I will be going with, but if you keep reading you will see something I came up
with that uses promises to place the assertion AFTER “postMessage,” which I find easier to read and
reason about when doing asynchronous tests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lesson learned here: always read the documentation fully and upgrade if you can first.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Second Attempt:&lt;/h2&gt;
&lt;p&gt;Time to be clever. Since my goal was to test the Web Worker code itself, I decided to reverse
engineer the Web Worker API. I realized that the Worker was making an XMLHttpRequest to grab the
script and then executing the code in its own context, so I took a similar strategy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sum_foo_spec.js&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sums the values of foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; http &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;sum_foo.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; workerCode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;responseText

  &lt;span class=&quot;token comment&quot;&gt;// This will define the worker&apos;s &quot;onmessage&quot; function in the context of this test&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workerCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Callback when the worker has done its work&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Execute the action under test&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;onmessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;h2&gt;Improvements:&lt;/h2&gt;
&lt;p&gt;Now that I had a working solution, I had to write more tests for more workers (so far my app has 14
workers and maybe more to come), which means reusability. I wanted to extract away all the hairiness
of requesting the worker script and evaling it into the current context. I also don’t like writing
the expectation before the action of the test, so I turned to promises to help out.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: using jQuery’s Deferred here as my promise library because I already have jQuery in the
project.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// worker_helper.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getWorker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  http &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;responseText
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;workerTester&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workerCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; deferred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Deferred&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Define onmessage from the worker&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workerCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// The worker will call this method with the post-back data&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;thenAssertOn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;assertion&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;assertion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;sendMessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Call into the worker code&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;onmessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; data &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; thenAssertOn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; thenAssertOn &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sendMessage&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sendMessage &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// sum_foo_spec.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; workerCode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getWorker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum_foo.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sums the values of foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;workerTester&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workerCode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; foo&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;thenAssertOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sum&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Bingo! I was pretty happy with the final solution. It made testing of the rest of the workers
trivial. And it works both in the browser and in a headless environment such as phantomjs.&lt;/p&gt;
&lt;h2&gt;Rails Setup:&lt;/h2&gt;
&lt;p&gt;I am using Rails 4 on the backend for this, which actually took a bit of time to get everything set
up to work correctly in a Rails pipeline. Here is what I’ve done.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;All workers are in a separate folder: “app/assets/javascripts/workers”&lt;/li&gt;
&lt;li&gt;“application.js” does &lt;em&gt;NOT&lt;/em&gt; require the workers. As I alluded to, when instantiating a worker
with &lt;code class=&quot;language-text&quot;&gt;new Worker(‘script_name.js’)&lt;/code&gt;, an AJAX request is made to the server to fetch the resource,
so compiling it into application.js isn’t necessary&lt;/li&gt;
&lt;li&gt;Add all workers to the precompile array:
&lt;code class=&quot;language-text&quot;&gt;config.assets.precompile += Dir.chdir(File.join(Rails.root, &amp;#39;app/assets/javascripts&amp;#39;)) { Dir[&amp;#39;workers/*.js&amp;#39;] }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Instantiate workers using inline JavaScript in application.html:
&lt;code class=&quot;language-text&quot;&gt;new Worker(&amp;#39;#{javascript_path(&amp;quot;workers/script_name.js&amp;quot;)}&amp;#39;);&lt;/code&gt; &lt;em&gt;Notice the use of
`javascript&lt;/em&gt;path`. The workers are being precompiled by the asset pipeline and will need the MD5
checksum._&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The final issue was with &lt;a href=&quot;https://github.com/searls/jasmine-rails&quot;&gt;jasmine_rails&lt;/a&gt;. Running
&lt;code class=&quot;language-text&quot;&gt;rake spec:javascript&lt;/code&gt; worked fine, but when running &lt;code class=&quot;language-text&quot;&gt;RAILS_ENV=test rake spec:javascript&lt;/code&gt;, the
worker scripts were not able to be fetched and thus a lot of tests failed. When jasmine rails runs,
it copies all the files it needs into its own temp directory (tmp/jasmine by default). I ended up
figuring out that running the jasmine specs in the TEST environment causes the src and spec files
you specified in your jasmine.yml to be concatenated into a single jasmine-specs.js file, copied
into tmp/jasmine, and included in the jasmine runner.html file. This meant the workers were not
available to be fetched via AJAX. The solution I found is to use a custom spec runner layout file
that manually includes the workers. This causes them to be copied into tmp/jasmine along with the
concatenated jasmine-specs.js file, and available for fetching by the Web Worker.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-haml&quot;&gt;&lt;code class=&quot;language-haml&quot;&gt;&lt;span class=&quot;token multiline-comment comment&quot;&gt;// app/views/layouts/jasmine_rails/spec_runner.html.haml&lt;/span&gt;

&lt;span class=&quot;token doctype&quot;&gt;!!!&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;%html&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;%head&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;%meta&lt;span class=&quot;token attributes&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;text/html;charset=UTF-8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;http-equiv&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;%title&lt;/span&gt;
      Jasmine Specs

    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; stylesheet_link_tag &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;jasmine_css_files&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;%body&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;#jasmine_content&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; javascript_include_tag &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;jasmine_js_files&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; javascript_include_tag &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;chdir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;app/assets/javascripts&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;workers/*.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;(&lt;a href=&quot;https://github.com/searls/jasmine-rails#custom-helpers&quot;&gt;https://github.com/searls/jasmine-rails#custom-helpers&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;So a few hoops to jump through, but now I’m very happy with the Web Workers and the testing strategy
I arrived at.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GOTO Chicago 2014 Experience Report]]></title><description><![CDATA[I had the privilege of attending  Goto;con 2014  in Chicago. It
was smaller than I anticipated, spread over just a few conference rooms in a…]]></description><link>http://ryanogles.by/goto-chicago-2014-experience-report/</link><guid isPermaLink="false">http://ryanogles.by/goto-chicago-2014-experience-report/</guid><pubDate>Mon, 26 May 2014 13:31:00 GMT</pubDate><content:encoded>&lt;p&gt;I had the privilege of attending &lt;a href=&quot;http://gotocon.com/chicago-2014/&quot;&gt;Goto;con 2014&lt;/a&gt; in Chicago. It
was smaller than I anticipated, spread over just a few conference rooms in a small corner of the
Drake Hotel, with no more than 400 attendees. This gave the conference a fairly informal, casual
vibe. The talks were spread over a variety of tracks, from distributed systems to UX to functional
programming languages, which kept things fresh over the 2 day conference.&lt;/p&gt;
&lt;p&gt;Here I will capture summaries and my key takeaways from some of the sessions I attended (which
represents only a small fraction of the 40+ presentations).&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Camille Fournier: So You Want to Rewrite That…&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Head of Engineering, Rent the Runway&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Camille extrapolated some lessons from a successful rewrite of PHP Drupal system to a more modular
platform built on a Ruby frontend with supporting Java microservices. Two of her main suggestions in
order to make a rewrite sustainable were to 1. change as little as possible, and 2. to change only
one thing at a time. Keep it small and incremental. She went on to discuss how to sell a rewrite to
the business by making it clear what “done” will look like for the stakeholders. She also mentioned
potential pitfalls, such as a version 2 that tries to do everything because of too many additional
features being added during the rewrite. There is also the worry of over engineering. And if the
team does not have a good idea of what done means, you could end up never really getting there.&lt;/p&gt;
&lt;p&gt;Her overall message was that a rewrite can be successful, and to make that happen you should make
incremental changes that provide value.&lt;/p&gt;
&lt;h2&gt;Reid Draper: Forty Years of Pretending&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Profesional Erlang Developer, Works on Riak&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Reid spoke about the recent resurgence of RPC-style architectures in JavaScript heavy web apps. At
first I did not quite buy it, was he saying we are going back towards RPC? No way! But he ended up
connecting the dots in the end.&lt;/p&gt;
&lt;p&gt;He reminded us of some of the glaring problems with RPC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is difficult to keep consistent code on every node. If you need to update code, then you have
to update it everywhere. Think of JS on clients as the nodes. You don’t control which version of
the JS the client has. With JS on browsers, how to you deliver updated code? Do you force users to
reload the page?&lt;/li&gt;
&lt;li&gt;How do you handle failure? HTTP is inherently unstable.&lt;/li&gt;
&lt;li&gt;How do you serialize complex objects such as DB connection objects?&lt;/li&gt;
&lt;li&gt;Streaming&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;He went on to talk about how, since we can write JS on the front end and back end now, we may be
tempted to use this RPC-style architecture and run the same code on both ends. He briefly noted a
few JS-RPC libraries and advised against using them, since we already know the shortcomings of this
approach.&lt;/p&gt;
&lt;p&gt;He then walked through the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing&quot;&gt;Fallacies of Distributed Computing&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The network is reliable&lt;/li&gt;
&lt;li&gt;Latency is zero&lt;/li&gt;
&lt;li&gt;Bandwidth is infinite&lt;/li&gt;
&lt;li&gt;The network is secure&lt;/li&gt;
&lt;li&gt;The network topology does not change&lt;/li&gt;
&lt;li&gt;There is a single network admin&lt;/li&gt;
&lt;li&gt;Transport cost is 0&lt;/li&gt;
&lt;li&gt;The network is homogeneous&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have been kind of unconsciously aware of these while developing web and mobile applications, but
it was awesome to make them really explicit. He used them to stress the difficulties in developing
JS web apps and brought up a great final point.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Even a simple web app is a distributed system”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Michael Nygard: Five Years of DevOps: Where are we Now?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Author of “Release It!”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It was pretty great to hear a talk about DevOps from Michael Nygard. He started with the basics and
growth of DevOps, including CAMS (Culture, Automation, Measurement, Sharing). He made a good point
by applying Donella Meadows’
&lt;a href=&quot;http://www.donellameadows.org/archives/leverage-points-places-to-intervene-in-a-system/&quot;&gt;“Leverage Points in a System”&lt;/a&gt;
to DevOps, and how the best place to affect an organization with DevOps comes at the information
flow level and goals of the organization. Eventually, he outlined that DevOps over the past few
years has come to mean:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CAMS + human factors + Agile values + Continuous Delivery = DevOps&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really enjoyed his scorecard of where we are currently at with DevOps:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Category&lt;/th&gt;&lt;th&gt;Score&lt;/th&gt;&lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Deployments&lt;/td&gt;&lt;td&gt;A&lt;/td&gt;&lt;td&gt;Most deployment tech right now targets a single machine, not a cluster&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Provisioning&lt;/td&gt;&lt;td&gt;B&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Logging&lt;/td&gt;&lt;td&gt;A+&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Monitoring&lt;/td&gt;&lt;td&gt;A+&lt;/td&gt;&lt;td&gt;Graph all the the things!&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Anomaly Detection&lt;/td&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;System Comprehension&lt;/td&gt;&lt;td&gt;D+&lt;/td&gt;&lt;td&gt;We are not very good at connecting a machine being down to the implications on the rest of the system and to the bottom line of the organization&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Going forward, some more things to expect in this space:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More focus on &lt;em&gt;anti-fragility&lt;/em&gt; - systems that improve from randomness. He used the
&lt;a href=&quot;https://github.com/Netflix/SimianArmy&quot;&gt;Symian Army&lt;/a&gt; from Netflix as a current example.&lt;/li&gt;
&lt;li&gt;A culture shift to viewing development infrastructure as mission critical. “Development is
Production”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, some cautions: Michael thinks DevOps is at the top of the “innovative technology adoption
curve” right now.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://s9.postimg.org/8unpmxe2n/Technology_Adoption_Curve.png&quot; alt=&quot;Innovative technology adoption curve&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is a market penetration and DevOps is the most popular one at the party. He warned against
trying to emulate practices without adopting the DevOps culture though. There is no such thing as
DevOps-in-a-box. Having a separate DevOps team is also an anti-pattern.&lt;/p&gt;
&lt;h2&gt;Martin Odersky: Scala - The Simple Parts&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Creator of Scala, Co-founder and Chairman of Typesafe&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Martin basically wanted to address some bad rap Scala has gotten lately about it being overly
complex and huge (I think so too). He called it a growable and modular language. It is growable in
the sense that it is easy to build a DSL on top to expand its capabilities (such as
&lt;a href=&quot;http://spark.apache.org/&quot;&gt;Spark&lt;/a&gt;, &lt;a href=&quot;https://chisel.eecs.berkeley.edu/&quot;&gt;Chisel&lt;/a&gt;,
&lt;a href=&quot;http://akka.io/&quot;&gt;Akka&lt;/a&gt;, etc). It is a language for growth - you can start fast, with a 1-liner
program. You can experiment fast. Then, it can grow very huge by using a combination of OO and
functional programming. Large systems need both. This leads to also viewing Scala as a modular
language. Modules are essential pieces of both OO and functional languages. With modular
programming, your focus in on combining modules to do interesting things. Scala give you the power
to choose how to combine modules, and which programming paradigm to use.&lt;/p&gt;
&lt;p&gt;Martin was trying to stress that Scala has some simple building blocks (remember that
&lt;a href=&quot;http://www.infoq.com/presentations/Simple-Made-Easy&quot;&gt;simple != easy&lt;/a&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Everything is an expression&lt;/li&gt;
&lt;li&gt;Scopes allow you to nest everything (functions inside of functions)&lt;/li&gt;
&lt;li&gt;Patterns and case classes&lt;/li&gt;
&lt;li&gt;Recursion and more importantly, tail recursion&lt;/li&gt;
&lt;li&gt;Function values&lt;/li&gt;
&lt;li&gt;Collections. Think transformations, not CRUD operations&lt;/li&gt;
&lt;li&gt;vars. Combine a little bit of mutable state&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall, to me the talk actually had the opposite effect, it showed me how little I understand of
some of the principles on which Scala is built. During the last half of the talk, Martin dived
deeper into some architecture choices in the collections libraries to illustrate additional crazy
Scala language choices and features. But he lost me and, from speaking with some of the other
attendees, many others too.&lt;/p&gt;
&lt;h2&gt;Aaron Bedra: The Future of Web Security isn’t Preventing Attacks&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Senior Fellow, Groupon&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I quite enjoyed Aaron’s talk. He had a lot of energy, which was great for an afternoon talk on the
final day. Aaron made his point right away that &lt;em&gt;you cannot prevent attacks&lt;/em&gt; any more than you can
prevent someone from mugging you on the street. We should stop treating security as purely
preventative. He used the analogy of a casino, and our web applications already ID visitors like
casinos. However, unlike casinos, once a visitor is in we stop caring and assume its all ok! Casinos
are watching everyone, everywhere, all the time.&lt;/p&gt;
&lt;p&gt;So what do we do? According to Aaron, the first thing to do is to &lt;em&gt;aggregate your logs&lt;/em&gt;, drop a
query engine on top, and generate graphs. Beyond tools, we should analyze what the risks are in
having our security breached, and have a well-thought out plan for when breaches occur. Do you have
a plan? We should not design security without intent, and security should be part of the design
process of our system. Security should be responsive, intelligent, and focused.&lt;/p&gt;
&lt;p&gt;Great security should not only tell us what, when, and how, but also &lt;em&gt;who&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt;. This is what
we should strive for. The attackers will always be one step ahead of us. So instead of focusing on
prevention, we should focus on getting great at detection and response.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Meet LazyDoc]]></title><description><![CDATA[I’ve been pretty heads down in a  ThoughtWorks  project for the better
part of 2013 and have unfortunately neglected this blog. But 2014 is…]]></description><link>http://ryanogles.by/meet-lazydoc/</link><guid isPermaLink="false">http://ryanogles.by/meet-lazydoc/</guid><pubDate>Wed, 25 Dec 2013 19:44:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been pretty heads down in a &lt;a href=&quot;http://www.thoughtworks.com&quot;&gt;ThoughtWorks&lt;/a&gt; project for the better
part of 2013 and have unfortunately neglected this blog. But 2014 is a new year and I want to get
into a semi-regular cadence of posts.&lt;/p&gt;
&lt;p&gt;So with that in mind…… another long overdue post! So say hello to
&lt;a href=&quot;https://github.com/ryanoglesby08/lazy-doc&quot;&gt;LazyDoc&lt;/a&gt;, a Ruby gem I have released. LazyDoc provides a
DSL for extracting deeply nested values from a JSON document.&lt;/p&gt;
&lt;h2&gt;Working with APIs&lt;/h2&gt;
&lt;p&gt;In many projects I work on these days, the application consumes a 3rd party or internal API. In
Ruby, it’s tempting to just parse a JSON response from an API into a Hash and then pass that around
your application.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;extract_user_from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This “works”, but now your application is tightly coupled to the structure of the API response. The
fields your application needs are never defined, making it tough to know what you have available to
use. Is the “name” field “first_name”, “firstName”, or just “name”?&lt;/p&gt;
&lt;p&gt;Ok, easy enough solution for that. Objects to the rescue!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;
  attr_reader &lt;span class=&quot;token symbol&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:last_name&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;first_name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; last_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@first_name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; first_name
    &lt;span class=&quot;token variable&quot;&gt;@last_name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; last_name
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;extract_user_from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;first_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;last_name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now we have separated the JSON response from our application domain. Sweet! Ok, done… Right? Not
quite. There are a few problems here.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What about everything else in &lt;code class=&quot;language-text&quot;&gt;json_body&lt;/code&gt;? It is now lost. :(&lt;/li&gt;
&lt;li&gt;What do you do when you need to extract more information from that JSON response? This code isn’t
very flexible. Either you end up with a constructor that takes in too many arguments, or you end
up with too many setters on your &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Many times you want to massage your API response data a little bit before adding it to your
object. These massaging operations end up going into random helper methods that end up being
duplicated all over your codebase.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can do better.&lt;/p&gt;
&lt;h2&gt;Embedded Document Pattern&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;Embedded Document Pattern&lt;/strong&gt; to the rescue! Defined by Martin Fowler
&lt;a href=&quot;http://martinfowler.com/bliki/EmbeddedDocument.html&quot;&gt;here&lt;/a&gt;. With this pattern, instead of parsing
through your documents when they are received and building object graphs, we cache the document and
only parse through it when necessary. Because sometimes your document may be large compared to the
number of properties your application actually needs, you can save complexity and time.&lt;/p&gt;
&lt;p&gt;The LazyDoc gem is a Ruby implementation of the Embedded Document Pattern. You maintain access to
the entire JSON response, which makes it easy to add, update, or remove fields from your object as
you need. You retain flexibility. Any massaging that needs to be done to the fields becomes easy to
manage.&lt;/p&gt;
&lt;p&gt;So now, with LazyDoc:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;
  include &lt;span class=&quot;token constant&quot;&gt;LazyDoc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DSL&lt;/span&gt;

  access &lt;span class=&quot;token symbol&quot;&gt;:first_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:last_name&lt;/span&gt;
  access &lt;span class=&quot;token symbol&quot;&gt;:address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; default&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;NONE PROVIDED&apos;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;lazily_parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;extract_user_from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json_body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;Lazy?&lt;/h2&gt;
&lt;p&gt;So why is it called &lt;em&gt;Lazy&lt;/em&gt;Doc? The lazy feature is one of the coolest parts of this gem. The
declarative method &lt;code class=&quot;language-text&quot;&gt;access :first_name&lt;/code&gt; merely defines a method that is able to fetch the
&lt;code class=&quot;language-text&quot;&gt;first_name&lt;/code&gt; property from the JSON body. Only upon calling the method will the property be
extracted and massaged according to any defined operations. Additionally, the returned value will be
cached, so any subsequent calls will only return the cached value.&lt;/p&gt;
&lt;p&gt;Check the &lt;a href=&quot;https://github.com/ryanoglesby08/lazy-doc&quot;&gt;README&lt;/a&gt; for more information and examples.
Also, the &lt;a href=&quot;https://github.com/ryanoglesby08/lazy-doc/tree/v0.4.0/spec/acceptance&quot;&gt;acceptance specs&lt;/a&gt;
have full example usage.&lt;/p&gt;
&lt;p&gt;Feel free to download and use in your next project! Feedback is welcome!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Fun With Rails I18n]]></title><description><![CDATA[Skipping the Basics… Anyone wanting to develop a truly internationalized application needs to address translating the
text of the app into…]]></description><link>http://ryanogles.by/fun-with-rails-i18n/</link><guid isPermaLink="false">http://ryanogles.by/fun-with-rails-i18n/</guid><pubDate>Tue, 29 Jan 2013 20:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Skipping the Basics…&lt;/h2&gt;
&lt;p&gt;Anyone wanting to develop a truly internationalized application needs to address translating the
text of the app into the supported languages. Fortunately for you Rails devs out there, the
framework provides an easy mechanism for managing and performing those translations, I18n.translate
or shortly I18n.t being the forefront. I am just going to mention the basics here and then move
right on to some of the more fun features of Rails translations that every Rails ninja needs to
know.&lt;/p&gt;
&lt;p&gt;So we all know how to do basic translations:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;hello-world&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Oh hai, World, you are looking nice&apos;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;welcome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Welcome, %{user_name}&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;hello-world&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Oh hai, World, you are looking nice&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.welcome&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user_name&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;OptimusPrime&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Welcome, OptimusPrime&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now some things you may not know about.&lt;/p&gt;
&lt;h2&gt;Pluralization&lt;/h2&gt;
&lt;p&gt;When you do translations you don’t have to try to hack together interpolated strings using
&lt;code class=&quot;language-text&quot;&gt;ActiveSupport#pluralize&lt;/code&gt;. Pluralizations are baked right in.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;You got no messages here fool!&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Only 1 message right now.&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;You have %{count} messages.&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.messages&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# You got no messages here fool!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.messages&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# Only 1 message right now.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.messages&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# You have 5 messages.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;HTML Safe&lt;/h2&gt;
&lt;p&gt;As a general rule, I avoid putting HTML markup in a translation string. HTML markup should be in the
view where it belongs. However, despite my best efforts, sometimes it is unavoidable - which is okay
in certain situations. Furthermore, sometimes the variables passed into a translation will contain
HTML markup. The default strategy in this situation that I have seen is to use &lt;code class=&quot;language-text&quot;&gt;raw&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;html_safe&lt;/code&gt;.
While this does the job, it adds unnecessary method calls when the HTML safe-ification can be
handled directly by I18n using the &lt;code class=&quot;language-text&quot;&gt;_html&lt;/code&gt; suffix.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;account-will-be-locked_html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Your account is about to be &amp;lt;strong&gt;locked&amp;lt;/strong&gt;&apos;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;remaining-characters&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Remaining characters: %{amount}&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.account-will-be-locked_html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# &apos;Your account is about to be &amp;lt;strong&gt;locked&amp;lt;/strong&gt;&apos; (marked HTML safe for the view)&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.remaining-characters.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; amount&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;em&gt;50&amp;lt;/em&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# &apos;Remaining characters: &amp;lt;em&gt;50&amp;lt;/em&gt;&apos; (marked HTML safe for the view)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Though you do receive the added benefit of avoiding unnecessary &lt;code class=&quot;language-text&quot;&gt;html_safe&lt;/code&gt; calls, the real winner
here it that by being explicit in the locale file, you tell any other developers looking at it which
strings are expected to have HTML. Easy win for visibility and communication.&lt;/p&gt;
&lt;h2&gt;Watch Out for yes/no!&lt;/h2&gt;
&lt;p&gt;This is a weird one. I am actually not sure why this happens, and would appreciate if anyone can
shed some light on the underlying reason for this. If you try to use the key “yes” or “no,” I18n.t
will not be able to find it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;yes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sure thing&apos;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;No way!&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.yes&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;span class=&quot;translation_missing&quot; title=&quot;translation missing: en.views.yes&quot;&gt;Yes&amp;lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.no&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;span class=&quot;translation_missing&quot; title=&quot;translation missing: en.view.yes&quot;&gt;No&amp;lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Only solution I know is just to not use “yes” or “no” as keys, which is not ideal if you are adding
a translation for those exact words.&lt;/p&gt;
&lt;h2&gt;Literal Naming FTW&lt;/h2&gt;
&lt;p&gt;It can be quite tempting to use semantic keys in your locale YML files. I see things like “title,”
“introduction-1,” or “header-text.” While this will work fine, I prefer to use literal keys that
reflect the actual content of the translation (in the default locale) so my views are easier to read
for myself and other developers.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-haml&quot;&gt;&lt;code class=&quot;language-haml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token comment&quot;&gt;# Hard to read. I have to jump out of my code just to read my own code! Ergggggghhhh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;.header&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.header.user-intro&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@current_user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;.main-content&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;%p&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.site-description-1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;%p&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.site-description-2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;%ul&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;%li&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.user-perks-1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-haml&quot;&gt;&lt;code class=&quot;language-haml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token comment&quot;&gt;# Easy to read. I understand my own code. Yessssssssss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;.header&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.header.welcome-to-the-site&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@current_user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;.main-content&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;%p&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.we-have-doo-dads&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;%p&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.and-foo-bar-widgets&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token tag&quot;&gt;%ul&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;%li&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; &lt;span class=&quot;token function&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;views.common.receive-service-any-time&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;That’s all for now! Most of this plus everything else you wanted to know about i18n can be found in
the &lt;a href=&quot;http://guides.rubyonrails.org/i18n.html&quot;&gt;Rails Guides&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bye! Adios! Adieu! Aloha!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Rails Controller Specs Don't Always Play Nice With Hashie]]></title><description><![CDATA[Hashie and Rspec - The Problem: Hashie  is a neat little Ruby gem that extends Hash and gives
object-like access and functionality to hashes…]]></description><link>http://ryanogles.by/rails-controller-specs-dont-always-play-nice-with-hashie/</link><guid isPermaLink="false">http://ryanogles.by/rails-controller-specs-dont-always-play-nice-with-hashie/</guid><pubDate>Wed, 26 Dec 2012 14:58:00 GMT</pubDate><content:encoded>&lt;h2&gt;Hashie and Rspec - The Problem:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/intridea/hashie&quot;&gt;Hashie&lt;/a&gt; is a neat little Ruby gem that extends Hash and gives
object-like access and functionality to hashes. Classes can extend from Hashie and add other
functionality as needed. It is especially useful when marshaling JSON or XML data from a service
layer into your business models.&lt;/p&gt;
&lt;p&gt;While Hashie is very useful, we have to be careful using this gem with ActionController Rspec tests.
When creating the &lt;code class=&quot;language-text&quot;&gt;assigns&lt;/code&gt; hash used in controller tests, Rspec creates a
&lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt;, which is dangerous with objects that act like Hash (such as Hashie
objects). Rspec ends up converting user-defined objects that inherit from Hashie into
&lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt; objects, causing us to lose any data that exists outside of the backing
hash.&lt;/p&gt;
&lt;h2&gt;The Setup:&lt;/h2&gt;
&lt;p&gt;Lets imagine our Rails application talks to an Employee API exposing JSON data. We have already
implemented the service layer that makes the API call and returns Employee objects that extend
Hashie. In the EmployeeController we make the service call and assign the resulting Employee object.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# employee.rb&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Hashie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Dash&lt;/span&gt;
  property &lt;span class=&quot;token symbol&quot;&gt;:first_name&lt;/span&gt;
  property &lt;span class=&quot;token symbol&quot;&gt;:last_name&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# foo is not specified using &quot;property&quot; because it does not come from the EmployeeService&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   JSON response. We are separating what comes from the service and what does not.&lt;/span&gt;
  attr_accessor &lt;span class=&quot;token symbol&quot;&gt;:foo&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# employee_controller.rb&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmployeeController&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ActionController&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; show
    &lt;span class=&quot;token variable&quot;&gt;@employee&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EmployeeService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find_by_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;@employee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;extra info&apos;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;The Tests (Where the conflict occurs):&lt;/h2&gt;
&lt;p&gt;We should be able to write some simple specs to test the controller, specifically, that the result
of the service call is stored in the correct variable passed into the view and that we assign
whatever extra processing we need to do outside of the service layer into “foo.”&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# employee_controller_spec.rb&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;spec_helper&apos;&lt;/span&gt;

describe &lt;span class=&quot;token constant&quot;&gt;EmployeeController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  describe &lt;span class=&quot;token string&quot;&gt;&apos;show&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    it &lt;span class=&quot;token string&quot;&gt;&apos;should assign the employee&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;EmployeeService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:find_by_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Employee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      get &lt;span class=&quot;token symbol&quot;&gt;:show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;employee_id&apos;&lt;/span&gt;

      assigns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:employee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;should be_an &lt;span class=&quot;token constant&quot;&gt;Employee&lt;/span&gt;
      assigns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:employee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;should &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;extra info&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;You would assume this test would pass right? Nope! Fail!&lt;/p&gt;
&lt;p&gt;The output of both assertions would be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;expected &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;first_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;last_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Smith&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; to be a kind of &lt;span class=&quot;token constant&quot;&gt;Employee&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;NoMethodError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; undefined method &lt;span class=&quot;token string&quot;&gt;&apos;foo&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;first_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;last_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Smith&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:ActiveSupport&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HashWithIndifferentAccess&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;As you can see, Rails has converted our Employee object into a
&lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html&quot;&gt;HashWithIndifferentAccess&lt;/a&gt;!
How dare you Rails?!&lt;/p&gt;
&lt;h2&gt;Why would Rails do this?&lt;/h2&gt;
&lt;p&gt;Well, don’t be too quick to point the finger, this is actually a combination of Rspec and Rails
(ActiveSupport). Rspec is trying to make it easier for you to use the ActionController
&lt;code class=&quot;language-text&quot;&gt;view_assigns&lt;/code&gt; hash by converting it into a &lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt;. Diving into
&lt;code class=&quot;language-text&quot;&gt;ActionDispatch::TestProcess&lt;/code&gt; we find the method definition for &lt;code class=&quot;language-text&quot;&gt;assigns&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# test_process.rb&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ActionDispatch&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TestProcess&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assigns&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      assigns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@controller&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;view_assigns&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;with_indifferent_access
      key&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; assigns &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; assigns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The easy access to the &lt;code class=&quot;language-text&quot;&gt;view_assigns&lt;/code&gt; hash is great, but looking deeper into the internals of the
&lt;code class=&quot;language-text&quot;&gt;with_indifferent_access&lt;/code&gt; method we find that while creating the &lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt;, any
assigns variable that is a &lt;code class=&quot;language-text&quot;&gt;Hash&lt;/code&gt; is converted into a &lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt;! Since Hashie
classes return true when asked if they are a &lt;code class=&quot;language-text&quot;&gt;Hash&lt;/code&gt;, they also get converted, therefore, losing
their original object identity. To me ActiveSupport is stepping over the line here. Yes, give us
easy access to the assigns hash, but don’t mess with the actual values of that hash unless I tell
you to.&lt;/p&gt;
&lt;h2&gt;Easy workaround:&lt;/h2&gt;
&lt;p&gt;First, this problem is unique to Rspec tests - production code does not have this same problem. One
solution would be to monkey patch &lt;code class=&quot;language-text&quot;&gt;ActiveSuport::TestProcess&lt;/code&gt; and
&lt;code class=&quot;language-text&quot;&gt;ActiveSupport::HashWithIndifferentAccess&lt;/code&gt;. But, since I try to stay away from monkey patching
whenever possible, the quick solution is just to not use &lt;code class=&quot;language-text&quot;&gt;assigns&lt;/code&gt; when your object under test is a
Hash and you care about it not being converted to a &lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt; for testing
purposes.&lt;/p&gt;
&lt;p&gt;Instead, use the controller’s &lt;code class=&quot;language-text&quot;&gt;view_assigns&lt;/code&gt; hash directly to avoid the conversion to
&lt;code class=&quot;language-text&quot;&gt;HashWithIndifferentAccess&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# employee_controller_spec.rb&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;spec_helper&apos;&lt;/span&gt;

describe &lt;span class=&quot;token constant&quot;&gt;EmployeeController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  describe &lt;span class=&quot;token string&quot;&gt;&apos;show&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    it &lt;span class=&quot;token string&quot;&gt;&apos;should assign the employee&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;EmployeeService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:find_by_id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Employee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

      get &lt;span class=&quot;token symbol&quot;&gt;:show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;employee-id&apos;&lt;/span&gt;

      &lt;span class=&quot;token comment&quot;&gt;# Can not use assigns[:employee] here because Employee inherits from Hashie&lt;/span&gt;
      controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;view_assigns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;employee&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;should be_an &lt;span class=&quot;token constant&quot;&gt;Employee&lt;/span&gt;
      controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;view_assigns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;employee&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;should &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;extra info&apos;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;In the end, its an easy workaround for a slightly annoying “feature” of Rspec.&lt;/p&gt;</content:encoded></item></channel></rss>