<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Code Climate Blog</title>
  <id>https://codeclimate.com/blog</id>
  <link href="https://codeclimate.com/blog"/>
  <link href="https://codeclimate.com/blog/atom.xml" rel="self"/>
  <updated>2017-12-14T10:00:00+00:00</updated>
  <author>
    <name>Code Climate LLC</name>
    <email>hello@codeclimate.com</email>
  </author>
  <entry>
    <title>How Codecademy achieves rapid growth and maintainable code</title>
    <author>
      <name>Jenna Smith</name>
      <uri>https://twitter.com/lefteess</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/codecademy-case-study/"/>
    <id>https://codeclimate.com/blog/codecademy-case-study/</id>
    <updated>2017-12-14T10:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p class="article__intro">We sat down with Jake Hiller, Head of Engineering at Codecademy, to find out how they use Code Climate to maintain their quality standards while rapidly growing their engineering team.</p>

<p></p>

<p><img class="post-image--left" src="https://d341kum51qu34d.cloudfront.net/images/posts/codecademy/codecademy_logo.svg" width="240" alt="Codecademy Logo"></p>

<div class="case-study__details">
  <div class="case-study__data">
    <span class="case-study__category">Industry</span>
    <span>Education</span>
  </div>
  <div class="case-study__data">
    <span class="case-study__category">Employees</span>
    <span>50+</span>
  </div>
  <div class="case-study__data">
    <span class="case-study__category">Developers</span>
    <span>20+</span>
  </div>
  <div class="case-study__data">
    <span class="case-study__category">Location</span>
    <span>Manhattan, NY</span>
  </div>
  <div class="case-study__data">
    <span class="case-study__category">Languages</span>
    <span>Ruby, JavaScript, SCSS</span>
  </div>
  <div class="case-study__data">
    <span class="case-study__category">Customer</span>
    <span>Since May 2013</span>
  </div>
</div>

<blockquote>
<p>Code Climate keeps our process for creating PRs really low-effort so we can quickly test ideas and ship sooner.</p>
</blockquote>

<h2>Why Code Climate</h2>

<p>Like many rapidly developing teams, Codecademy was running into growing pains for both engineering onboarding and code review. They had tried using local analysis tools but found them cumbersome to integrate as development environments varied across the team.</p>

<p>With an engineering workflow centered around pull request reviews, and a desire to reduce friction in committing and testing code, they needed a solution that would optimize their pull request review process and enable new team members to quickly become productive.</p>

<p>Codecademy had been using Code Climate for their Ruby stack since 2013. When Head of Engineering, Jake Hiller, joined in early 2015, he saw an opportunity to alleviate their code review and onboarding issues by rolling it out to the whole team.</p>

<p>&ldquo;We wanted to avoid anything that blocks engineers from committing and testing code. Other solutions that use pre-commit hooks are invasive to both experimentation and the creative process. Code Climate’s flexibility helps us maintain rules that are tailored to our team and codebase, while offering standard maintainability measurements. Plus it enables us to defer checks until code is ready to be reviewed, so we can quickly test ideas and ship sooner.&rdquo;</p>

<blockquote>
<p>&ldquo;Code Climate helps us transfer knowledge to new engineers – like our coding standards, why we&rsquo;ve made decisions over time, and why we&rsquo;ve chosen certain structures and patterns.</p>
</blockquote>

<h2>Increased speed and quality</h2>

<p>Since rolling out to the whole team, Hiller says Codecademy has seen an improvement in the quality of their code reviews and the ease with which new team members get up to speed.</p>

<p>&quot;Code Climate helps us transfer knowledge to new engineers – like our coding standards, why we&rsquo;ve made decisions over time, and why we&rsquo;ve chosen certain structures and patterns. New engineers can look through the Code Climate issues in their PR, ask questions, and propose changes and suggestions to the team.</p>

<p>&quot;It’s also increased the speed and quality of our pull request reviews. We&rsquo;ve been able to spend more time discussing the important functional aspects of our code, and less time debating smaller issues. There are a lot of issues that can&rsquo;t be fixed with an auto formatter, which is where Code Climate will always be really helpful for our team.&rdquo;</p>

<h2>About Codecademy</h2>

<p>Codecademy was founded in 2011 as an immersive online platform for learning to code in a fun, interactive, and accessible way. They’ve helped 45 million people learn how to code, covering a wide variety of programming languages, frameworks, and larger topics like Data Analysis and Web Development. Their recently released Pro and Pro Intensive products provide users with more hands on support and practice material to help them learn the skills they need to find jobs.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Role of being Technical in Technical Leadership</title>
    <author>
      <name>Kären Engelbrecht</name>
      <uri>https://twitter.com/scriberty</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/the-role-of-being-technical-leadership/"/>
    <id>https://codeclimate.com/blog/the-role-of-being-technical-leadership/</id>
    <updated>2017-11-15T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>In July, we hosted the first annual <a href="https://codeclimate.com/summit">Code Climate Summit</a>, a one-day
conference for leaders of engineering organizations who want to better
themselves, their processes, and their teams.</p>

<p>Today we’re sharing <strong>The Role of being Technical in Technical Leadership</strong>, by
<a href="https://twitter.com/skamille">Camille Fournier</a>, Managing Director at Two
Sigma.</p>

<script src="https://fast.wistia.com/embed/medias/h73buryae1.jsonp" async>
</script>

<script src="https://fast.wistia.com/assets/external/E-v1.js" async>
</script>

<div class="wistia_responsive_padding" style="padding:56.25% 0 0 0;position:relative;">
  <div class="wistia_responsive_wrapper" style="height:100%;left:0;position:absolute;top:0;width:100%;">
    <div class="wistia_embed wistia_async_h73buryae1 videoFoam=true" style="height:100%;width:100%">
    &nbsp;
    </div>
  </div>
</div>

<h2>Transcript of talk</h2>

<p><strong>Camille Fournier</strong>: Hi everyone, I am excited to be here at this Code Climate
Summit.  We were customers of Code Climate when I was at Rent the Runway, so
I&rsquo;m a huge fan of the product and I was very honored to be invited to come
speak.</p>

<p>This is a talk about engineering management, which I think is pretty important
for building effective engineering teams and building good products. We&rsquo;re
going to talk about what actually what it means to put the engineer in
engineering management.</p>

<p>Before I begin, of course, I must give a pitch to Two Sigma, so I am as of
about four months ago, the head of platform engineering at Two Sigma. Two Sigma
is a financial company here in New York. Our engineers and modelers harness
data at tremendous skill, use machine learning, distributed computing, and
other technologies to build powerful predictive models. If you are interested
in that world, twosigma.com/careers, check it out.</p>

<p>Okay. So. Let&rsquo;s get this really started. &ldquo;You either die an engineer or live
long enough to see yourself become the business person.&rdquo; This something my
friend Cliff Moon at some point said or tweeted, probably both, and I like this
quote not just because it&rsquo;s kind of funny, but also because I think it really
summarizes the struggle that many people have when they think about engineering
management. &ldquo;Am I still an engineer, or have I suddenly become a
business person?&rdquo;</p>

<p>I personally have struggled with this, so this is how I have a lot of empathy
with this. I started out my career as a hands-on engineer, I guess as most
people do. I was hands-on for a really long time, building lots of different
kinds of systems, mostly distributed systems.</p>

<p>I actually just got photographed for something called Faces of Open Source,
it&rsquo;s facesofopensource.com, which is taking pictures of various people in the
open source community. It was a cool experience and this is the photo that came
out of that.</p>

<p>So, I&rsquo;ve spent a long time as a hands-on engineer. At some point in my career I
was like, &ldquo;Oh, I want to do more, I want more power, I want more authority.&rdquo;
Lots of bad reasons, but I decided that I wanted to go into management, so I
joined a startup as a director of engineering, and I was still actually writing
a lot of code for the first year or so I was there.</p>

<p>As the startup grew - and that startup was, of course, Rent the Runway - as
that startup grew and was successful, and I was fortunate to be growing and be
successful along with it, I hit that dreaded cliff of no more coding, where I
really had to stop coding.</p>

<p>We tell managers that this will happen. Sometimes we tell them a little too
early in my opinion. I actually think it&rsquo;s okay for you to write some code when
you have a small team, but there is certainly a point where if you are writing
code as a manager, you&rsquo;re probably avoiding doing more important work, like
talking to people, and planning things, and other kinds of things that make
teams successful.</p>

<p>It&rsquo;s still hard. It&rsquo;s really hard if you&rsquo;ve been a programmer for a long time,
if you&rsquo;ve been a hands-on person for a long time, hitting that cliff of no
coding is really painful. I remember, it probably took me like a year of angst
before I finally got over it.</p>

<p>We say a lot of things about management, we call it a career change and now
that you&rsquo;re a manager, you&rsquo;re no longer an engineer anymore. I have probably
said this myself, and while I think it&rsquo;s kind of true, I also really love the
language that we use when we say this, because it&rsquo;s also kind of a negative way
to frame things.</p>

<p>I wrote a book and you all have copies of it, which is cool. I&rsquo;m very flattered
that they decided to give my book as a giveaway here. This book is about being
an engineering manager. It&rsquo;s about the various stages of engineering
management.</p>

<p>Part of the reason that I wrote this book was that I felt that there was not a
lot out there that really walked the path of being all the way from a mentor
and early career leader, but definitely still a hands-on engineer, all the way
through to being something like a CTO or a VP of engineering or a senior
executive.</p>

<p>I also wrote this book because I have a thesis that is, among other things,
while the people side of management is really important, managers also need to
be technical. I think that there is a reason that we tend to promote technical
people into management roles. It&rsquo;s not just because we want to punish them.</p>

<blockquote>
<p>Engineering management is the intersection of engineering and management.</p>
</blockquote>

<p>It&rsquo;s that, engineering management is the intersection of engineering and
management. It is not just managing a bunch of people who happen to be
engineers. It is important that you, to be a really successful engineering
manager, understand the way that people do their work. You are able to guide
their technical decisions.</p>

<p>This doesn&rsquo;t mean you&rsquo;re making decisions for them. In fact, most of the time,
I don&rsquo;t really make all that many decisions. I try to ask good questions and
guide my teams, but I&rsquo;m not actually making decisions for them. The hands-on
people who are doing the work are making the decisions, but I still need to
understand the context in which they are operating. That context includes what
it is like to be an engineer.</p>

<p>This talk is going to cover three traits that I believe are overlapping traits
that you tend to find in great senior engineers, and the way that these traits
translate into what makes good engineering managers. I&rsquo;m going to talk about
debugging, I&rsquo;m going to talk about empathy, and I&rsquo;m going to talk about
judgment.</p>

<h2>DEBUGGING</h2>

<p>Let&rsquo;s start with debugging. I love debugging. I don&rsquo;t know about all of you,
I&rsquo;m sure some of you do and some of you don&rsquo;t. It&rsquo;s definitely not the thing
that every single engineer loves to do, but it&rsquo;s something we all have to do
because</p>

<p>I&rsquo;m sure you&rsquo;ve probably forgot a semi-colon the first time you wrote hello
world.</p>

<p>We&rsquo;re always debugging all the time. Things are always breaking and you&rsquo;re
always having to debug, and as you become more and more of a senior engineer,
you experience more, new, interesting ways that things can fail. You start to
sense the vast possibility of causes behind failures.</p>

<p>Part of the reason that I went into management is actually the same reason that
I love debugging. I wanted to understand why things were happening. I started
asking why a lot. Why is this happening? Why are we doing this? Why do we do
this process this way? Why didn&rsquo;t we fix this? Why didn&rsquo;t we make this choice?
Why, why, why, why?</p>

<p>Asking why too much, it turns out, is a not uncommon way that people end up
becoming managers, because they want to know. They want to know not just about
what is causing systems to behave in a certain way, but they also want to know
what&rsquo;s causing us to make decisions this way in the first place.</p>

<p>At the end of the day, this skill set overlap is what a lot of people call
&ldquo;systems thinking&rdquo;. It&rsquo;s not my favorite term, but I like the concept. People
that are good at seeing the interactions of different kinds of systems that you
may not have perfect information into. When you&rsquo;re talking about looking at the
interactions of people, you can&rsquo;t read people&rsquo;s minds. You can only go by what
they tell you.</p>

<p>You don&rsquo;t always have perfect insight even into the software systems you&rsquo;re
developing. People who are good at seeing in systems, are good at debugging,
and they tend to become good managers for the same reason, because, guess what,
as a distributed systems engineer, the system is slow, it&rsquo;s probably the
hardest problem you&rsquo;ll ever have to debug, and as a manager, the team is slow.</p>

<blockquote>
<p>&ldquo;The team is slow&rdquo; is the hardest problem you&rsquo;ll ever debug.</p>
</blockquote>

<p>It&rsquo;s probably the hardest thing you&rsquo;ll ever need to debug, especially if you
happen to be working at a startup for a CEO, especially if the CEO is not
technical. But e*ven if the CEO is technical, frankly, they always want to
know, &ldquo;Why aren&rsquo;t we getting it done faster. Why aren&rsquo;t we moving faster. Why
isn&rsquo;t this release done? Why haven&rsquo;t we finished this?&rdquo;</p>

<p>To figure this out, you have to look across a bunch of different elements. You
have to look at the people, sometimes as humans, we move slowly because people
are unmotivated for whatever reason. They&rsquo;re burned out, they&rsquo;re tired. They
don&rsquo;t get along. The team hasn&rsquo;t actually gelled all that well. You&rsquo;ve got
somebody that&rsquo;s very disruptive. They just can&rsquo;t agree on the way to do
something.</p>

<p>Sometimes, of course, the challenge is a process problem. You&rsquo;ve got this
product management team that thinks that they&rsquo;re mini demi-gods over here,
throwing work over the wall to the engineering team and saying, &ldquo;Behold my
brilliance, go implement it.&rdquo; And most engineering teams don&rsquo;t really like
that, it can be very demotivating, although some of them do. You&rsquo;ve got to
understand what process, what&rsquo;s the process contributing to the team&rsquo;s
slowness.</p>

<p>And of course, sometimes it&rsquo;s the systems. Sometimes you really are dealing
with really hairy, nasty technical problems that are going to take a long time
to figure out. They&rsquo;re going to take a long time to solve.</p>

<p>You as an engineering manager, have moved beyond the world where you&rsquo;re
thinking about the interactions of software systems all the time, but you&rsquo;re
still looking at system interactions. You&rsquo;re looking at the interactions of the
systems of the humans and the processes that the humans are using and the
technology that they&rsquo;re having to deal with to get their job done every day.</p>

<h2>EMPATHY</h2>

<p>The second characteristic is empathy. We talk about empathy a lot. It was
already spoken of quite a bit in the last talk. I think it&rsquo;s a very popular
thing to talk about in technical circles these days, which is probably pretty
good, because for a long time we had this very robotic approach to technology.
Programmers want to go and close the door and be in silence and just thinking
about computers. We do realize that to really build effective products, we need
to care about our customers and to build effective teams, we need to care about
our teammates, and as a manager, we want people who appreciate people. But,
there&rsquo;s a little more to it than that.</p>

<p>There was a study done recently that showed that the number one contributor to
workplace happiness that they measured, was actually whether or not they
believed their boss was highly competent. Highly competent could mean a few
different things.  Highly competent could mean the boss could do your job, but
highly competent could also mean a domain expert in the field.</p>

<p>It&rsquo;s very clear though, that people really do want highly competent bosses, and
frankly I feel the same way. I get to work for this guy, his name is Alfred
Spector, he is the CTO at Two Sigma. He was a professor of computer science for
a long time, actually started a company, then became a lead scientist at IBM.
He ran Google Research for a very long time before coming to Two Sigma. He&rsquo;s a
very interesting person. He has a really incredible technical computer science
background, he&rsquo;s a good manager, which is amazing, and he&rsquo;s entrepreneurial.
All of those things are awesome, and I&rsquo;m really excited to get to work for
someone like that. I want to work for someone that I believe is highly
competent and has shown a track record of doing great things.</p>

<p>That doesn&rsquo;t mean that I expect him to sit down next to me and pair program.
That actually doesn&rsquo;t mean that you as a manager are going to be spending all
of your time actually in the weeds of the technology, coding with your team.</p>

<p>So what does it really mean to say that we want someone who possesses technical
empathy? What does this empathy element mean for managers beyond just, you can
see how people are feeling?</p>

<p>I think it really means that you want someone who appreciates the work, someone
who appreciates the details of the work and why work is good or bad. Your
manager is often the person who evaluates you, who is evaluating your work and
saying who&rsquo;s doing well and who&rsquo;s not doing well, maybe even who&rsquo;s going to get
promoted. You want that person to actually be able to tell the difference
between somebody who does high quality work and someone who doesn&rsquo;t.</p>

<p>You also just want that feeling of the expert appreciation. It means more when
you respect someone&rsquo;s opinion that they have a high opinion of you. We want
someone who really appreciates why our work is hard, why our work is done well,
maybe even, sometimes is able to give us suggestions about how to do it better.
But certainly, we at least want that appreciation.</p>

<p>It&rsquo;s also good as a manager, to be able to appreciate what your teams are going
to be excited about. Different people are excited about different things, but
engineering teams tend to get excited about slightly different kinds of
problems than marketing teams or sales teams. Engineering is a special
discipline with its own rules, with its own challenges and we want managers who
can appreciate and identify interesting problems and direct us towards those
interesting problems and make us feel like they understand what the wider tech
world is excited about and can actually help us get to do some of those
exciting things. Even more importantly of course, we want managers who
appreciate what frustrates engineers. It&rsquo;s not obvious to a non-engineer, what
parts of the job are stressful. It just isn&rsquo;t. It&rsquo;s very hard to understand how
stressful it is to get distracted or pulled away from your code every 15
minutes because somebody keeps coming over to talk to you over your shoulder.</p>

<p>That can be a hard thing for people to understand. It&rsquo;s much easier with a
technical manager, at least someone who appreciates what the work is like, to
be able to predict those frustrations and therefore cut them off before they
start happening.</p>

<h2>TECHNICAL JUDGMENT</h2>

<p>Last but not least, there&rsquo;s the matter of technical judgment, which is of
course, very important in senior engineers. I said before that technical
management is often the art of guiding technical decision making. It&rsquo;s not
making the decisions yourself, but even when you have a very strong tech lead
or architect or whatever and a great product manager, what you will often find
as an engineering manager is that you are the person sitting in the middle of
those two and trying to balance those differing viewpoints.</p>

<p>You need to make sure that you are actually taking into account the full
context of both the technical and the business side in order to help the team
prioritize their work. Because ultimately, the technical decisions that are
made will impact the effectiveness of the team, and the effectiveness of the
team as a manager is definitely your job.</p>

<p>A lot of the people in their first go round of engineering management try to
apply just the process to things. They say, &ldquo;Oh, I know the process that will
solve it.&rdquo; It can be anything from we&rsquo;re going to do OKRs, we&rsquo;re going to have
engineers vote on whatever project they want to work on, we&rsquo;re going to do
agile, scrum, kanban, whatever style project management you want to do.</p>

<p>I actually think process is useful and different processes work well for
different teams, but there&rsquo;s a lot of nuance. You have to understand what
process is going to work for your team. Moreover, you&rsquo;ve got to remember that
process does not make decisions for you. The best thing process does is provide
the context, again, all of the information at your fingertips with the right
people in the room, to help you make decisions.</p>

<p>One quote I use in my book is that a good political idea is one that works well
in half-baked form, which I believe is from some kind of economics blog. I
believe the same is true for a process. Good processes are going to work well
in half-baked form. As an engineering manager, you&rsquo;ve got to understand how to
get something that works well for your team, but it&rsquo;s not going to be the
magical decider of all your difficult technical decisions.</p>

<p>Good senior engineers and good engineering managers have a good eye for detail.
They can be detail oriented when they need to be, because ultimately, building
good software systems is all about the details. It&rsquo;s all about understanding
the details of the problem you&rsquo;re solving and accounting for those details.</p>

<p>The same is true for making good decisions. Good decision making is all about
having the taste and understanding the nuance that makes two decisions that
seem about equivalent actually different, and one the right way to go, and one
the wrong way to go.</p>

<p>I talked about prioritizing. I&rsquo;m going to reaffirm that point. You&rsquo;re at the
end of the process, you&rsquo;re trying to get something shipped. Prioritizing,
prioritizing, prioritizing, is the name of the game and good engineering
managers are good at being in that end stage and looking at the list of
technical features and looking at the list of product features and asking both
sides what&rsquo;s really important here.</p>

<p>&ldquo;What technical features can we absolutely not ship without. It would be bad
for us to ship without having any kind of alerting on this, because this is
actually pretty mission critical. But you know what? Actually, this is just an
MVP and it&rsquo;s going out to five people, so maybe we can just ship it without
that feature.&rdquo;</p>

<p>On the product side of course, it&rsquo;s like, &ldquo;Hey, product team, I know you love
all these features, but which of these do you love the most, because guess
what, this beautiful widget that you want the engineering team to build, we&rsquo;ve
talked it over and this is going to be a three week project to get right. Does
this really have to be in the critical path of delivery?&rdquo;</p>

<p>Being able to balance those two concerns and advocate for each side is one of
the important characteristics of good engineering management.</p>

<p>Last point here, you have to understand the problems that the team is solving
well enough to be able to communicate them with various people.</p>

<p>Manager telephone. Manager telephone happens when your manager goes and sits in
a meeting, takes a bunch of notes, comes back to the team, asks the questions
they have written down on their sheet that were the questions that were asked
in the meeting, writes down your responses, goes back to the other team, reads
those responses out and so forth. Zero value add. You want managers who can
understand at least well enough to focus and reframe the questions that are
being asked from people who aren&rsquo;t familiar with the work of the team and who
are good at actually getting the right information out of the engineering team,
and making sense of it.</p>

<p>Nobody wants managers who are going to play telephone. That&rsquo;s simply a zero
value add activity. We want people who are going to appreciate the work that&rsquo;s
going on well enough to actually focus the discussions around it.</p>

<p>Debugging, empathy and judgment. These are pretty important. I think these are
important skills to build whether you decide to become a manager or whether you
simply want to be a really great hands-on engineer. What else?.</p>

<p>There is a little bit of a risk to this whole &ldquo;rah rah managers should be
technical&rdquo; and that risk is that you get managers who were once pretty good at
being technical, but who have gone hands-off for a long time and lost their
touch a little bit. They still think of themselves as really amazing, as one of
the people, as it were, but they don&rsquo;t really remember what it&rsquo;s like, and
frankly, they haven&rsquo;t even kept up, so they don&rsquo;t really know what it&rsquo;s like to
write code in JavaScript. They&rsquo;ve only ever written code in C++, and frankly,
that&rsquo;s just a different world, right? Writing code for the browser&rsquo;s super
different. They have not kept up. They don&rsquo;t really appreciate what the actual
work looks and feels like.</p>

<blockquote>
<p>Stay humble.</p>
</blockquote>

<p>If you decide to go on this path, it&rsquo;s very important that you stay humble with
your knowledge and your understanding. You can glue this in a bunch of
different ways. Some people advocate for going back and forth between big
companies and small companies where you can be a manager and then you can be
hands-on and that&rsquo;s an awesome path to take.</p>

<p>Some ways you could do it - frankly, I sometimes write a little bit of code. I
work on a lot of open source projects, but realistically, you can keep reading
code, you can keep helping debugging. You&rsquo;re going to get a little hands-off,
though.</p>

<p>My advice if you decide to follow this path is to, if nothing else, keep
learning, particularly about advances in the way software engineers do their
work. That&rsquo;s things like, &ldquo;What does it mean to build all your software based
on cloud services.&rdquo;</p>

<p>That&rsquo;s very different than building everything in house. What does it mean to
do a continuous deployment process? What are the major advances in the way
people actually do work and deliver software? That&rsquo;s a really important thing
for you to keep in touch with as an engineering manager if you&rsquo;re managing
software engineering.</p>

<p>Okay, so these traits, one more time. Debugging, seeing those symptoms,
technical empathy, that technical appreciation, and finally judgment,
prioritizing and understanding the problems at hand.</p>

<p>I still consider myself an engineer, even though I don&rsquo;t write code all that
often. I personally hope to die an engineer someday, but whichever of those two
paths I end up following, I know that it&rsquo;s going to require constant learning,
constant reading.</p>

<p>You can be like this guy. He used to work for Code Climate and he is the
quintessential renaissance man who manages to both be the business jerk and be
an engineer, all in one. So read more. You can start with my book, because you
all have a copy of it, and thank you all very much. I&rsquo;m happy to take
questions.</p>

<p><strong>Audience 1</strong>: Thank you for the talk, it&rsquo;s great. Disclaimer, I&rsquo;m not an
engineer, I&rsquo;m a product manager. My question to you as the technology industry
veteran that you are today, you see these four engineers that either goes into
principal engineers or technical fellow or going to director of engineering, do
you see the same trend with product management? Do you have any advice for
managers of product manager?</p>

<p><strong>Camille Fournier</strong>: Not as much, mostly because the product teams tend to be
so small that even as a manager of product managers, you&rsquo;re not usually
managing a lot of people. There&rsquo;s just a huge difference between &hellip; frankly, I
think you can be an &ldquo;individual contributor style&rdquo; engineer and still manage
three or four people, particularly if they&rsquo;re very senior and they don&rsquo;t
require a lot of mentorship or management.</p>

<p>I think that often product management, because there are just not that many
people to be managed, it&rsquo;s not as much of a fork. I do think that what you see
happen with product management is that product managers who become more senior
or experienced, tend to be like general managers - perhaps of business lines -
and that is a bigger, more complex management job.</p>

<p>I could imagine that for product managers there is a little bit of a split
between, I&rsquo;m going to go be a general manager for a pretty big company and run
a large business line and actually have a lot of management accountability or
I&rsquo;m going to stay very focused on just product direction and strategy.</p>

<p><strong>Audience 2</strong>: Great talk, thank you so much. In your experience, what is a
good management to engineer in ratio, so how many engineers per engineering
manager do you think is a right mix. I know it&rsquo;s different for every company
and every field and all that, but just in general.</p>

<p><strong>Camille Fournier</strong>: Okay. I do think it&rsquo;s very hard to effectively be a
one-on-one manager for more than eight to ten people. If you&rsquo;ve got a team of
more than ten people directly reporting to you, and frankly for many people
it&rsquo;s less than that, you are probably not serving very well, some of those
people.</p>

<p>I know personally that if I have more than about six direct reports, at some
point, people are getting less of me than they otherwise might. That helps sort
of think about the ratios. I do still believe that you can effectively be
managing a small team and acting as an individual contributor. You&rsquo;re not going
to be 100% as effective as you would be if you had no team. You can tweak
ratios that way, but I certainly don&rsquo;t think that it&rsquo;s a good ratio to have one
manager per 20 employees. It&rsquo;s probably not a good ratio to have one manager
per two employees either. It&rsquo;s going to be somewhere in that.</p>

<p>I would say probably one to six, one to eight is okay, especially if the line
managers are still expected to stay fairly technical even if they&rsquo;re not
writing a lot of code there, they&rsquo;re really thinking about a lot of technical
issues.</p>

<p><strong>Audience 3</strong>: Hi. You said that team effectiveness is a manager&rsquo;s primary
responsibility or one of them. What are the KPI&rsquo;s that you use to determine
your team&rsquo;s effectiveness?</p>

<p><strong>Camille Fournier</strong>: Okay. A few KPIs that I would see, obviously, retention.
Are people quitting? That&rsquo;s a big one. How are we doing on the deliveries that
we&rsquo;ve committed to? If we&rsquo;ve committed to deliver certain software or hit
certain goals, how effective are we at hitting those goals and are those goals
stretch goals? Do we think they&rsquo;re not the level we would like them to be?</p>

<p>I think overall morale of a team is just generally important, so even if people
aren&rsquo;t quitting, you can still find yourself in a situation where people aren&rsquo;t
quitting, but they&rsquo;re just not that excited about work. They&rsquo;re not that
engaged and enthusiastic. A lot of team effectiveness, the output is what work
gets done, but the side pieces of it are really a lot about morale and
retention and engagement from the team.</p>

<p><strong>Audience 4</strong>: You talked about show an appreciation for team members. Have
you ever been in a situation where you show appreciation of a team member and
it&rsquo;s fostered envy from other members or there&rsquo;s been resentment as a result?</p>

<p><strong>Camille Fournier</strong>: Yeah, absolutely. I think was accused of playing
favorites at some point in my career, so I&rsquo;ve tried to be very aware of that. I
think appreciation is one of those core management things that you want to try
to do a lot for everyone. It actually is not a bad thing to tell people they&rsquo;re
doing a good job fairly regularly and try to tell everyone on the team.</p>

<p>The way you recognize people, particularly if you do public recognition, you&rsquo;re
definitely shaping your culture when you do that. If you always publicly
recognize individuals, and you never publicly recognize teams, your company is
going to start to develop a culture of &ldquo;individual accomplishments are the most
important thing and it&rsquo;s better for me to get the win myself than to bring the
whole team along.&rdquo;</p>

<p>You have to be very careful with thinking about how you recognize those things.
Honestly, I think a lot of this appreciation is just in that one on one. Do I
feel like my boss really understands the work I&rsquo;m doing well enough to be like,
&ldquo;Wow, that was a hard thing. That was a really cool set up you did to get that
migration to go so smoothly. I&rsquo;m very impressed with the technical work that
you did. I&rsquo;m impressed you thought through this process in that way.&rdquo;</p>

<p>I think a lot of appreciation is very effective just in a one-on-one context,
not even worrying about big team appreciation.</p>

<p><strong>Audience 5</strong>: You mentioned we all want to work on hard problems, fun problems,
and maybe direct our team towards those. Often we don&rsquo;t necessarily have the
decision making in where the product goes, where a business wants to go, so
what are your strategies for maybe managing upward or convincing them of going
towards maybe a more difficult problem but more impactful?</p>

<p><strong>Camille Fournier</strong>: I think it depends, so a lot of the times &hellip; hard problems is a
little bit of a, I don&rsquo;t think I phrased that as well as I should have.
Engineers want to feel like they are having impact, so some engineers are very
much driven by solving the hardest problem. I think the best thing you can do
in that case is help identify where there are really hard problems and make
sure you&rsquo;re keeping those engineers as close to those as possible.</p>

<p>A lot of the times what you do though as an engineering manager is you also
help people find some of the more purely technical problems to solve, and those
are not necessarily hard in the theoretical computer science hard way, but
they&rsquo;re often hard in the, &ldquo;Oh we really need to clean up this particular piece
of technical data or this particular system&rdquo; and you as a manager, are actually
explaining the value of spending that technical focus to the rest of the
business and saying look, &ldquo;This is what this is going to enable. This is how
this is going to speed us up, or not slow us down in the future.&rdquo;</p>

<p>And that, I think it&rsquo;s a matter of really being specific about what the goal in
that clean up work is and trying to find measurable things that you can do once
you have done that. Some of it&rsquo;s also just about setting very hard guidelines
with &ldquo;we always spend a certain amount of time on this kind of thing because
this is important and this is the way we run our engineering teams.&rdquo; It&rsquo;s a
combination of those things.</p>

<p><strong>Audience 6</strong>: As you become more removed from the day to day delivery of code, do
you have any tips for ensuring code quality from your team members?</p>

<p><strong>Camille Fournier</strong>: That&rsquo;s hard. Well, perhaps you can use, a lovely product
like Code Climate, a word from our sponsors [laughs]. I do think that letting
go actually can be really hard. Some of it is setting standards and being as
clear as you can about the standards that you want the software to maintain.
That can be anything from someone like me, I&rsquo;m very passionate about testing, I
think testing is really important and so I try to set basic standards like,
&ldquo;Look, we should be very cautious about ever accepting pull requests or
whatever that don&rsquo;t have tests with them. Why isn&rsquo;t this code tested? Why
aren&rsquo;t we writing tests for this stuff?&rdquo; I think you can do things like that.</p>

<p>I think also some of it though is about, you hopefully have senior engineers on
your team that you&rsquo;ve trained, that they understand what good code looks like.
You want them to be teaching everyone on the team what good code looks like.
That is really one of those areas where it&rsquo;s not really your job as a manager,
although you probably still care, but you do want to make sure that senior
engineers feel like they have the ability to chime in and say, &ldquo;Hey, we want to
improve the standards in this code. We want to improve the standards in this
software, and here&rsquo;s what we&rsquo;re going to do to help with that.&rdquo;</p>

<p><strong>Audience 7</strong>: When you first transitioned from coding full time to management, did
you experience imposter syndrome and how did you deal with that?</p>

<p><strong>Camille Fournier</strong>: I wouldn&rsquo;t say that it was imposter syndrome exactly. I
will say that part of becoming a, especially a senior manager, is developing a
certain level of presence and being able to, the body language and the way that
you present yourself, and the way that you talk, and the questions that you
ask, and the things that you do, are actually important. That&rsquo;s actually a
pretty hard lesson to learn, and so I wouldn&rsquo;t say that it was exactly imposter
syndrome, but there was certainly a level of &ldquo;why am I not getting the respect
that I should get because of my title or whatever&rdquo; and I think some of that was
just, &ldquo;Oh yeah, I have to learn how to be in a room with my peers and be
productive and not undermine people and not be disruptive in certain ways, or
make my points in a way that people will hear them and they won&rsquo;t react
negatively. I would say for me, that was the harder lesson than imposter
syndrome. I don&rsquo;t feel like I had too much of that, that&rsquo;s never been my
problem.</p>

<p><strong>Audience 8</strong>: Hi. Thanks for speaking with us. Quick question on dealing with
promotions, especially as your team size starts to grow. You naturally have to
promote people within hopefully, but oftentimes you might find a couple of
candidates within your team that when one is a more natural leader, but they
both have the same aspirations, how do you generally deal with that? How do you
smooth that out?</p>

<p><strong>Camille Fournier</strong>: Yeah. I think the best thing that you can do &hellip; I think you&rsquo;re
lucky if you know the aspirations. I&rsquo;ve certainly had people where we did a
round of making tech leads, for example, and someone got very upset because
they weren&rsquo;t chosen and it was a shock to everyone involved because nobody had
any idea that this person was even interested. And so that was a little bit of
a mistake on our part of not actually spending the time to understand what
people wanted, to understand people&rsquo;s aspirations.  Part of what you need to do
is make sure you understand the aspirations.</p>

<p>Once you understand them, I think then if you think that you&rsquo;ve got a person
who has, frankly, better skills right now, maybe because they just have a
natural skill set, that&rsquo;s okay, but you want to give the other person coaching
and try to identify specific opportunities for them to develop some of those
skills and to learn some of those things.</p>

<p>Even though they&rsquo;re not necessarily being promoted to manager, maybe they can
be running certain projects. Maybe you can work with the new manager and say,
&quot;This person really does want to be in a management role and so we need to be
looking for opportunities for them to step up and take some leadership and push
themselves out of their comfort zone, maybe give presentations to the team&rdquo;,
whatever those gaps that you think that they might have, giving them a chance
to actually practice the job and fill those gaps is a good way to prepare them
for when the next opportunity arises. Now they really have the skills and the
confidence to do it.</p>

<p>All right, I guess that&rsquo;s it. Thank you.</p>

<p><em><em>Camille Fournier</em> is a Managing Director and Head of Platform Engineering at
Two Sigma. She is the former Chief Technology Officer of Rent The Runway and a
former Vice President of Technology at Goldman Sachs.</em></p>

<p><em>Fournier earned an undergraduate degree from Carnegie Mellon University and a
Master’s degree in Computer Science from the University of Wisconsin–Madison.
She is a maintainer of the Apache ZooKeeper open source project, writes the Ask
The CTO column for O’Reilly Media, and is a regular public speaker and advocate
for greater diversity within technology and leadership. Her book, <a href="http://shop.oreilly.com/product/0636920056843.do"><em>The
Manager’s Path</em></a>, was published by O’Reilly in early 2017.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Customer Gap</title>
    <author>
      <name>Kären Engelbrecht</name>
      <uri>https://twitter.com/scriberty</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/summit-2017-gordon-diggs-abby-armada/"/>
    <id>https://codeclimate.com/blog/summit-2017-gordon-diggs-abby-armada/</id>
    <updated>2017-11-09T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>In July, we hosted the first annual <a href="https://codeclimate.com/summit">Code Climate Summit</a>, a one-day
conference for leaders of engineering organizations who want to better
themselves, their processes, and their teams.</p>

<p>Today we&rsquo;re sharing <strong>The Customer Gap</strong>, presented by Code Climate&rsquo;s Director
of Engineering, <a href="https://twitter.com/GordonDiggs">Gordon Diggs</a>, and Code Climate&rsquo;s Customer Support
Lead, <a href="https://twitter.com/mygiantrobot">Abby Armada</a>. In this talk, you will hear about how we&rsquo;ve fostered
a positive, productive relationship between customer support and engineering. By
creating processes, and encouraging cross-team collaboration, we can combine our
strengths to best focus on customers of current and future products.</p>

<p><script src="https://fast.wistia.com/embed/medias/8ojplyuk0r.jsonp" async></script><script src="https://fast.wistia.com/assets/external/E-v1.js" async></script><div class="wistia_responsive_padding" style="padding:56.25% 0 0 0;position:relative;"><div class="wistia_responsive_wrapper" style="height:100%;left:0;position:absolute;top:0;width:100%;"><div class="wistia_embed wistia_async_8ojplyuk0r videoFoam=true" style="height:100%;width:100%">&nbsp;</div></div></div></p>

<h2>Transcript of talk</h2>

<p><strong>Abby Armada:</strong> Before we get into this, I wanted to highlight this customer quote, and following exchange between our customer support and engineering teams. So: &ldquo;Awesome dedication by the engineering and customer support team. Thanks, Jenna, Abby, and Ashley.&rdquo; And there&rsquo;s Jenna, who&rsquo;s on customer support, saying, &ldquo;You da best.&rdquo; And Ashley saying, &ldquo;No, you da best.&rdquo; So, you can see this is the kind of vibe your team can have by closing the customer gap.</p>

<p>I&rsquo;m Abby. I&rsquo;m the customer support lead here at Code Climate. And including me our awesome team is three people, one being remote. I&rsquo;ve been at Code Climate for over a year and in various customer-facing roles for about 13 years. I really like running and I really like eat tacos, but not at the same time.</p>

<p><strong>Gordon Diggs:</strong> Hi, I&rsquo;m Gordon. I&rsquo;m a record collector and I like to cook lasagna. I do sometimes do those two things at the same time. I lead Code Climate&rsquo;s engineering team and I&rsquo;m responsible for growing the team in both size, in terms of hiring and, for lack of a better word, &ldquo;mentality&rdquo; in terms of our processes and the kinds of ways that we work on things.</p>

<p>Engineering at Code Climate takes up about 40% of the entire company. So, we&rsquo;re a sizeable department. And Abby and I have actually been discussing and collaborating on the support and engineering relationship for over four years. So we&rsquo;re really excited to sort of have this culmination of a lot of the stuff that we&rsquo;ve talked about for so long and share some thoughts with you.</p>

<blockquote>
<p>Many companies list customer focus as a core value, but few engineers spend time talking to their customers.</p>
</blockquote>

<p>When you think of customer focused companies, you may think of companies like Amazon, where everyone trains in support center and answers calls, or Apple where the CEO regularly works on the support team. And so, many companies list customer focus as a core value. But few engineers spend time actually talking to their customers. So you have the big companies like Amazon and Apple, but many smaller companies that we found also list customer focus as a core value. A lot of people want to do this. They want to be a customer focused company, but it&rsquo;s really hard and it&rsquo;s time consuming.</p>

<blockquote>
<p>The customer gap: The delta between a stated customer focus and the reality of how engineering spends its time.</p>
</blockquote>

<p>And so we coined this term &ldquo;the customer gap.&rdquo; We define the customer gap as the delta between the stated customer focus and the reality of how engineering spends its time. Engineering tends to be very separated from our customers. But there are also gaps between your strictly customer-facing departments and your engineering team. If you can close the gap between engineering and those other departments, you can also work to close the customer gap.</p>

<p>Over the years we&rsquo;ve talked extensively about the gap between customer support and engineering and we think that in order to close that gap, there are things engineering should do, things customer support can do, and things that we should do together.</p>

<p>As a little bit of a visual aid, I made this kind of cheesy chart. But you can sort of see the idea here. You have your customers on the left. You have a small gap between them and your strictly customer-facing departments. And then a wider gap between those departments and your engineering team. And so, one of the things that this shows is that your customer-facing departments are doing a better job of closing the customer gap than you are already, and that&rsquo;s why they&rsquo;re closer to the users. And then there&rsquo;s this larger space between them and the engineering. So, if you can work on closing this gap on the right, then you can really work on closing the greater gap.</p>

<p><strong>Abby Armada:</strong> Here&rsquo;s a brief outline of what we&rsquo;re going to cover in this talk. We&rsquo;ll start by talking about ways to build customer empathy within your engineering team. And next, we&rsquo;ll talk about some examples of processes customer support can implement to work more closely with engineering. And lastly, we&rsquo;ll talk about closing gaps between engineering and other departments.</p>

<h2>Building customer empathy within engineering</h2>

<p><strong>Gordon Diggs:</strong> Building customer empathy within engineering. This is a really important part of the formula because if your engineers don&rsquo;t understand your users or their experience, or aren&rsquo;t bought into this idea of customer empathy and focus, it&rsquo;ll be a lot harder to close the gap. Ultimately, you really need to get them bought in.</p>

<p>And if I&rsquo;m being honest, we at Code Climate have this kind of easy. Our customers are software engineers so it&rsquo;s not a big gap for us, as engineers, to understand our users and their motivations. If we were some kind of printed product, a fashion company, or some kind of feminine care start up, we couldn&rsquo;t be sure that 100% of our team has something in common with our users and understands them.</p>

<p>So, we can go to conferences, and we can go to meetups, and we can meet people who use our product or who want to use it or who we think should use it because it would really help their workflows. So, this is just a little bit easier for us. But it is also a little bit of a trap. Software engineers are a very diverse group of people and we need to make sure that we don&rsquo;t project our own biases and assumptions when thinking about our users.</p>

<p>For a few examples: We at Code Climate are a team of Ruby engineers. We work at a small company. We have a good continuous deployment pipeline, and we generally have good coding practices as the nature of the work that we do. But people who buy and use Code Climate come from wildly different perspectives. A lot of them work on very, very large teams, and with tools that we don&rsquo;t use and understand as well as our own. So while we can get pretty far working with our idea of software engineering, we need to be aware of where that ends and where our customer&rsquo;s experience starts.</p>

<p>So, it&rsquo;s really important that customer focus and empathy is a cultural driver. And you need to build that empathy into your engineering culture. It&rsquo;s not enough to only think about focusing on your customers when things are broken or when your site is down. And so, what does that look like? What does it look like to build empathy into your engineering culture?</p>

<p>First, make your engineers talk to your customers on a regular basis. Include them in customer site visits. Put them on your sales calls. Make them work with support on debugging customer issues. And send them to conferences or meetups or if there&rsquo;s some kind of trade show that&rsquo;s relevant to your company, send them to that and put them at the table that you&rsquo;re sponsoring.</p>

<p>Secondly, we put every mention of Code Climate on Twitter into a Slack channel. So, good and bad, engineers can see what people are saying about Code Climate online. If we ship something and it&rsquo;s a poor user experience, or the CTA was a really weird color or something and people start complaining about that, we&rsquo;re going to see it. And similarly, when an engineer ships something that really resonates with a group of users and they start talking about it online, there&rsquo;s a nice boost there. So, you can kind of get both sides of the coin there.</p>

<p>We also put engineers on the frontline of responding to our community in both our community slack group and on our open source repositories. If you open an issue or a pull request on one of our repos, it doesn&rsquo;t go to a member of our support team. It goes directly to an engineer who&rsquo;s responsible for triaging that issue and finding the solution.</p>

<p>Our engineers also run our status page. If our site goes down or our service is in any way degraded, they&rsquo;re the ones who are responsible for keeping our users up to date about what&rsquo;s going on. Obviously, they collaborate with marketing and customer support on these updates to make sure that they are of the highest quality that they can be, but ultimately, the timing and the content is up to them.</p>

<p>And lastly, watch your users use the product. One issue that we have as engineers, particularly product engineers is that we know the code that goes into the site and we know that if a page is slow or a user experience is weird, it&rsquo;s often because the code behind it is complicated. And we bring this bias into using our own product that, &ldquo;Well, this page is slow because there&rsquo;s all this nested logic in the templates and stuff.&rdquo; But your users don&rsquo;t understand that. They don&rsquo;t have any of that. And watching them interact with your product, watching the way that they use it, and where they get frustrated, will really help eradicate some of that handwaviness.</p>

<p>So, as with most cultural efforts, building empathy is harder on bigger teams.</p>

<p><a href="/blog/summit-2017-panna-pavangadkar/">Panna actually touched on this a little bit earlier.</a> So, if you can start when your team is small, that&rsquo;s better. The bigger your team is, the more people you need to convince to buy in to this idea of customer focus and empathy. So, if you&rsquo;re at a small company, that&rsquo;s great. You&rsquo;re in a really prime position to effect change across your team. If you&rsquo;re at a larger company, all hope is not lost. You can start with a small subset of your team, find a pilot team, and have engineering managers of that team spread their success laterally throughout the organization.</p>

<p>And it&rsquo;s really important, I really want to mention that it&rsquo;s not enough to silo this empathy. You can do all you want to build customer focus within your engineering team, but it&rsquo;s also important to work closely with your support team. And Abby&rsquo;s going to talk a little bit about some of the ways to do that.</p>

<h2>Helping each other</h2>

<p><strong>Abby Armada:</strong> So, you have to work together. There are a couple of solutions we created here at Code Climate to help both the engineering and support teams be successful at this. These solutions may seem obvious in some ways but the execution and upkeep is essential for it to work well and close the gap, which in turn closes the other gap that exists between engineering and your customers.</p>

<p>The first of these solutions on our side was addressing escalations, which is when a customer&rsquo;s problem has gone past a scope of troubleshooting and knowledge of the support team and requires a solution from an engineer or someone else. I&rsquo;m sure many of you here have had to deal with customer escalations in one way or another, and it might have been a thorn in your side. We did a lot of work to improve this process for both of our teams, which ultimately has made our customers way happier.</p>

<p>Our main channel of support is email, then it trickles through to Twitter, Slack, and sometimes GitHub Issues. This is where all of our escalations come from.</p>

<p>So, how did we address escalations before? Engineers worked on escalations on a weekly rotation. This wasn&rsquo;t ideal for anyone. For the incoming engineer, there wasn&rsquo;t a lot of context for existing open issues. Plus, it seemed like a giant chore that was an interruption to their regular work. On support&rsquo;s side, it&rsquo;s hard to ramp up someone for this work, and it&rsquo;s especially difficult to form a good working relationship with your new engineer for only a one-week rotation.</p>

<p>We didn&rsquo;t have a great way of tracking this work, or a consistent process for handing off open issues to the new engineer, or giving enough context for the problems. Prioritizing issues did not exist at all, and we kind of thought they would just figure it out. This led to everyone drowning in a sea of confusion and sadness.</p>

<p>To fix this we came up with a couple of solutions. Instead of a weekly rotation, we now have a dedicated support engineer for a quarter. This solved that problem of feeling like they&rsquo;re interrupting other work and gives the engineer a chance to fully work and focus on escalations. It also builds a great rapport between engineering and support because we get to know each other for a quarter.</p>

<p>And we broke down our escalations by severity, which gives us an actual prioritization system that makes sense to both teams. There are now four levels of severity, one being the highest and four being the lowest. This isn&rsquo;t a new concept by any means, but implementing something concrete was the most important part of the solution.</p>

<p>We also documented how to respond to each severity, both as a support person, and as an engineer, and holistically as an organization. This is written in our company handbook so everyone can see and have the knowledge. We also have concrete examples in the doc for easy reference. So, if someone is confused, they can look at the doc examples and know how to assign an issue a severity.</p>

<p>And lastly, we started using a GitHub repo and issues to track and update customer escalations. Everyone in the company already knows how to use GitHub, so implementing this part was the easiest.</p>

<p>This is an example of our severity documentation. You don&rsquo;t need to read the whole thing – and the people in the back probably can&rsquo;t anyway – but you can see the structure of how we define severities. In this case, this is a severity three, normal/minor impact. It&rsquo;s something that&rsquo;s like a moderate loss of application functionality that doesn&rsquo;t really affect any of their other workflows. It matches the description. And then the examples live underneath. In this case, a customer reports a bug in an engine that&rsquo;s kind of broken but doesn&rsquo;t have any effect anything else that they&rsquo;re doing. And then the response plan underneath details what both the customer support person and the engineers can do to sort of solve this issue.</p>

<p>Another change is that severity ones are treated differently than other severities within our organization. A severity one is a major issue. So, for example, if a customer&rsquo;s instance of Code Climate Enterprise is down, we flag it as severity one and it requires all hands on deck to fix.</p>

<p>In past quarters, we found that the burden of solving these types of escalations is hard for a single escalations engineer. They often had to ask for extra help anyway. So we changed severity ones to be treated as production incidents. Support escalates directly to our engineering teams existing PagerDuty rotation. We have a fairly robust alerting pipeline for codeclimate.com, so most issues are caught by other alerts before they even get to support. It was pretty easy for us to integrate these other issues into that rotation. Distributing the work amongst those who are already on call helps solve severity ones more quickly and taps into existing expertise.</p>

<p>After adopting the aforementioned quarterly rotation, it helped highlight gaps in our own team&rsquo;s knowledge about troubleshooting in other parts of the product. Thus, engineering has started leading proactive education workshops to teach concepts that will help us troubleshoot future issues. For instance, one of our support engineers noticed that we were pretty much escalating every single issue that had to do with our enterprise product. He set up a workshop to talk through troubleshooting concepts and how engineering looks at the same issues. This helped the support team work through more enterprise issues and lessen those types of escalations.</p>

<p>Engineers really benefit from this, too. Having them explain their work and their contributions to the product helps them grow and build empathy, and again, really strengthens that great rapport between your support and engineering teams. And informing the support team empowered us to troubleshoot and triage more effectively and even nipped future escalations in the bud.</p>

<p>Here&rsquo;s our resolution time for escalations per month. So, after a slight rise due to those new processes, especially proactive education, we were able to have a fast mean time to resolution to customers than before and our customers, obviously, are really happy about that. And here are our escalations per month. You can see the tangible benefits of when we adopted these new processes and it&rsquo;s because of that quarterly rotation, better processes around triaging, and proactive education. On average, our monthly escalations have gone down month to month, and that&rsquo;s great.</p>

<p>Having worked on our escalation process, the next thing we did was take a look at the product engineering and support relationship. It&rsquo;s a common problem that support doesn&rsquo;t have the full picture of what&rsquo;s being developed. I hear this all the time from other support professionals that I interact with every day, and this is a problem for everyone.</p>

<p>Even on a small team, communication is oversaturated. There are too many Slack posts and GitHub issues, and this is not sustainable at all. There&rsquo;s just too much to keep up with. Last quarter, we established a weekly customer support and product meeting to sync up about work being done that week, as well as talk about things coming through the pipeline. Instead of trying to keep up with endless notifications, now we talk face-to-face and it&rsquo;s much easier.</p>

<p>Personally, this is my favorite meeting I have every week because it&rsquo;s really productive for my team and the product team, and it really gives my team great perspective on what&rsquo;s happening in our organization. So, we talk about work in progress. What&rsquo;s the progress on last week? What&rsquo;s happening this week? We cover any upcoming releases. We get to answer the question of what exactly are we shipping and when? And how does it affect our customers? Then we talk about any customer-facing communications needed like updating docs, release notes, as well as inquiry response to incoming new customer questions. And lastly, we talk about feature requests. I&rsquo;ll cover that in a little bit more detail in a bit.</p>

<p>This has helped our teams a lot. I share the most important knowledge back to my team since one of my people is remote, it&rsquo;s good that we can be all on the same page about what&rsquo;s happening that week. And it also helps us action any internal work that helps that product work. And it has also stopped confusion about what exactly is being released. We&rsquo;re more confident and thus can help our customers better. And lastly, it fosters trust, again, between support and product. We know what&rsquo;s going to be released and how to handle it.</p>

<p>Now that we have that open channel of communication with product and engineering, we decided to tackle the beast; feature requests. We all want to be the type of company that welcomes customer feedback, and feature requests, and actually actions on it. But I think this is the hardest gap to close but we&rsquo;ve made a lot of steps here at Code Climate to do so.</p>

<p>Before, support had ways to catalog feature requests, but no way to surface them in a meaningful way for people to action them. So, we had a very bad GitHub repo, then a very bad Trello board, and – hey, Gordon, did you look at any of those ever?</p>

<p><strong>Gordon Diggs:</strong> Ehhhhhhh…</p>

<p><strong>Abby Armada:</strong> Yeah, me neither. There&rsquo;s a limited process for both of the repos and the Trello board, which also housed bugs alongside feedback. Someone would make an issue, which would live on in perpetuity. And every time a request came up again, someone would comment on it and push it to the top. It sounds good in theory, but no one ever looked at them. Just having the tools isn&rsquo;t enough. We thought that switching to Trello would solve the problem of stale, sad feature requests. But, in fact, you just needed a process.</p>

<blockquote>
<p>The more you can get feedback into the eyeballs of your company, the better. You have to be loud to get this actioned.</p>
</blockquote>

<p>We created a feedback repo on GitHub, again, which feeds into a Slack channel, then we talk about important feedback during that product meeting I mentioned before. The more you can get feedback into the eyeballs of your company, the better. You have to be loud to get this actioned.</p>

<p>This is what that GitHub repo looks like. You can see the different issues opened by the people on our team. And we use labels to easily identify the status of each feature request. You can see stuff that&rsquo;s been actioned, what needs to be reviewed, and the different parts of the site that the feature request is about. And now these are pure feature requests. They are not bugs or anything pertaining to escalations. These are all nice to haves and legitimate product feedback from our customers.</p>

<p>Of note, this repo is completely internal. There&rsquo;s no way for a customer to directly add feedback to this repo. Only people at Code Climate can do this. And then the feedback is curated by me. We have an issues template that asks a bunch of relevant questions. If the feedback doesn&rsquo;t clearly answer why a customer is asking for a feature or isn&rsquo;t detailed enough, it gets rejected. This curation process keeps the board fresh and keeps my finger on the pulse of what our customers want.</p>

<p>This is that Slack channel with that piped in feedback activity. It has all new issues and comments on old issues. And they all get fed into this channel that anyone in our company can join. So, in this screenshot, Jenna opened an issue, pinged Noah to get his thoughts, which he then shared to the issue itself. Loud is good.</p>

<p>As I mentioned, we also talk about the feedback issues in that weekly product and customer support meeting and see if they&rsquo;re still relevant and see where they fit within our product roadmap. Sometimes feedback and feature requests can alter a product roadmap, giving us ideas for something we didn&rsquo;t even consider before. And through all of this, we&rsquo;ve seen an immense improvement in adoption of customer feedback within product development. In fact, after we adopted these processes, 25% of feature requests were actioned by our product team, which is a huge improvement from basically zero.</p>

<p>You&rsquo;ve heard me talk a lot about what we did at Code Climate to close the gaps between engineering and support, but these solutions might not necessarily work for your specific teams or solve the types of problems you&rsquo;re facing between your customers, support, and engineering team. As an engineering manager, it&rsquo;s up to you to try and work in tandem with your support team to solve these problems. Collaboration, communication, and iterating on processes together are the key ways to do this and it leads to happier customers overall.</p>

<h2>Closing the gap to other departments</h2>

<p><strong>Gordon Diggs:</strong> We&rsquo;ve talked about how to build customer empathy and we&rsquo;ve talked about some of the processes that support and engineering have worked on together. But what about the other customer-facing departments in our organizations? Your customers move through life cycles, and engineering should follow them.</p>

<p>Before your customers are even your customers, they interact with your marketing and with your marketing team&rsquo;s efforts. At Code Climate, we dedicated an engineer for a whole quarter to help build automation for our marketing lead pipeline. He did this by supplementing leads with data from a variety of sources and piping it all into our CRM. He learned about what makes leads more qualified from a marketing perspective and our pipeline is fuller and faster than it&rsquo;s ever been. He also learned a lot about our user personas and our segments. And this ties back to that idea of the diversity of our users from before. He came back from the marketing team with a better understanding of our users and where they come from. Dedicating a full-time engineer to this rather than hiring a contractor or farming out to buying some product, ensures that we built this in the right way and in a way that we can easily maintain and extend moving forward.</p>

<p>Sales is a really important part of most businesses, but particularly at a SaaS product we need to have a sales team. And sales people usually aren&rsquo;t engineers and may not be able to articulate the same engineering concepts. But they are very good at learning and they can really learn from your engineers. And there are a few ways that engineers can get involved with your sales department.</p>

<p>The first and maybe most obvious of these is building features for customers who are in your sales pipeline. Putting engineers on your sales team means that you can more quickly action the high value projects that will sign customers right away. So, we identified three key features blocking sales and then we built them. And additionally, in just having the conversation about what features are the users that you&rsquo;re talking to, what features do they really want? In just having that conversation, we clarified our product direction and have a clearer idea of where we need to go.</p>

<p>There&rsquo;s a very, very important note and caveat to this. Some features will be too big for this setup and some will be in conflict with your existing product roadmap. I&rsquo;m not suggesting that you give your sales people carte blanche to implement features in your product. But, working through the discussion of the features that they want to build and finding the compromises will really help grow your business. It&rsquo;ll help clarify your roadmap, and it&rsquo;ll sign customers, which is really good.</p>

<p>So, another sales engineering activity is reviewing leads technically. This is a little bit specific to Code Climate as a highly technical product, but we have an on-premise enterprise product and we want to be sure that we only deploy it to platforms and customers that will be successful. Doing this once a customer is about to sign a contract causes the sales process to lose momentum, but if you review the technical requirements – for us that&rsquo;s things like virtualization platform, version control system, programming languages, that kind of stuff – if you review that earlier in the process, your leads will be more successful.</p>

<p>Pulling engineers in to do this on an ad hoc basis was something that we used to do like, &ldquo;Oh, yeah, just go grab someone off of product to review one of these leads.&rdquo; But it meant more prep, more interruption, and generally lower quality reviews. So having people on your sales team ready to do those reviews is a really big strength.</p>

<p>Similarly, installing and setting up the product with customers gives engineers a really good sense of what your onboarding experience is like. In many cases, it&rsquo;s been years since one of your engineers signed up for your product and, most likely, they&rsquo;ve never done that with money on the line. So, having them sit down and understand what the customer is going through helps them build it better in the future and it helps get the customers up to speed faster. This also ties back to that idea that I was talking about earlier of watching your users use the product. This will really help eradicate some of those unconscious biases that your engineers bring to your onboarding experience.</p>

<p>Lastly, putting customers in touch with your engineers directly build rapport. It&rsquo;s rare that you can jump on a sales call with a company and there&rsquo;s an engineer there to tell you about how they built the product, particular features that they really like, that kind of stuff. It&rsquo;s also rare that you can be in the Slack group and DM an engineer directly to ask them a question about how do I configure this? How do I work with this? And so, having that engineer there really helps build this rapport.</p>

<p>Abby talked extensively about customer support and shared lots of really good thoughts, but I want to throw this department up here because escalations were where we started. Both Abby and I started talking about this customer support engineering thing, and it was the first place that we experimented with this quarterly rotation idea. I also want to mention that being on the support team doesn&rsquo;t mean just answering escalations and providing technical knowledge to the support team. A successful setup of an engineer on a support team means also building the features that ensures that those customer issues don&rsquo;t happen again.</p>

<p>So, in the same way that sales engineers build features for customers in the sales pipeline, your support engineers should collaborate with product and engineering to action the features that will really help prevent future issues. So, you can see that drop in escalations per month, and a lot of that is because we found the patterns and where users were running into trouble and where they were writing into support, and built better experiences for them.</p>

<p>What about once someone is a customer but their experience isn&rsquo;t broken? So, they&rsquo;re not writing into your support team. Customer success works with customers who are configuring the product, who are discovering how to use it, and who are using it in their workflows everyday. Your engineers can help train users on how to use your product. They can go do customer visits. They can sit down and eat lunch with your users and show off their work or talk about things that are coming up that they&rsquo;re working on.</p>

<p>I really love training customers, and working with them, and seeing them get excited about a feature that someone on my team built, or seeing them understand a complex part of our system. And if your customers are engineers like ours are, that&rsquo;s even better because they&rsquo;re going to want to know what it&rsquo;s like, what the special sauce behind Code Climate is.</p>

<p>So, in both customer success and sales, the engineers are both training you customers and your representatives about the product. Your representatives may not know about the newest features or what&rsquo;s in development. And if they do, they may not know about all of the edge-cases or the best applications for these features.</p>

<p>And ultimately, working with customers and with other departments makes your engineers more well-rounded. They&rsquo;re still going to be great product engineers. They&rsquo;re not going to stop wanting to build features. It&rsquo;s fine. But they&rsquo;re also going to be better at sales. They&rsquo;re going to be better at support. They&rsquo;re going to be better at marketing. And this will set them up for success both in your company and in their careers at large. We&rsquo;re lucky because our quarterly rotation lends itself well to putting engineers on other teams and working directly with other customers.</p>

<p>Engineers also remember their customer interactions. And it informs the way that they build things in the future. They remember seeing that customers missed a CTA or ran into an error because of a configuration problem. And this memory or this interaction lingers with them the next time they build a feature or talk to another customer. And it really informs the way that they go about their work in the future. So, we&rsquo;ve seen that engineers who do a tour on the customer support team come back to product and have a new way of looking at building product because they&rsquo;re thinking about customers and they&rsquo;re focusing on them more. To restate that, more experience with customers leads to better features.</p>

<blockquote>
<p>More experience with customers leads to better features.</p>
</blockquote>

<p>Engineers don&rsquo;t like to be interrupted. We&rsquo;ve talked a lot about building processes to reduce this interruption. Getting into flow is a really important thing for engineers. All the engineers in the room are nodding their heads. And we, as managers, can&rsquo;t pretend to change that. We&rsquo;re not going to change flow. We&rsquo;re not going to solve that problem. But understanding why your support team is bugging you to fix issues and understanding their motivations and that they&rsquo;re advocating for your users will really help your engineers grow and will make your product more stable.</p>

<p>And I&rsquo;ll also mention, we made these slides and we did a rehearsal of this talk. And one of my engineers is like, &ldquo;I don&rsquo;t like the word nagging on this slide because I think it&rsquo;s a negative thing.&rdquo; And it is. It&rsquo;s only nagging if there&rsquo;s a problem and if it&rsquo;s something that they don&rsquo;t really want to be doing. Talking to support more often, doing these weekly check-ins, having the people there for them to discuss escalations with, will prevent the unnecessary interruptions and it won&rsquo;t be nagging. It&rsquo;ll just be talking to you. Support will be talking to you for a reason.</p>

<p><strong>Abby Armada:</strong> Support doesn&rsquo;t like to be interrupted either. We&rsquo;re doing work too. So having dedicated time to talk to engineers really helps everyone and your customers.</p>

<p>And here&rsquo;s that visual we presented before except we&rsquo;ve closed the gap significantly. And our engineers are close to our customers than ever before.</p>

<p>Let&rsquo;s review some takeaways and what you can do.</p>

<p><strong>Gordon Diggs:</strong> Build empathy within your engineering team to foster a focus on your customers. Know where the gaps are between your engineers experience and your customers, and then close them. And start small. If you have a small engineering team, that&rsquo;s great. Get everyone onboard right away. But if your organization is larger, find a pilot team and then recruit your leaders within engineering to spread their success to others.</p>

<p><strong>Abby Armada:</strong> Make sure your processes promote good collaboration between support and engineering. Don&rsquo;t be afraid to experiment and try new things and talk to each other. You&rsquo;ll learn a lot about the ways that you can work together and make your customers happier.</p>

<p><strong>Gordon Diggs:</strong> Include engineers in every stage of your customers&rsquo; life cycle. Find a way. Go to those teams in the strictly customer-facing departments and say, &ldquo;How can engineering help here?&rdquo; From marketing to sales to support to customer success, find out where the engineers can help and then put them on the teams for a significant amount of time.</p>

<p><strong>Abby Armada:</strong> At the end of the day, if you&rsquo;re truly customer focused, then happy customers will mean a happy business.</p>

<p><strong>Gordon Diggs:</strong> Thank you. Obviously, Abby and I have lots of thoughts on this and we&rsquo;ve talked about this for a long time. If you have thoughts about any of this stuff, please come talk to us. If these sound like particularly interesting problems to you that you want to help us solve, Code Climate is hiring for both engineering and support roles. So, please come talk to us. And yeah, thank you for coming today.</p>

<p><strong>Abby Armada:</strong> Thanks!</p>

<p><strong>Gordon Diggs:</strong> Thank you for listening to us.</p>

<p><em><a href="https://twitter.com/GordonDiggs">Gordon</a> is the Director of Engineering at Code Climate. He spends his days managing and growing the engineering team. When he is not at work, he can usually be found at the nearest record store or at home cooking lasagna.</em></p>

<p><em><a href="https://twitter.com/mygiantrobot">Abby</a> is the Customer Support Lead at Code Climate, and is passionate about great customer experiences. She’s currently working on developing her team, scaling support infrastructure, and finding the perfect taco in New York City.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Building a developer culture with InnerSource</title>
    <author>
      <name>Kären Engelbrecht</name>
      <uri>https://twitter.com/scriberty</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/summit-2017-panna-pavangadkar/"/>
    <id>https://codeclimate.com/blog/summit-2017-panna-pavangadkar/</id>
    <updated>2017-11-03T16:30:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>In July, we hosted the first annual <a href="https://codeclimate.com/summit">Code Climate Summit</a>, a one-day
conference for leaders of engineering organizations who want to better
themselves, their processes, and their teams. Starting today, we&rsquo;re excited to
start sharing videos and transcripts of the six great talks. First up is <a href="https://twitter.com/pannasingh">Panna
Pavangadkar</a>, Global Head of Engineering Developer Experience at
Bloomberg LP, with her keynote: <strong>Building a developer culture with
InnerSource</strong>.</p>

<p><script src="https://fast.wistia.com/embed/medias/huvt4bp9yk.jsonp" async></script><script src="https://fast.wistia.com/assets/external/E-v1.js" async></script><div class="wistia_responsive_padding" style="padding:56.25% 0 0 0;position:relative;"><div class="wistia_responsive_wrapper" style="height:100%;left:0;position:absolute;top:0;width:100%;"><div class="wistia_embed wistia_async_huvt4bp9yk videoFoam=true" style="height:100%;width:100%">&nbsp;</div></div></div></p>

<h2>Transcript of talk</h2>

<p>I&rsquo;ll just start by introducing a little bit of my background, how I got here, and why I do what I do today.</p>

<p>I run something that we call Developer Experience at Bloomberg. How I got there is a slightly long-winded story so bear with me.</p>

<p>I started off in the &lsquo;90s working as a late night lab assistant in India, which then led me to supporting the manufacturing sector and then the financial sector. When you joined as a consultant, you literally did everything. You were an app developer. You were a system administrator. You were a DBA. You were the person who wired up the cables and got into the machine room and did everything.</p>

<p>That then led me to deciding to follow databases. I became a database consultant and moved to Asia in the financial sector. Long story short: I landed up here in New York City, working in the financial sector again, focusing on application development and databases, and then system engineering, and performance engineering. This long-winded story comes back to why it puts me in this unique position for Developer Experience, as I discovered that – going through these various roles in these various countries, encountering different types of developers – the one thing that I developed a lot for was empathy.</p>

<p>I realized that every single personality type in computer science, varied system administrators, DBAs, app dev, web developers, have their own personality types. We all have our own quirks, our own religion, and do things in a very particular way that&rsquo;s unique to us. So &ldquo;it&rsquo;s my way or the highway&rdquo; and &ldquo;I&rsquo;m god&rsquo;s gift to mankind&rdquo;.</p>

<p>That made me develop a lot of empathy that led me to saying, well how can we make our developer experience across the spectrum of people different? Because we all actually want to work with each other. It&rsquo;s not that we don&rsquo;t want to work with each other. But we are so myopic in the way that we want to develop our piece of the puzzle, that we don&rsquo;t see the other person&rsquo;s point of view.</p>

<p>Two and a half years ago, I got approached by Bloomberg to try and explain how should we be developing software. I had been at Goldman Sach&rsquo;s for 16 years and done various, various roles. And as a tech fellow at Goldman we were driving technology in a particular way. When I started talking to Bloomberg it was really about how can we continue to embrace change, and keep our developers excited, and continue to develop quality software, and be the product leader that we have been for so long. So we created this team called developer experience.</p>

<p>So basically, my team does anything and everything from owning the tools that are required by the developers, the process, the framework, the training, the documentation. I even got a, this is a real story, I even got asked if we were responsible and we would take care of having enough male bathrooms. But don&rsquo;t quote me on that one.</p>

<h3>INNERSOURCE: LEVERAGING OPEN SOURCE BEST PRACTICES IN THE ENTERPRISE</h3>

<p>Let me make a one second pitch for Bloomberg: Since the majority of people here are from New York City, you&rsquo;ve obviously heard of Mike Bloomberg. Anybody not heard of Bloomberg the product company? All right. Awesome. So just to make sure we&rsquo;re all on the same page, we&rsquo;re a product company based in New York City predominantly, and we&rsquo;re in the business of providing information. 5,000 engineers across the globe who work on developing the platform on Bloomberg Terminal. You&rsquo;ve heard of Business Week and you&rsquo;ve heard of the Bloomberg media news outlets, etc., but our predominant product is the Terminal.</p>

<p>I said we were in the business of providing information. As you can imagine, it&rsquo;s been 30 years of development that have gone into building the Terminal, to be able to provide very high touch individuals with specialized functions to get the information they need. Whether it&rsquo;s news, trade related, analysis, portfolio management, to finding out the current events that are happening. So we have to really, really work to provide low latency information and also a broad variety of information.</p>

<p>You can imagine that everyone is working on different functions. Could be for the equities business or it could be for the news media or it could be for some of the back-end functions, just to develop this Terminal itself.</p>

<p>When I got in, what we discovered was that we collaborated a lot. There was a lot of collaboration, but we collaborated the old-fashioned way. Spoke to people. Put in tickets for other people to do things. We were transparent about the fact that your ticket is going to wait for me to finish what I&rsquo;m working on, or it has to get prioritized by whichever product owner of whichever team I&rsquo;m working in.</p>

<p>I started exploring the concept of how can we bring open source best practices in house, inside the enterprise. As we started exploring that, we called it &ldquo;collaboratively sourced&rdquo; or we called it &ldquo;internal open source&rdquo; and finally some of our active developers came up with the fact that hey, this thing already exists in the market. It&rsquo;s called InnerSource.</p>

<p>Anybody hearing InnerSource for the first time? Cool. It wasn&rsquo;t a well-known term. We hadn&rsquo;t heard about it. We were just wanting to bring the best practices in house. After going through a few iterations, we settled on saying fine, we&rsquo;ll call it InnerSource. Of course, having spent the past 20 years in the industry, my fear was InnerSource would get thought of as developers outside the company working on it. But in any case, supposedly O&#39;Reilly had coined the term 17 years ago, so the term existed.</p>

<p>About 17 or 18 companies, decided to collaborate to see if we could make InnerSource a much more popular term. But more importantly for me, was really bringing those practices in house and sort of breaking down the barriers that exist within an enterprise.</p>

<p>What I discovered is: Most enterprises have grown up organically over the years. It&rsquo;s very easy in a startup to start with a clean, fresh slate and work on things, and be open about it, be transparent about it, be able to look at each other&rsquo;s code, etc. In an enterprise that&rsquo;s evolved over 20 years, you&rsquo;ve grown up in silos. Thing have got added on as they got added on, so people hold on to their little bit of the codebase. That&rsquo;s how they&rsquo;ve grown. What we needed to do was figure out a way of breaking down those barriers and really embracing some of the benefits.</p>

<p>I list out the benefits here – transparency, collaboration, innovation, community, reuse, mentorship, self help – but there are obviously more benefits to open source than these. What I was really focusing on for our developers is collaboration and a lot of the community and the camaraderie that can be built up, so that we have empathy for each other. We are able to work with each other without getting protective about it. That&rsquo;s pretty much the theme that started it.</p>

<h3>HOW</h3>

<p>So how did we go about it? Initially, it was really just talking about the concept. Just like how I asked you, who has heard about InnerSource and a lot of you hadn&rsquo;t. When I spoke about collaboratively sourced, it was met with of course, a lot of skepticism. There was a lot of critiques. It was like it&rsquo;s just not going to work. Like, why the hell would we do this? We are already working within our teams. We have enough work to be done within our teams. So the first thing was really about introducing the concept and saying, at least just be open to the idea that I can go across an enterprise team, organizational, artificial boundary and look at somebody else&rsquo;s code and add value or vice versa. Have somebody else who may have something to offer, may have some sort of expertise, or just be interested in that area, to come and look at my codebase.</p>

<p>Just sharing that idea and getting the excitement created within the development community was the first step that we went about. I did think about, and everybody asked me, what sponsorship do we have? Do we have management buy in? What I had done was just tested the waters, to say, if I go and ask for permission, will it get squashed down or should I push for this collaboration social experiment and beg for forgiveness later?</p>

<p>Fortunately, one of Mike Bloomberg&rsquo;s business principles state that take the risks and beg for forgiveness if needed. So that&rsquo;s how we decided to say let&rsquo;s start getting the developers excited about the fact that hey if you are waiting on somebody to do something for you, you can offer to help them out. In the offering to help them out is where the whole drama lies, but the concept was well understood.</p>

<h4>Identify early adopters</h4>

<p>Once the concept got understood and a few of the developers started embracing the concept, that&rsquo;s when we said, let&rsquo;s identify early adopters. I was in this unique position to say, I own the tools. I own the tools that developers use, so let&rsquo;s open up these tools and if the next person who asks me for a feature, we&rsquo;re going to tell them that they can help us and contribute to our codebase and make that happen for themselves.</p>

<p>Two and a half years later it sounds way easier to say what I&rsquo;m saying. Trust me, all my team leads hated me. Literally hated me. They were like, why is she bringing all this into this? We were functioning just fine, right? Because I mandated that we open up our own codebase.</p>

<p>So I identified early adopters. In your organizations it really is about finding out what&rsquo;s that sweet spot, what&rsquo;s the low hanging fruit, which of the less resistant applications, functions, codebases would be able to accept external contributions. Then, it really was about mobilizing people to actually start to engage and contribute.</p>

<h4>Engage (at all levels)</h4>

<p>This is where we were slightly unique because we already had a few years ago started off with engaging our development community a lot more. We have people who are called partners, we have people who are called champs, we have people who actually within their own areas, are responsible for being the people who engage with the other teams, continue to collaborate with the other teams, as well as pushing best practices. So it was really leveraging this champ/partner community. We have tech reps as well, really embracing and getting them to embrace it and then they started engaging with us to say, can they start contributing to these early repositories because it really was setting precedence.</p>

<h4>Evangelize</h4>

<p>Once we had the precedence set, because we had a few repositories where people from other teams could now contribute code, we could then start to evangelize a little bit more and even tell middle management, or our managers, or our senior management, that this concept can work. We just have to push the envelope a little bit. So really it was the engagement on all levels and the evangelization.</p>

<p>This is really about tooting your own horn for the project itself. So for InnerSourcing to be accepted, for people to start understanding the terminology, we created an internal function called sauc. It&rsquo;s just a play on Innersource but it&rsquo;s called sauc, so when you type in sauc it&rsquo;s nothing but a list of repositories with pull request, books, help wanted tags, and it&rsquo;s just a very, very simple gaming methodology. Not to call out people, but to call out projects that have lent themselves to being contributed to as well as extended.</p>

<h4>Sponsorship</h4>

<p>That&rsquo;s a key, but in our case, we got sponsorship way later into the game when we had already sort of proved concept, to say this can actually work.</p>

<h3>AFFECTING CHANGE</h3>

<h4>Organizational structure, culture and dynamics</h4>

<p>So I mentioned change is hard. Tell me to walk on the left side of the road when I get out of Penn Station and I go berserk because I have a set pattern. I walk on the right side of the road to get from Penn Station to Park. That&rsquo;s just a simple example. Try telling any one of you to change the way you write code or change the way you do certain things and you&rsquo;re going to be questioning why it needs to change because it works for you. The way I develop software on my laptop works for me, why the hell should I change anything, right?</p>

<p>It was really, really hard to get people to accept the fact that now we are going to introduce the ability for other people can contribute to your codebase. You can contribute to other people&rsquo;s codebase. Keep in mind, I&rsquo;m talking about history. People at Bloomberg have been around for 20 years. So they have set patterns. They have ways of working. It&rsquo;s not like we&rsquo;re getting in or changing 5,000 people overnight. When new people come in, of course they want to be able to bring their new best practices with them. Being able to talk about the fact and getting them comfortable with this organizational structure should not be the barrier which holds you from going across organizational boundaries, which is something that we really had to work on. It was a lot of talking. A lot of sharing stories and convincing people that this is good for them.</p>

<p>There is a lot of pride in the work that we bring, the work that we have done. Sure, I took some short cuts at some point in time, but I had pride then and now, because I don&rsquo;t want to feel exposed, I&rsquo;m reluctant to open it up and allow people to critique it or comment on it.</p>

<p>So, code pride is one of the things that I found was the biggest road block because people have evolved over time and they have become better, they have embraced new things, so if you go back and open up something that somebody wrote 15 years ago, and start saying this person doesn&rsquo;t know what the hell he was writing about. Yeah, maybe he didn&rsquo;t. Maybe he or she had no clue what they were doing at that point in time, but they have evolved now.</p>

<p>What became really interesting is creating a culture where it was okay to talk about code that was written earlier, but it was not okay to say nasty things. It&rsquo;s easier said than done.</p>

<p>We use IB, Instant Bloomberg, as our internal chat. I can&rsquo;t police multiple chat rooms to say people shouldn&rsquo;t say nasty things to each other. I&rsquo;m guilty of saying, this is just ridiculous stuff, I&rsquo;m not even going to bother commenting on it or they shouldn&rsquo;t have done it this way, but we had to start creating cultural awareness that you cannot bite somebody else&rsquo;s head off, you cannot be nasty, and creating the informal policing.</p>

<p>I talked about champs. I talked about tech reps, I talked about evangelists. Creating that culture where developers feel that they can hold accountable other people who may be getting vicious, or even slightly aggressive, on IB or mail or even comments in the codebase itself. Really embracing the fact that you&rsquo;re coming from different places and you&rsquo;re contributing at different times and therefore, passing a judgment is not acceptable, and we have to find more constructive ways of changing that codebase and making that change.</p>

<h4>Accepting contributions is hard work</h4>

<p>As soon as we started getting over that barrier, the next thing was, well, accepting contributions is hard work. And then taking ownership of somebody else&rsquo;s contribution, because I may still own the product and I&rsquo;m responsible for when the tool breaks. It then became the concept of saying, well we have to then define how am I going to discuss the feature request coming in, or how am I going to deal with the idea, the suggestion, the code contribution coming in, and what are the rules of engagement? What are my guidelines? Or, what&rsquo;s my point of entry? And what are we willing to engage with and what are we not willing to engage with.</p>

<p>Now, in the whole Agile transformation, it&rsquo;s tough because you need the product owners to buy in, you need the team to buy in, you need to be able to set aside the time to accept contributions that weren&rsquo;t part of your regular stream of work coming in.</p>

<h4>Trusted committers</h4>

<p>This is where we started to talk about expanding our trusted committers beyond the organizational or product team. Could we grow our list of trusted committers beyond the organizational boundaries? This was really, really hard work. It of course meant that there was a lot more coaching involved. There is a lot more shadowing involved. A lot more people who are getting familiar with your codebase, before they can actually help out with code reviews, by being able to review your pull request, etc.</p>

<h3>CHALLENGES</h3>

<h4>Risk</h4>

<p>It&rsquo;s complicated. There is a lot of risk to it and the risk is if I&rsquo;m owning a production function and you&rsquo;ve contributed code to it, and something breaks, I&rsquo;m going to be held accountable for it. I&rsquo;m going to have to support it. I&rsquo;m going to have to get up at night and deal with whatever broke because you didn&rsquo;t test some edge condition. It&rsquo;s easier just to say no we can&rsquo;t do this. So that risk was the biggest one that we had to overcome, to start to encourage a higher standard of acceptance such that we could take this risk of getting contributions from other people.</p>

<h4>Commitment</h4>

<p>The next one is commitment, both time and team.</p>

<p>Time is the easier one because – and I got into trouble for saying this in Europe, but – everyone does 120%. Some people even do 140%. It is basically going beyond your day job and providing some contributions to other teams or even functions you&rsquo;re interested in, but Europe has some very strict guidelines around the 80/20 and just padding 100% of the time that they work on, so I was told to work on trying to figure out how we could adjust our external or additional contributions to within 100%.</p>

<p>So we went back to this concept of 80/20, 90/10, call it what you want. We didn&rsquo;t really advertise it internally, but we took a few teams and said, let&rsquo;s try it out, to see how much does our work really suffer, if we do set aside 10% of our time to work with other teams or things that we may be interested in personally. The product buy-in on this was really, really tough, as well as some of the teams just didn&rsquo;t embrace it initially.</p>

<p>I won&rsquo;t say this was a solved problem, but we continue to work on it and I truly believe persistence is going to pay off. Over time, both project owners as well as the teams will realize that having that 10% flexible time for me to work with other projects that I&rsquo;m maybe interested in, is actually a motivating factor for me because I don&rsquo;t mind the drudgery stuff I may be doing or I don&rsquo;t mind some of the other things that may come on my plate, because I have that 10% excitement of what I want to do. Or try out a new thing. Or be able to look at a new exciting project that&rsquo;s going on in some other part of the firm and be able to do that.</p>

<p>It also led to this whole confusion between projects and products and projects done by teams versus what the product ownership is. The reason I bring that up is, even though the Terminal is one big product, we have multiple products within the Terminal, and then we have multiple projects that go across multiple products – so there&rsquo;s no one size fits all. So we would have to figure out what the right distribution of work across projects and products is. As I said, in an enterprise having evolved over time, time accounting or people accounting became a question, to say, where does a developer&rsquo;s time go?</p>

<p>Again, we went back and forth on this, saying we shouldn&rsquo;t worry about where a developers time goes, we should worry about the progress that we&rsquo;re making with moving the product forward or the project forward, and the innovation that we&rsquo;re bringing in, the new functionality that we&rsquo;re bringing in, which is what our higher end clients need.</p>

<p>That is again a lot of proving by actually getting some initial teams to be able to participate in this sharing concept, move the product forward, and getting the product owners to actually talk about the wins. We had some crazy user stories being shared internally about just functional changes that we were able to move forward much faster because multiple teams were now able to collaborate at a completely different level.</p>

<h4>Rules of Engagement</h4>

<p>I spoke about rules of engagement. I spoke about people defining, so we didn&rsquo;t set a one size fits all. We didn&rsquo;t say this is the participation criteria across the board, we said, every team can now put in a contributing.md and I said team but I really mean a repository. Any repository, you can define your rules of engagement. You must have a contributing.md otherwise you&rsquo;ll get a default one. And in that, your rules of engagement and your acceptance criteria for contributions. Then what we started doing was scraping all the repositories to find these contributing.md&rsquo;s as well as started to showcase where people were being forthcoming about defining their rules of engagement really well and their acceptance criteria as well as where it was then possible for others to start contributing to it.</p>

<h4>Buy in</h4>

<p>I already spoke about the buy in. We had to get and we cheated again a little bit on this, we went around the product owners and found out which product owners would lend themselves to this concept of inner sourcing, who would lend themselves to saying, some portion of my time, 5%, 10% of my developer time, can be spent and we had various sort of negotiations with them which is to say, fine, I can move tickets in some other project as long as it helps my project move forward. If I&rsquo;m waiting on somebody, I have the leeway to contribute to that particular project and move it forward for myself.</p>

<p>So we engaged with some of the earlier product owners. Once we had gone through six months with them, we got them to talk to other product owners and showcase how it was beneficial - not just in terms of moving the product forward, but in terms of the developers engaging with the other development teams on a much deeper level. We were engaging and collaborating at the codebase.</p>

<p>It also helped with keeping us motivated, and having options. I now like what&rsquo;s happening in the other team, and I have mobility options to actually move to the other team and help them move things forward. We had various occasions where somebody moved to another team for six months, helped the move a particular area forward and then move back. It just opened up a variety of avenues for us.</p>

<h4>It&rsquo;s my baby</h4>

<p>Finally breaking the myth about it&rsquo;s my baby. How many of you still hold onto stuff saying that it&rsquo;s your baby? I used to be one of those people 10 years ago. You have to learn to let go. Literally, it&rsquo;s not going to get better continuing to be your baby, right? At some point of time, even parents let their kids go. So, the breaking down that concept of &ldquo;this is my baby and I&rsquo;m not going to let go&rdquo; was probably the toughest one. So we had to continue to push on those people who thought it was their baby and work with them on an individual one on one basis. I will claim we still have a few. I think we&rsquo;ve broken down most people to at least open the doors. They still think it&rsquo;s their baby but they&rsquo;ve opened the doors. We still have a few more to go and that&rsquo;s been the toughest one.</p>

<h3>DIVERSITY</h3>

<h4>Individuals</h4>

<p>I started my talk with what got me to this place which is I had experiences across Asia. So in India, it&rsquo;s a very hierarchal society. It&rsquo;s changing, so don&rsquo;t throw darts at me right now, this was 20 years ago. We had just started. The computer boom had just started in the mid 90s and it&rsquo;s very hierarchal. You get delivered a set of tasks. You move forward. Nothing. You&rsquo;re not allowed to question or offer a suggestion.</p>

<p>Unfortunately, I was sort of badly placed there. I was born and brought up in India, but I was badly placed there because my dad sort of encouraged us to really do whatever the hell we wanted. We were two girls. When I started working, it was really tough for me to hold back because if I didn&rsquo;t agree with something, I would say, this is just wrong. I&rsquo;m not going to write it this way. That was my individual experience. However, I discovered – as I moved into system administration and database administration, I was one of 50 to 100 guys sitting there – I was okay working with them because I had grown up that way. But the other girls that started joining our teams, were not okay with it. They found it difficult. That&rsquo;s when my head started clicking and I said every single individual is different. I could deal with it but some of the other aren&rsquo;t dealing with it.</p>

<p>Then I discovered that it&rsquo;s not a gender thing. It&rsquo;s individuals. They are individuals who are soft spoken. There are individuals who don&rsquo;t mind putting their ideas out there. There are individuals who are more thoughtful. There are individuals who will speak off the cuff and we have to account for those individuals, for those different individual traits when we start collaborating and we have to try to create a practice where everybody is sort of self-policing themselves so that we are more inclusive. That&rsquo;s something that just doesn&rsquo;t come naturally. But we had to start talking about it and as I held more and more intimate 20 people, 30 people sessions on pointing out behaviors within instant messaging, pointing out behaviors with updates on tickets, pointing out behaviors with code reviews that were nasty, or appear to be nasty. I am a direct person. I can ask a direct question. I didn&rsquo;t think twice about it. But the person on the other end or a newcomer on the other end, may perceive it as hey I&rsquo;m not going to touch this thing because the next thing I do my head is going to get bitten off and I just don&rsquo;t have time to engage with it.</p>

<p>That really is something that each one of you, individually, if you&rsquo;re just conscious about the fact that the other person might be coming from a different place, we can collectively improve the developer culture across the board. Just by being conscious of the fact that somebody is coming from a different place and may have a different criteria in mind.</p>

<p>(By the way the picture up there is a fish tank at Bloomberg and I always get fascinated because every fish behaves differently and that&rsquo;s why I wanted to put that picture in there.)</p>

<h4>Building a culture of mentoring/coaching</h4>

<p>Building that culture of mentoring, of coaching, is every individual&rsquo;s responsibility, and just making people conscious, all developers conscious, of the fact that this is what&rsquo;s happening. I found a very unique way to do it. Get a bunch of people in the room, of varying experience and at different levels in the organization. So two years&rsquo; experience to 20 years of experience and ask very provoking questions on how they would react to a certain statement out there or how they felt when something happened in IB and instant messaging or what would they think if they had a newbie question to ask. Who would they ask that question to? How would another person who was sitting there react to that newbie question?</p>

<p>When we started having these conversations, it was very interesting because people discovered, just observing and hearing other stories in the room, behaviors that they probably needed to change themselves. It wasn&rsquo;t anybody judging it was just sharing stories. And we still do that to bring developers together even in meetups, we ask those questions, especially around being more inclusive, about the varying range we have.</p>

<h4>Community driven</h4>

<p>As I said, it&rsquo;s all community driven. We leverage the champs, the partners, the SI partners a lot. I encourage developers to be their own police so we don&rsquo;t have top down mandate. We don&rsquo;t have a management decree coming down that thou shall do this. It is all based on grass roots efforts. We do have support now though.</p>

<h3>TEAMWORK</h3>

<p>Of course, it&rsquo;s not, even though we are all individuals and every single individual contributes to it, nothing moves forward without us moving as a team including this collective developer audience as a team.</p>

<p>[Indicates slide outlining roles within team and a picture of a dog sled race team] The reason I very specifically picked this sled racing team is to point out the very, very simple difference. They are not all eight equal dogs. Each dog has its own personality. If they are trained, they are trained for the position they are running at. So the leader dogs versus the end dogs, have very different roles to play and part of the training goes into training those dogs that way. Those dogs don&rsquo;t behave out of their roles. They behave in their roles.</p>

<p>I don&rsquo;t mean to compare us to a sled dog team, but the reason I point this out is because when we&rsquo;re functioning in a team, you will realize that and you probably already know this, that everybody plays a different role, apart from the official role. So some are more mentors. Some are more coaches. Some can ask more questions. Some are more outspoken and will take over the meeting or take over the design discussion and it&rsquo;s their way or the highway.</p>

<p>What I&rsquo;m really asking for in this is the roles should be really determined for the team as to who is doing what, but we should really embrace the differences and ask people – or make people comfortable – to participate in the team, even though the roles are clearly defined. Where people take over meetings or where people may be bullish about something, find somebody to coach them, mentor them, to change that behavior so that the team itself can evolve and become a better team.</p>

<h3>TOOLS</h3>

<p>When I go back two and a half years, I said okay, what are our silos? Why are we so siloed? Where is the collaboration happening? We didn&rsquo;t have the appropriate tools. Tools did play an important role. Repositories were permissioned individually. I won&rsquo;t even go back to whether we were using CDS, Purecase, SVN. Earlier versions of Git. We are now on Git but the reason I bring that up is because repositories are individually permissioned traditionally. That&rsquo;s how we grew up in silos. So the first thing we did was say, okay, we&rsquo;re going to open up our repositories.</p>

<p>&ldquo;Oh no, no, no. You can&rsquo;t open up my repository because I have sensitive stuff there.&rdquo; What sensitive stuff? &ldquo;Oh we store passwords there.&rdquo; I&rsquo;m like that&rsquo;s not sensitive stuff. Take your passwords out. The repo is not the right place to store the password and keep a closed repository. This is a true story by the way. But it always came up as &ldquo;oh we have sensitive code. We cannot open it up.&rdquo; As I started questioning what is the sensitivity of that code, it always boiled down to one of three reasons. Three invalid reasons and I&rsquo;ll tell you the one valid reason.</p>

<p>&ldquo;I have some secure stuff there that I shouldn&rsquo;t have put there but I put it there so therefore I can&rsquo;t open it up beyond my team.&rdquo;</p>

<p>&ldquo;I have some…&rdquo; am I allowed to say shitty code? &ldquo;I have some really badly written stuff here. We&rsquo;ve made some bad decisions. We have to clean it up before we can open it up. So we&rsquo;ll clean it up and then we&rsquo;ll open it up.&rdquo; Of course it&rsquo;s never going to get there.</p>

<p>And last but not the least is &ldquo;oh, because these are low level APIs and we don&rsquo;t want them to know what we&rsquo;re doing and be able to leverage some of the other stuff, we can&rsquo;t open it up because they can&rsquo;t see the decisions we&rsquo;re making because then they&rsquo;ll directly access our codebase.&rdquo;</p>

<p>The one valid reason which is probably true across the industry is 10% or 20% of the codebase probably was truly specific to competitive business advantage, maybe some algorithms. Maybe some business logic, etc. Right? That was the key, the glue, the thing that sold your product. 10%, 20% and this is just an off the cuff number.</p>

<p>The minute we said that all repositories are open by default, we started working through these restrictions that were laid out to us and we started just saying, you&rsquo;ve got to open a repository by default. If you want to close it up, you&rsquo;ve got to talk to me. Then of course I&rsquo;ll wear you down with asking you questions and then I&rsquo;ll take you to your CIO and wear you down with asking questions.</p>

<p>That was our first thing. We were pretty scared and skeptical that because of this rule, we would not get people moving into this concept, but as I go back to how I started my conversation with the early adopters, with the evangelist that we created, with the buzz that got created about having a tool set that actually works, we started getting people moving their codebases over from whichever legacy repository they sat on. And we started getting more and more requests for features such that the tools would enable them to embrace this change.</p>

<p>Agile brought in some rules. So our Agile coaches came with some very specific guidelines. We had to then coach our coaches on some of the &#39;religion&rsquo; that they brought in versus some of the common sense which is just we needed to work with within our enterprise because our enterprise had grown up that way. Just to get them to recognize the differences and work with us was a challenge, but it&rsquo;s something we worked through.</p>

<p>What we also discovered was thinking outside the box. In a traditional enterprise company, we didn&rsquo;t have hackathons. We didn&rsquo;t have coding days. We didn&rsquo;t have space for ideation. So we started sponsoring a lot of those kind of activities. We have something called a Dev-X hack a thon which runs for a couple of days. We have it two or three times a year. We have it in London and we have it in New York. We do other cool stuff. The swag, the prizes, but the fact is that the ideas that come out of Dev-X hackathon get sponsored to get built up as a project.</p>

<p>So a lot of the tools integrations that we built up, were a result of the hack a thons. The idea started in a hackathon and then got sponsored and we could go ahead and build out that integration, amongst the other various SELC tools.</p>

<h3>ENCOURAGING COLLABORATION WITH STRETCH PROJECTS</h3>

<p>We found this to be a really, really interesting way of encouraging collaboration across teams. All the newcomers or the new classes that come in, I always encourage them, as part of their training to take on stretch projects. If they are interested in taking on a stretch project, I encourage people to work with their management teams to allow them to do those stretch projects. That seems to have helped us in moving the agenda forward because as people start to see the benefits both for the people that are working in their teams as well as the projects that they are working on, everybody has got a win, win situation.</p>

<p>What we also started to do was say, if I have opened up my repository, I&rsquo;m going to have some issues being tracked and I can put in help wanted tags on the issues that are low hanging fruit for me and I can get others to contribute to them. I mentioned this function called sauc. You run sauc, you get to see a list of repositories which have help wanted functions. For somebody who doesn&rsquo;t know specifically where they want to get started, or they may have an idea they can just go look at the help wanted issues, pick them up, and work on those. This was a really easy way for us to say, do it yourself. Self-serve yourself for moving something forward.</p>

<p>What we also did was shared infrastructure projects. Everything with software infrastructure which was related to the tools we opened it up. Some places it&rsquo;s harder to accept contributions especially when it&rsquo;s really related to compiler flags which go across the entire stack, so those are harder contributions to accept. But some of the simpler contributions are really straightforward. We also started to understand common pain points that came across because as you can imagine, we&rsquo;ve opened up a codebase now. So I can look across my entire sauc repository and see everybody&rsquo;s projects. If I have somebody working on containers, I can see who else is working on containers and create those opportunities to pull them together so that we don&rsquo;t have everybody doing their own thing. And pull those projects together and actually sponsor it as a project so we can collectively work on that one functionality or feature or piece of infrastructure that we&rsquo;re developing.</p>

<p>And with that, I&rsquo;m going to say and encourage all of you to get started. You can look at innersourcecomments.org. I have references at the end and the three things, I called it my three pronged approach initially when I started, which is identify the early adopters, evangelize, and then get the sponsorship. I hope this has been useful for you.</p>

<p><em><strong>Panna Pavangadkar</strong> is the Global Head of Developer Experience for Bloomberg&rsquo;s Engineering group. Building a great developer experience is at the heart of what her team does, providing a development environment that enables application developers to focus on building the company&rsquo;s core product: the Bloomberg terminal. Her past experience with databases, operating systems, infrastructure and application development in various engineering roles &ndash; as Technical Fellow, Vice President at Goldman Sachs (New York) and JP Morgan (Singapore) and NIIT (Pune, India) &ndash; gives her a unique perspective to understand and work to introduce and encourage wide scale change within the company&rsquo;s developer and engineering communities.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Our 10-point technical debt assessment</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/10-point-technical-debt-assessment/"/>
    <id>https://codeclimate.com/blog/10-point-technical-debt-assessment/</id>
    <updated>2017-10-12T11:33:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>In the six years since we first introduced radically simple metrics for code
quality, we&rsquo;ve found that clear, actionable metrics leads to better code and
more productive teams. To further that, we recently revamped the way we measure
and track quality to provide a new, clearer way to understand your projects.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/tech-debt-assessment/pillars.png"></p>

<p>Our new rating system is built on two pillars: maintainability (the opposite of
technical debt) and test coverage. For test coverage, the calculations are
simple. We take the covered lines of code compared to the total &ldquo;coverable&rdquo;
lines of code as a percentage, and map it to a letter grade from A to F.</p>

<p>Technical debt, on the other hand, can be a challenge to measure. Static
analysis can examine a codebase for potential structural issues, but different
tools tend to focus on different (and often overlapping) problems. There has
never been a single standard, and so we set out to create one.</p>

<p>Our goals for a standardized technical debt assessment were:</p>

<ul>
<li><p><strong>Cross-language applicability</strong> - A good standard should not feel strained when
applied to a variety of languages, from Java to Python to JavaScript. Polyglot
systems are the new normal and engineers and organizations today tend to work in
an increasing number of programming languages. While most languages are based on
primitive concepts like sequence, selection, and iteration, different paradigms
for organizing code like functional programming and OOP are common. Fortunately,
most programming languages break down into similar primitives (e.g. files,
functions, conditionals).</p></li>
<li><p><strong>Easy to understand</strong> - Ultimately the goal of assessing technical debt with
static analysis is to empower engineers to make better decisions. Therefore, the
value of an assessment is proportional to the ease with which an engineer can
make use of the data. While sophisticated algorithms may provide a seemingly
appealing “precision”, we’ve found in our years of helping teams improve their
code quality that simple, actionable metrics have a higher impact.</p></li>
<li><p><strong>Customizable</strong> - Naturally, different engineers and teams have differing
preferences for how they structure and organize their code. A good technical
debt assessment should allow them to tune the algorithms to support those
preferences, without having to start from scratch. The algorithms remain the
same but the thresholds can be adjusted.</p></li>
<li><p><strong>DRY (Don’t Repeat Yourself)</strong> - Certain static analysis checks produce highly
correlated results. For example, the cyclomatic complexity of a function is
heavily influenced by nested conditional logic. We sought to avoid a system of
checks where a violation of one check was likely to be regularly accompanied by
the violation of another. A single issue is all that’s needed to encourage the
developer to take another look.</p></li>
<li><p><strong>Balanced (or opposing)</strong> - Tracking metrics that encourage only one behavior
can create an undesirable overcorrection (sometimes thought of as “gaming the
metric”). If all we looked for was the presence of copy and pasted code, it
could encourage engineers to create unwanted complexity in the form of clever
tricks to avoid repeating even simple structures. By pairing an opposing metric
(like a check for complexity), the challenge increases to creating an elegant
solution that meets standard for both DRYness and simplicity.</p></li>
</ul>

<h2>Ten technical debt checks</h2>

<p>With these goals in mind, we ended up with ten technical debt checks to assess
the maintainability of a file (or, when aggregated, an entire codebase):</p>

<ol>
<li><p><strong>Argument count</strong> - Methods or functions defined with a high number of arguments</p></li>
<li><p><strong>Complex boolean logic</strong> - Boolean logic that may be hard to understand</p></li>
<li><p><strong>File length</strong> - Excessive lines of code within a single file</p></li>
<li><p><strong>Identical blocks of code</strong> - Duplicate code which is syntactically identical
(but may be formatted differently)</p></li>
<li><p><strong>Method count</strong> - Classes defined with a high number of functions or methods</p></li>
<li><p><strong>Method length</strong> - Excessive lines of code within a single function or method</p></li>
<li><p><strong>Nested control flow</strong> - Deeply nested control structures like if or case</p></li>
<li><p><strong>Return statements</strong> - Functions or methods with a high number of return statements</p></li>
<li><p><strong>Similar blocks of code</strong> - Duplicate code which is not identical but shares the
same structure (e.g. variable names may differ)</p></li>
<li><p><strong>Method complexity</strong> - Functions or methods that may be hard to understand</p></li>
</ol>

<h2>Check types</h2>

<p>The ten checks break down into four main categories. Let’s take a look at each of them.</p>

<h3>Size</h3>

<p>Four of the checks simply look for the size or count of a unit within the
codebase: <em>method length</em>, <em>file length</em>, <em>argument count</em> and <em>method count</em>.
Method length and file length are simple enough. While these are the most basic
form of static analysis (not even requiring parsing the code into an abstract
syntax tree), most programmers will identify a number of times dealing with the
sheer size of a unit of code has presented challenges. Refactoring a method that
won’t fit all on one screen is a herculean task.</p>

<p>The <em>argument count</em> check is a bit different in that it tends to pick up <em>data
clumps</em> and <em>primitive obsession</em>. Often the solution is to introduce a new
abstraction in the system to group together bits of data that tend to be flowing
through the system together, imbuing the code with additional semantic meaning.</p>

<h3>Control flow</h3>

<p>The <em>return statements</em> and <em>nested control flow</em> checks are intended to help
catch pieces of code that may be reasonably sized but are hard to follow. A
compiler is able to handle these situations with ease, but when a human tasked
with maintaining a piece of code is trying to evaluate control flow paths in
their head, they are not so lucky.</p>

<h3>Complexity</h3>

<p>The <em>complex boolean logic</em> check looks for conditionals laced together with
many operators, creating an exploding set of permutations that must be
considered. The <em>method complexity</em> check is a bit of a hybrid. It applies the
cognitive complexity algorithm which combines information about the size,
control flow and complexity of a functional unit to attempt to estimate how
difficult a unit of code would be to a human engineer to fully understand.</p>

<h3>Copy/paste detection</h3>

<p>Finally, the <em>similar and identical blocks of code</em> checks look for the
especially nefarious case of copy and pasted code. This can be difficult to spot
during code review, because the <em>copied</em> code will not show up in the diff, only
the pasted portion. Fortunately, this is just the kind of analysis that
computers are good at performing. Our copy/paste detection algorithms look for
similarities between syntax tree structures and can even catch when a block of
code was copied and then a variable was renamed within it.</p>

<h2>Rating system</h2>

<p>Once we’ve identified all of the violations (or issues) of technical debt within
a block of code, we do a little more work to make the results as easy to
understand as possible.</p>

<h3>File ratings</h3>

<p>First, for each issue, we estimate the amount of time it may take an engineer to
resolve the problem. We call this <em>remediation time</em>, and while it’s not very
precise, it allows us to compare issues to one another and aggregate them
together.</p>

<p>Once we have the total remediation time for a source code file, we simply map it
onto a letter grade scale. Low remediation time is preferable and receives a
higher rating. As the total remediation time of a file increases, it becomes a
more daunting task to refactor and the rating declines accordingly.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/tech-debt-assessment/rating-times.png"></p>

<h3>Repository ratings</h3>

<p>Last, we created a system for grading the technical debt of an entire project.
In doing so, we’re cognizant of the fact that older, larger codebases naturally
will contain a higher amount of technical debt in absolute terms compared to
their smaller counterparts. Therefore, we estimate the total implementation time
(in person-months) of a codebase, based on total lines of code (LOC) in the
project, and compute a <em>technical debt ratio</em>: the total technical debt time
divided by the total implementation time. This can be expressed as a percentage,
with lower values being better.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/tech-debt-assessment/tech-debt-formula.png"></p>

<p>We finally map the technical debt ratio onto an A to F rating system, and
presto, we can now compare the technical debt of projects against one another,
giving us an early warning system when a project starts to go off course.</p>

<h2>Get a free technical debt assessment for your own codebase</h2>

<p>If you’re interested in trying out our 10-point technical debt assessments on
your codebase, <a href="https://codeclimate.com">give Code Climate a try</a>. It’s always
free for open source, and we have a 14-day free trial for use with private
projects. In about five minutes, you’ll be able to see just how your codebase
stacks up. We support JavaScript, Ruby, PHP, Python and Java.</p>

<p>If you’re already a Code Climate customer, you can expect a rollout of the new
maintainability and test coverage ratings over the next few weeks &ndash; but if
you’d like them sooner, feel free to <a href="mailto:hello@codeclimate.com">drop us a
line</a>, we’re always happy to help!</p>
]]>
    </content>
  </entry>
  <entry>
    <title>A new, clearer way to understand code quality</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/a-new-clearer-way-to-understand-code-quality/"/>
    <id>https://codeclimate.com/blog/a-new-clearer-way-to-understand-code-quality/</id>
    <updated>2017-09-21T15:26:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>It’s been six years since Code Climate introduced radically simple metrics for code quality: a grade
point average (GPA) from 0 to 4.0 for repositories, and a letter rating for every file. Today, we’re
going further by completely revamping the way we measure and track quality, and shipping a bunch of
new features to go along with it.</p>

<p>Every repository and file will now receive two top-level ratings:</p>

<p><strong>Maintainability</strong>: An estimate of technical debt in the repo based on our standardized 10-point
assessment which looks at duplication, complexity and structural issues.</p>

<p><strong>Test Coverage</strong>: The percentage of covered lines compared to the total number of lines of code.
(We ingest test coverage information from your continuous integration server using our new
<a href="https://docs.codeclimate.com/docs/setting-up-test-coverage">universal test reporter</a>.)</p>

<p>Here’s how it all comes together on your new repository Overview page:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/repo-overview.png"></center></p>

<p>On top of this foundation, we’re launching five major, new features:</p>

<h2>Unified Code tab with maintainability and test coverage side-by-side</h2>

<p>Gone is the isolated Test Coverage tab, which was an additional place to get a full view of your
overall quality. We’ve fully integrated test coverage information into the Code tab, and everywhere
else.</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/code-tab.png"></center></p>

<p>Drilling down, you can access per-file quality statistics on the new Stats sub-tab:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/file-overview.png"></center></p>

<h2>In-app configuration of code quality analysis</h2>

<p>It’s now possible to control the way we analyze your code quality using simple, in-app
configuration. Easily select which checks to run and exclude files that are not relevant.</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/in-app-settings.png"></center></p>

<p>You can also easily browse and enable open source static analysis plugins, taking advantage of the
30+ tools that are compatible with our open, extensible platform.</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/plugin-config-settings.png"></center></p>

<p>For those who prefer finer-grained control, or wish to keep their configuration in version control,
file-based configuration using <code>.codeclimate.yml</code> remains available. If checked in, the
<code>.codeclimate.yml</code> takes precedence over the in-app configuration.</p>

<h2>Reorganized and expanded Trends area</h2>

<p>With all this new data available, we thought it was a great time to add some organization to the
Trends tab. The left sidebar now makes it easy to get right to what you’re looking for.</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/technical-debt-trend.png"></center></p>

<p>We’ve also added a new chart allowing you to see the total amount of technical debt in the project,
and the overall project maintainability, all in one place.</p>

<h2>Improved quality alerts via Slack and email</h2>

<p>Our pass/fail pull request statuses are great for ensuring that every change merged into your
codebase meets your quality standards. However, every once in awhile something may slip through the
cracks. For these situations, we’ve revamped the quality alerts we send via both Slack and email.
Here’s what it looks like in Slack:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/slack-notification.png"></center></p>

<p>And an email reporting some test coverage changes:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/quality-model/email-notification.png"></center></p>

<p>Alerts are sent when any letter rating changes, or any new files are created with “C” or lower
ratings. We think this new functionality is an excellent complement to our recently-launched
<a href="https://codeclimate.com/changelog/59271e1ea8cf0a0276001147">customizable issue alerts</a>.</p>

<h2>All of the above and more available via a REST API</h2>

<p>OK, so this one isn’t completely new, but it’s gotten much better and we couldn’t resist including
it. Over the past year we’ve been developing Code Climate with an API-first methodology. As a
result, the data that powers all of the above features is available over a
<a href="https://developer.codeclimate.com/">robust REST API</a> for you to take advantage of as you see fit.
Here’s a few examples:</p>

<h3>Get the current ratings for an individual file</h3>
<div class="highlight"><pre class="highlight shell"><code><span style="color: #008080">$ </span>curl <span style="color: #d14">\</span>
  https://api.codeclimate.com/v1/repos/:repo_id/ratings <span style="color: #d14">\</span>
  <span style="color: #000080">-H</span> <span style="color: #d14">"Accept: application/vnd.api+json"</span> <span style="color: #d14">\</span>
  <span style="color: #000080">-H</span> <span style="color: #d14">"Authorization: Token token=&lt;token&gt;"</span> |
  jq <span style="color: #d14">'.data | .[] | select(.attributes.path == "path/to/file.rb")'</span>
</code></pre></div><div class="highlight"><pre class="highlight json"><code><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"id"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"59c41d36d0c53d0001000001"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"type"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"ratings"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"attributes"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"path"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"path/to/file.rb"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"letter"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"A"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"measure"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">220</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"unit"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"minute"</span><span style="color: #bbbbbb">
    </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"pillar"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"Maintainability"</span><span style="color: #bbbbbb">
  </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"id"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"59c41d36d0c53d0001000002"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"type"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"ratings"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"attributes"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"path"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"path/to/file.rb"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"letter"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"A"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"measure"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">92.40506329113924</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"unit"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"percent"</span><span style="color: #bbbbbb">
    </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"pillar"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"Test Coverage"</span><span style="color: #bbbbbb">
  </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span></code></pre></div>
<h3>Get a time-series of test coverage information</h3>
<div class="highlight"><pre class="highlight shell"><code><span style="color: #008080">$ </span>curl <span style="color: #d14">\</span>
  https://api.codeclimate.com/v1/repos/:repo_id/metrics/test_coverage <span style="color: #d14">\</span>
  <span style="color: #000080">-X</span> GET <span style="color: #d14">\</span>
  <span style="color: #000080">-H</span> <span style="color: #d14">"Authorization: Token token=&lt;token&gt; </span><span style="color: #d14">\</span><span style="color: #d14">
  -H "</span>Accept: application/vnd.api+json<span style="color: #d14">" </span><span style="color: #d14">\</span><span style="color: #d14">
  --data-urlencode "</span>filter[from]<span style="color: #000000;font-weight: bold">=</span>2017-08-01<span style="color: #d14">" </span><span style="color: #d14">\</span><span style="color: #d14">
  --data-urlencode "</span>filter[to]<span style="color: #000000;font-weight: bold">=</span>2017-09-01<span style="color: #d14">" |
  jq
</span></code></pre></div><div class="highlight"><pre class="highlight json"><code><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"data"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"id"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"59c41d36d0c53d0001000001"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"type"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"metrics"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"attributes"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"name"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"test_coverage"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
      </span><span style="color: #d14">"points"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">1501459200</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">98.57142857142858</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">1502064000</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">98.50960160504442</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">1502668800</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">98.53490376328641</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">1503273600</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">98.53314527503527</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">1503878400</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
          </span><span style="color: #d14">"value"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #009999">98.5405557114791</span><span style="color: #bbbbbb">
        </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
      </span><span style="background-color: #f8f8f8">]</span><span style="color: #bbbbbb">
    </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
  </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span></code></pre></div>
<p>Just head over to your <a href="https://codeclimate.com/profile/tokens">API access page of your user settings</a>
area to generate a personal access token and get started.</p>

<p>These features will be rolled out to all repositories on CodeClimate.com starting today.</p>

<h2>Wrapping Up</h2>

<p>We hope you’ll agree that these changes represent a dramatic leap forward for Code Climate. As we’ve
been testing this functionality internally and with a small group of customers, we’ve found it
really changes the way we interact with code quality information day-to-day.</p>

<p>There may be a few rough edges as we refine and polish some areas. As always, if you have any
questions about anything, please don’t hesitate to <a href="https://codeclimate.com/help">get in touch</a>.
Our fantastic support team is always here to help.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Your checklist for quality code</title>
    <author>
      <name>Kären Engelbrecht</name>
      <uri>https://twitter.com/scriberty</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/your-checklist-for-quality-code/"/>
    <id>https://codeclimate.com/blog/your-checklist-for-quality-code/</id>
    <updated>2016-11-10T15:42:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Businesses want high quality codebases and developers want to write high quality code – but what does that really mean? How can you tell if your code is high quality?</em></p>

<p>Search for a single definition of software quality and you’ll see that it is open to considerable, and sometimes heated, debate. Aside from matters of taste, this is because code quality can’t be defined by a single attribute, but rather through a combination of traits. So how do you identify them?</p>

<p>Over the years, as we’ve talked with customers about what they’re trying to achieve with a code quality solution, the same eight traits keep coming up:</p>

<h2>&#9744; Clear</h2>

<p>Can the code be read, understood, and maintained over time, by someone who isn’t the code’s original author. Martin Fowler, an authority on code quality, stated this well: &ldquo;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&rdquo;<a href="http://www.martinfowler.com/books/refactoring.html">1</a></p>

<h2>&#9744; Simple</h2>

<p>Elegant code that does exactly what is needed and nothing more, sometimes described as &ldquo;the simplest thing that could possibly work&rdquo;.</p>

<h2>&#9744; Well-tested</h2>

<p>Code is written to achieve a purpose, and testing – either with unit tests or integration tests or both – is the best way to determine if it achieves that purpose and works with the rest of a codebase. Of course, just having lots of tests doesn’t mean code is &ldquo;well-tested&rdquo;. The tests themselves must be concise, readable, and comprehensive.</p>

<h2>&#9744; Bug-free</h2>

<p>A raincoat that doesn’t keep out water isn’t high quality. For the same reason, the presence of bugs preventing desired behavior is a common marker of low-quality code.</p>

<h2>&#9744; Refactored</h2>

<p>Refactored code is code that is not just written once and committed, but iterated on to match best practices and the team’s conventions.</p>

<h2>&#9744; Documented</h2>

<p>As with clarity, documentation – inside the code or external – is highly regarded because it supports long-term maintainability.</p>

<h2>&#9744; Extensible</h2>

<p>In a business environment, codebases are constantly evolving to meet new requirements. Code that is extensible is prized for its ability to enable developers to rapidly add new features without having to spend a lot of time on maintenance.</p>

<h2>&#9744; Performant</h2>

<p>For businesses delivering a service where speed is paramount – say, e-commerce platforms – code is unlikely to be considered high quality unless it’s performant.</p>

<p><strong>Any combination of these can make for great quality code depending on what’s important to your business</strong>. The difficulty is deciding what that is as a team.</p>

<p>Perhaps initial time to market is your core business priority – if so, you may not be as concerned about test coverage, and that’s okay.</p>

<p>The important thing is to make sure that everyone contributing to your codebase is on the same page, and the goals for your business and your code are aligned. If not, you risk moving in different directions and not achieving either.</p>

<p><em>Next time we’ll take a look at how to choose the right complexity metric for your team.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Our Series A and a new, open source edition of Code Climate</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/series-a-and-community-edition/"/>
    <id>https://codeclimate.com/blog/series-a-and-community-edition/</id>
    <updated>2016-10-06T12:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Today we’re excited to announce that Code Climate has raised $4.5M in Series A funding from Union Square Ventures (USV) and existing investors NextView Ventures, Lerer Hippeau Ventures, Trinity Ventures and Fuel Capital. Albert Wenger, Managing Partner at USV, is joining our board, and we’re excited to join USV’s portfolio of companies, which includes MongoDB, Twilio, Etsy, and others.</p>

<p>This is a major milestone for us, and we’re excited about what it means for the over 80,000 developers who use Code Climate to build and ship better software. We have a big vision for the future:</p>

<blockquote>
<p>Empowering every software developer to improve the quality of their code and the outcomes of their projects with the most advanced, open and extensible platform for source code analytics.</p>
</blockquote>

<p>Since our seed funding round in summer of 2014, we’ve introduced an open and <a href="http://codeclimate.com/blog/code-climate-platform/">extensible static analysis platform</a>, shipped a major new edition of our <a href="https://codeclimate.com/enterprise">on-premises product</a>, and launched a powerful <a href="https://codeclimate.com/browser-extension">browser extension</a> that brings code quality and test coverage information directly into the GitHub user interface.</p>

<p>We’ve grown to provide analysis for more than 90,000 repositories across 20+ programming languages and frameworks, and analyze two billion lines of code each day – making us the largest provider of cloud-based static analysis.</p>

<p>Here’s what our new investors had to say:</p>

<blockquote>
<p>There is a common mantra that you can have any two in software: fast time to market, low cost of development, or high quality, but never all three. This, of course, is also what people used to believe about manufacturing before the rise of techniques such as lean manufacturing and continuous improvement. When you lead with quality in manufacturing you can, in fact, have quality, speed, and low cost. The same will be true for code, which makes assessing and managing the quality of code a key challenge for the coming years.</p>

<p>- Albert Wenger, Union Square Ventures</p>
</blockquote>

<p>We completely agree, and we’re thrilled to have the resources to accelerate our work on this problem for years to come. To that end, we’d like to share a little about the next big thing in the works&hellip;</p>

<h2>Coming soon: A new, open source edition of Code Climate</h2>

<p><strong>We’re working on an open source, standalone edition</strong> of the Code Climate application, which you’ll be able to download and run anywhere – including behind your firewall – completely free. We’re calling it Code Climate Community Edition (CE) for now and expect to ship an alpha version within a month.</p>

<p>It should come as no surprise that we’re huge fans of open source. We’ve long provided free service to open source projects, and last year we open sourced our static analysis engines and a command line interface (CLI) when we launched our open, extensible platform. We see providing a workflow-integrated code analytics experience as an open source package as the next big step in making Code Climate a ubiquitous part of every software developer’s toolbox, and hope you’re as excited about it as we are.</p>

<p>Great companies like GitLab and Travis CI have built thriving business around open source (or &ldquo;open core&rdquo;) offerings, and we thank them for their inspiration and innovation in these areas.</p>

<p>Since it will be possible to run the community edition of Code Climate for free, you may wonder what our plans are for revenue. In short, they don’t change much. We’ll continue to provide our cloud-based product at CodeClimate.com (still free for open source projects!) where we host and manage everything for you and keep things running smoothly. We’ll also continue to offer an &ldquo;enterprise&rdquo; edition of Code Climate for on-premises installs, with exclusive features and services focused on larger teams. We’ll have more to share when we release the Community Edition alpha.</p>

<p>We believe that every developer and every project can benefit from Code Climate from day one, and are happy to make that even easier for more organizations, regardless of their requirements for where they store their source code.</p>

<p>P.S. <a href="http://jobs.codeclimate.com/">We’re hiring!</a> If the vision we’re pursuing sounds appealing to you, we’d love to chat with you about joining our growing team in New York.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Code Climate Platform Is Out of Beta</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/codeclimate-platform-is-out-of-beta/"/>
    <id>https://codeclimate.com/blog/codeclimate-platform-is-out-of-beta/</id>
    <updated>2016-02-09T12:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Today we’re excited to announce that the Code Climate Platform is out of beta. When we <a href="https://www.youtube.com/watch?v=lukVYdENeNY&amp;feature=youtu.be">launched</a> the first open, extensible platform for static analysis back in June of last year, we knew it would take some time to perfect. Since then, we&rsquo;ve been working hard to add features, fix bugs, support community contributors, and upgrade infrastructure to create a superior experience for developers everywhere.</p>

<p>Our engines-based analysis now offers the key features you&rsquo;ve come to expect from our &ldquo;classic&rdquo; offering, and a lot more, including:</p>

<ul>
<li>Style checks for Ruby, PHP and Python</li>
<li>Support for more programming languages like Go, Haskell, JSX, CoffeeScript and SCSS; and frameworks like Ember.js, React and RubyMotion</li>
<li>Dependency audits for potential vulnerabilities in your RubyGems and NPM packages</li>
<li>Atom editor integration and a CLI to get feedback before you push</li>
<li>Improved configurability and tuning options support in <code>.codeclimate.yml</code> (and per-engine config files)</li>
<li>Ability to create your own analysis engines using our open source spec and make them available through CodeClimate.com</li>
</ul>

<p>Already, Code Climate serves tens of thousands of developers. We&rsquo;re proud to be working with a community of over 100 contributors and members of our Developer Program to provide over 1,800 checks across 20 static analysis engines on our new platform.</p>

<blockquote>
<p>Code Climate allows us to incrementally improve and maintain good code hygiene, decreasing the number of defects in our products, and leading to better overall product quality. The Code Climate open platform is a game changer and allows us to build and improve static analysis engines to support our highly complex environment.</p>

<p><em>Andy Blyler, Senior Director of Engineering, Barracuda Networks</em></p>
</blockquote>

<p>For those who gave our engines-based analysis a try soon after launch, in addition to bug fixes you&rsquo;ll notice a number of key improvements, including:</p>

<ul>
<li>Visibility into the analysis process via our new <a href="https://codeclimate.com/changelog/565e166c1b88310c560003e2">Builds</a> pages</li>
<li>More accurate ratings and GPAs</li>
<li>Improved <a href="https://codeclimate.com/changelog/56a7e89ba8fa0b004d00106b">Issues</a> browsing and filtering</li>
<li>Better performance for faster results</li>
<li>Improved stability from infrastructure upgrades we&rsquo;ve made behind the scenes</li>
</ul>

<p>Want to see it for yourself? Take a look!</p>

<p><center><iframe src="https://d341kum51qu34d.cloudfront.net//fast.wistia.net/embed/iframe/j3n3ufoqt0" allowtransparency="true" frameborder="0" scrolling="no" class="wistia_embed" name="wistia_embed" allowfullscreen mozallowfullscreen webkitallowfullscreen oallowfullscreen msallowfullscreen width="640" height="498"></iframe></center>
<script src="https://d341kum51qu34d.cloudfront.net//fast.wistia.net/assets/external/E-v1.js" async></script></p>

<h2>Start using the Code Climate Platform today</h2>

<p><a href="https://codeclimate.com/">Sign up today</a> to get started with Code Climate for your projects. You’ll get 20% off your first year when you start a new subscription by February 29, using the promo code <em>CCGA2016</em> at checkout.</p>

<p>For existing customers, just follow <a href="http://docs.codeclimate.com/article/300-the-codeclimate-platform">these instructions</a> for moving your repositories over to our new engines-based analysis. We&rsquo;re confident that you&rsquo;ll find it&rsquo;s a superior experience to our “classic” offering.</p>

<p>Finally, we recognize that Code Climate is most valuable when you can use it wherever your work. For customers whose ability to host code with third-party services is limited, we recommend <a href="https://codeclimate.com/enterprise">Code Climate Enterprise</a>, our on-premise service.</p>

<p>With the new foundation that the Code Climate Platform provides, we&rsquo;re looking forward to the new opportunities we&rsquo;ll have to bring you even more functionality. Stay tuned for more big announcements in 2016 (you can follow us on <a href="https://twitter.com/codeclimate">Twitter</a> here).</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Code Climate for Atom</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/codeclimate-for-atom/"/>
    <id>https://codeclimate.com/blog/codeclimate-for-atom/</id>
    <updated>2015-11-19T12:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>We&rsquo;re thrilled today to share a project we&rsquo;ve been working on for some time − <a href="https://atom.io/packages/linter-codeclimate">editor integration</a> with GitHub&rsquo;s awesome <a href="https://atom.io/">Atom</a> text editor. We&rsquo;re super excited about it, and since it&rsquo;s customary to express one&rsquo;s excitement with an animated GIF, we&rsquo;ve done just that:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/atommovie.gif"></center></p>

<p>This integration takes advantage of Code Climate&rsquo;s unique platform, allowing you to seamlessly aggregate the results from all of your favorite static analysis tools into one clear, unified report. Our CLI makes it easy to get those results right on your laptop, before code is merged − and now the same is true inside your text editor:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/atom_inline.png"></center></p>

<p>Integration with Atom is powered by the <a href="https://atom.io/packages/linter">Atom Linter project</a>, a fantastic, open toolset for integrating static analysis into Atom. We collaborated with the Linter team to provide you with the best possible Atom experience, and we think you’re going to love being able to use Code Climate in your editor.</p>

<p>To get started, you’ll need to have the <a href="https://github.com/codeclimate/codeclimate">Code Climate CLI</a> installed. If you’re using a Mac with <code>brew</code>, installing is as simple as:</p>
<div class="highlight"><pre class="highlight plaintext"><code>brew tap codeclimate/formulae
brew install codeclimate
</code></pre></div>
<p>Once <code>brew</code> is done, you’ll want to make sure that the engines you need to analyze your code are installed locally. If the repo you want to analyze already includes a <code>.codeclimate.yml</code> file, you can run:</p>
<div class="highlight"><pre class="highlight plaintext"><code>cd MYPROJECT
codeclimate engines:install
</code></pre></div>
<p>When you&rsquo;ve got the CLI up and running, you&rsquo;re ready to see analysis results within the comfort of Atom. Install the <code>linter</code> and <code>linter-codeclimate</code> packages using the UI or like so:</p>
<div class="highlight"><pre class="highlight plaintext"><code>apm install linter
apm install linter-codeclimate
</code></pre></div>
<p>After the packages are installed, reload your editor. Now, when you save a file it will kick off Code Climate analysis - woot! You’ll see your results inline, as in the screenshot above.</p>

<p>Currently our Atom package supports analysis engines for JavaScript, Ruby, Python, CoffeeScript and PHP (plus the perennial favorite FIXME, for all of your bug-finding needs). We&rsquo;ll ship an update soon which will include support for the balance of our engines.</p>

<p>We hope you&rsquo;re as excited as we are to have so much powerful analysis available right inside Atom. Being able to get feedback to developers <em>where they work</em> has always been at the core of our mission, and editor integration is a big step for us in that regard. If you&rsquo;re interested in building support for your favorite editor shoot an email to <a href="mailto:mrb@codeclimate.com">mrb@codeclimate.com</a> and we’ll help get you started! Building tools that suit your workflow is what Code Climate is all about.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Build your own Code Climate Analysis Engine</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/build-your-own-codeclimate-engine/"/>
    <id>https://codeclimate.com/blog/build-your-own-codeclimate-engine/</id>
    <updated>2015-07-07T12:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Recently, we <a href="http://codeclimate.com/blog/code-climate-platform/">announced the release</a> of the <a href="https://codeclimate.com/platform">Code Climate Platform</a>, which lets anyone create and deploy static analysis tools to an audience of over 50,000 developers. These Open Source static analysis tools are called &ldquo;engines,&rdquo; and in this post I&rsquo;ll show you how to create one from scratch.</p>

<p>We&rsquo;ll create an engine that <code>grep</code>s through your source code and looks for instances of problematic words like <code>FIXME</code>, <code>TODO</code>, and <code>BUG</code>. This engine conforms to the <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md">Code Climate engine specification</a>, and all of the code for this engine is <a href="https://github.com/codeclimate/codeclimate-fixme">available on GitHub.</a> When we get up and running, you&rsquo;ll see results like this on your command line:</p>

<p><center><img src="https://d341kum51qu34d.cloudfront.net/images/posts/fixme.png"></center></p>

<p>Engines that you create can be tested with <a href="https://github.com/codeclimate/codeclimate">the Code Climate command line tool</a>. Once you’ve got an Open Source engine that works, we&rsquo;d love to chat with you about making it available on our cloud platform, so that your whole community can have access to it!</p>

<p>For more information <a href="https://codeclimate.com/dev_form">join our Developer Program</a>.</p>

<h3>What&rsquo;s an engine made of?</h3>

<p>Instead of asking you to dive into the <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md">Code Climate engine specification</a>, to learn what an engine is, I&rsquo;ll give you a brief overview here.</p>

<blockquote>
<p>A Code Climate engine is a containerized program which analyzes source code and prints issues in JSON to STDOUT.</p>
</blockquote>

<p>Sound simple? We really think it is! Hopefully this blog post will illustrate what we mean.</p>

<p>More concretely, the <code>FIXME</code> engine we&rsquo;re going to create contains three important files:</p>

<ul>
<li>A <code>Dockerfile</code> which specifies the Docker image</li>
<li>A <code>bin/fixme</code> executable wrapper script that runs the engine</li>
<li>The <code>index.js</code> file, which contains the engine source code</li>
</ul>

<p>There are other requirements in the specification regarding resource allocation, timing, and the shape of the output data (which we&rsquo;ll see more of below), but that&rsquo;s really all there is to it.</p>

<h3>A little bit of setup</h3>

<p>Before we write any code, you need a few things running locally to test your engine, so you might as well get that out of the way now. You&rsquo;ll need the following things running locally:</p>

<ul>
<li>A <a href="https://www.docker.com/">Docker</a> environment (we recommend <a href="https://docs.docker.com/engine/installation/mac/">Docker For Mac</a> for OSX development.</li>
<li>The <a href="https://github.com/codeclimate/codeclimate">Code Climate CLI tool</a> (you can <code>brew tap codeclimate/formulae &amp;&amp; brew install codeclimate</code> on OSX)</li>
</ul>

<p>Run <code>codeclimate -v</code> when you&rsquo;re done. If it print a version number, you should be ready to go!</p>

<h3>FIXME</h3>

<p>The idea for <code>FIXME</code> came to us when we were brainstorming new engine ideas which were both <em>high value</em> and <em>easy to implement.</em> We wanted to release a sort of <code>Hello, world</code> engine, but didn&rsquo;t want it to be one that did something totally pointless. Thus, <code>FIXME</code> was born.</p>

<p>The <code>FIXME</code> engine looks for (case-insensitive, whole word) instances of the following strings in your project&rsquo;s files:</p>

<ul>
<li>TODO</li>
<li>FIXME</li>
<li>HACK</li>
<li>BUG</li>
<li>XXX</li>
</ul>

<p>This is not a novel idea.  It&rsquo;s well known that instances of these phrases in your code are lurking problems, waiting to manifest themselves when you least expect it. We also felt it worth implementing because running a <code>FIXME</code> engine in your workflow has the following benefits:</p>

<ul>
<li>Existing <code>FIXME</code>s hacks will be more visible to you and your team</li>
<li>New <code>FIXME</code>s will bubble up and can even fail your pull requests if you configure them properly on <a href="http://codeclimate.com">codeclimate.com</a></li>
</ul>

<p>Pretty nifty for around 75 lines of code.</p>

<p>To achieve this, the engine performs a case insensitive <code>grep</code> command on all of the files you specify, and emits Code Climate <code>issues</code> wherever it finds one.</p>

<h3>Implementing an engine in JavaScript</h3>

<p>The meat of the actual engine is in the <code>index.js</code> file, which contains around 50 lines of JavaScript. The entirety of the file <a href="https://github.com/codeclimate/codeclimate-fixme/blob/a47a1d257b11187648e175c67494f19972cac1df/index.js">can be found here</a>. I&rsquo;ll highlight a few important sections of the code for the engine below, but if you have any questions, please <a href="https://github.com/codeclimate/codeclimate-fixme/issues">open an issue on the GitHub repo</a> and I&rsquo;ll try my best to answer promptly!</p>

<p>On to the code. After requiring our dependencies and typing out the module boilerplate, we put the phrases we want to find in grep pattern format:</p>
<div class="highlight"><pre class="highlight plaintext"><code>var fixmeStrings = "'(FIXME|TODO|HACK|XXX|BUG)'";
</code></pre></div>
<p>This will be used in a case insensitive search against all of the files the engine we&rsquo;ll analyze.</p>

<p>Next, we create a function that we will use to print issues to <code>STDOUT</code> according to the <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md#issues">issue data type specification in the engine spec</a>. The <code>printIssue</code> function accepts a file name, a line number, and the issue string,</p>
<div class="highlight"><pre class="highlight plaintext"><code>var printIssue = function(fileName, lineNum, matchedString){
  var issue = {
    "type": "issue",
    "check_name": "FIXME found",
    "description": matchedString + " found",
    "categories": ["Bug Risk"],
    "location":{
      "path": fileName,
      "lines": {
        "begin": lineNum,
        "end": lineNum
      }
    }
  };

  // Issues must be followed by a null byte
  var issueString = JSON.stringify(matchedString)+"\0";
  console.log(issueString);
}
</code></pre></div>
<p>This data format contains information about the location, category, and description of each issue your engine emits. It&rsquo;s at the heart of our engine specification and massaging data from an existing tool to conform to this format is typically straightforward.</p>

<p>The data in the JSON your engine prints will be consumed by the CLI and if you join our <a href="https://codeclimate.com/dev_form">Developer Program</a> and work with us, it can also be made available to all users of <a href="http://codeclimate.com">codeclimate.com</a>. We&rsquo;ll work with you to ensure your engine is spec compliant and meets our security and performance standards, and get your work in front of a lot of people!</p>

<p>The actual code that greps each file isn&rsquo;t super interesting, but you should <a href="https://github.com/codeclimate/codeclimate-fixme/blob/a47a1d257b11187648e175c67494f19972cac1df/index.js#L33-L58">check it out on GitHub</a> and <a href="https://github.com/codeclimate/codeclimate-fixme/issues">open an issue on the repo</a> if you have a question.</p>

<p>Because it&rsquo;s a requirement of engines to respect the file exclusion rules passed to it by the CLI or our cloud services, though, I&rsquo;ll show a bit of how that works:</p>
<div class="highlight"><pre class="highlight plaintext"><code>// Uses glob to traverse code directory and find files to analyze,
// excluding files passed in with by CLI config
var fileWalk = function(excludePaths){
  var analysisFiles = [];
  var allFiles = glob.sync("/code/**/**", {});

  allFiles.forEach(function(file, i, a){
    if(excludePaths.indexOf(file.split("/code/")[1]) &lt; 0) {
      if(!fs.lstatSync(file).isDirectory()){
        analysisFiles.push(file);
      }
    }
  });

  return analysisFiles;
}
</code></pre></div>
<p>Here I am using the NPM <code>glob</code> module to iterate over all of the files starting at <code>/code</code> recursively. This location also comes from the engine specification. The <code>fileWalk</code> function takes an array of <code>excludePaths</code>, which it extracts from <code>/config.json</code> (this will be made available to your engine after the CLI parses a project&rsquo;s <code>.codeclimate.yml</code> file). This all happens in the main function of the engine, <code>runEngine</code>:</p>
<div class="highlight"><pre class="highlight plaintext"><code>FixMe.prototype.runEngine = function(){
  // Check for existence of config.json, parse exclude paths if it exists
  if (fs.existsSync("/config.json")) {
    var engineConfig = JSON.parse(fs.readFileSync("/config.json"));
    var excludePaths = engineConfig.exclude_paths;
  } else {
    var excludePaths = [];
  }

  // Walk /code/ path and find files to analyze
  var analysisFiles = fileWalk(excludePaths);

  // Execute main loop and find fixmes in valid files
  analysisFiles.forEach(function(f, i, a){
    findFixmes(f);
  });
}
</code></pre></div>
<p>This main function gives hopefully gives you a clear picture of what this engine does:</p>

<ul>
<li>It parses a JSON file and extracts an array of files to exclude from analysis</li>
<li>It passes this list of files to a function that walks all files available to the engine, and produces a list of files to be analyzed</li>
<li>It passes the list of analyzable files to the <code>findFixmes</code> function, which greps individual files and prints them to STDOUT</li>
</ul>

<h3>Packaging it up</h3>

<p>How engines are packaged as Docker containers is important: it <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md#packaging">has it&rsquo;s own section of the engine specification</a>. The <code>Dockerfile</code> for <code>FIXME</code> is pretty typical:</p>
<div class="highlight"><pre class="highlight plaintext"><code>FROM node

MAINTAINER Michael R. Bernstein

RUN useradd -u 9000 -r -s /bin/false app

RUN npm install glob

WORKDIR /code
COPY . /usr/src/app

USER app
VOLUME /code

CMD ["/usr/src/app/bin/fixme"]
</code></pre></div>
<p>Here&rsquo;s a breakdown of each line (for more information about each directive, <a href="https://docs.docker.com/reference/builder/">see the official Docker documentation</a>):</p>

<ol>
<li><p>The official <code>node</code> Docker container is the basis for this engine container. It has <code>node</code> and <code>npm</code> installed, and generally  makes our lives easier.</p></li>
<li><p>Declare a maintainer for the container.</p></li>
<li><p>Create the <code>app</code> user to run the command <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md#packaging">as specified.</a></p></li>
<li><p>Install packages with <code>npm install glob</code> so that the external dependency is available when the engine runes.</p></li>
<li><p>Set the <code>WORKDIR</code> to <code>/code</code>, where the source to be analyzed will be mounted.</p></li>
<li><p>Copy the engine code to <code>/usr/src/app</code>.</p></li>
<li><p>Use the <code>app</code> user that we created earlier.</p></li>
<li><p>Mount <code>/code</code> as a <code>VOLUME</code> per <a href="https://github.com/codeclimate/spec/blob/master/SPEC.md#packaging">the spec</a></p></li>
<li><p>Our engine specification says that the engine should launch and run immediately, so we use <code>CMD</code> to achieve this. In the case of <code>FIXME</code>, the executable wrapper script instantiates the engine we wrote in JavaScript above, and runs it. Check it out:</p></li>
</ol>
<div class="highlight"><pre class="highlight javascript"><code><span style="color: #999999;font-weight: bold">#!/usr/bin/env node
</span>
<span style="color: #000000;font-weight: bold">var</span> <span style="background-color: #f8f8f8">FixMe</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">require</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'../index'</span><span style="background-color: #f8f8f8">);</span>
<span style="color: #000000;font-weight: bold">var</span> <span style="background-color: #f8f8f8">fixMe</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">new</span> <span style="background-color: #f8f8f8">FixMe</span><span style="background-color: #f8f8f8">();</span>

<span style="background-color: #f8f8f8">fixMe</span><span style="background-color: #f8f8f8">.</span><span style="background-color: #f8f8f8">runEngine</span><span style="background-color: #f8f8f8">();</span>
</code></pre></div>
<p>We now have all of the pieces in places. Let&rsquo;s test it out.</p>

<h3>Testing your engine locally</h3>

<p>If you want to test the code for this engine locally, you can clone the <a href="https://github.com/codeclimate/codeclimate-fixme">codeclimate-fixme repository</a> locally, and follow these steps:</p>

<ul>
<li>Build the docker image with <code>docker build -t codeclimate/codeclimate-fixme .</code> (You must be inside the project directory to do this)</li>
<li>Make sure the engine is enabled in the <code>.codeclimate.yml</code> file of the project you want to analyze:</li>
</ul>
<div class="highlight"><pre class="highlight plaintext"><code>  engines:
    fixme:
      enabled: true
</code></pre></div>
<ul>
<li>Test the engine against the engine code itself (whoooah) with <code>codeclimate analyze --dev</code></li>
</ul>

<p>And you should see some results from <code>test/test.js</code>! Pretty cool, right?</p>

<p><em>Note that if you want to test modifications you are making to this engine, you should build the image with a different image name, e.g. <code>codeclimate/codeclimate-fixme-YOURNAME</code>. You would then add <code>fixme-YOURNAME</code> to your <code>.codeclimate.yml</code> file as well.</em></p>

<p>If you get stuck during development, invoke <code>codeclimate console</code> and run:</p>
<div class="highlight"><pre class="highlight plaintext"><code>Analyze.new(['-e', 'my-engine', '--dev']).run
</code></pre></div>
<p>And you should be able to see what&rsquo;s going on under the hood.</p>

<h3>What will you build?</h3>

<p>Hopefully seeing how straightforward an engine can be will give you lots of great ideas for engines you can implement on your own. If tools for your language don&rsquo;t exist, contact us, and maybe we can help you out!</p>

<p>Simple ideas like <code>FIXME</code> have a lot of power when your entire team has access to them. Wire up the <code>codeclimate</code> CLI tool in your build process, push your repositories to Code Climate, and keep pursuing healthy code. We can&rsquo;t wait to see what you&rsquo;ll build.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Launching Today: The Code Climate Platform</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-climate-platform/"/>
    <id>https://codeclimate.com/blog/code-climate-platform/</id>
    <updated>2015-06-19T12:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/platform-e72b147d.jpg" alt="Code Climate Platform" /></p>

<p><strong>Update: See our CEO and Co-Founder Bryan Helmkamp introducing the Code Climate Platform!</strong></p>

<p><center><iframe width="560" height="315" src="https://www.youtube.com/embed/lukVYdENeNY" frameborder="0" allowfullscreen></iframe></center></p>

<p>Today, we’re thrilled to launch the <a href="https://codeclimate.com/platform">Code Climate Platform</a> − the first open, extensible platform for all types of static analysis.</p>

<p>We’ve come a long way since we started building a static analysis tool for Rubyists. Today, we’re fortunate enough to help 50,000 developers analyze about 700BN lines of code every weekday. As we’ve grown, we’ve seen that clear, actionable static analysis leads to healthier code and happier developers. Our new platform brings those benefits to every team, regardless of the technologies they use, so that they can focus on shipping quality software.</p>

<p>What does this mean exactly? First, we’re open sourcing our analysis tools, including the engines and algorithms we use to evaluate code. If you have a running Docker host, using Code Climate on your command line is as easy as:</p>
<div class="highlight"><pre class="highlight plaintext"><code>boot2docker up &amp;&amp; `boot2docker shellinit`
brew tap codeclimate/formulae
brew install codeclimate
</code></pre></div>
<p>We’re also enabling anyone to write static analysis engines that run on our servers by following a simple <a href="https://github.com/codeclimate/spec ">specification</a>. No longer will you have to wait for us to provide support for your programming languages, frameworks and libraries of choice. Finally, using our new <a href="https://github.com/codeclimate/codeclimate">Code Climate CLI</a>, you can now run any Code Climate-compatible static analysis on your laptop &ndash; for free.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/platform-cli-9f7fb307.png" alt="Code Climate Platform CLI" /></p>

<p>Let’s look at each of these in turn&hellip;</p>

<h2>Open Source</h2>

<p>We’re releasing the static analysis engines that power the new Code Climate Platform, and going forward, all of our static analysis code will be published under Open Source licenses. Code Climate has always provided free analysis to Open Source projects, and this continues to deepen our commitment to, and participation in, the OSS community.</p>

<p>Code Climate has always stood on the shoulders of giants in depending on Open Source libraries for the bulk of our static analysis algorithms. We would not exist today if not for the great work of people like Ryan Davis (Flog, Flay) and Justin Collins (Brakeman) that demonstrated the value of static analysis and allowed us to quickly bring it to developers.</p>

<p>Open Source static analysis means you can dig in and understand exactly how your code is being evaluated. And customizing static analysis algorithms becomes as simple as clicking the &ldquo;Fork&rdquo; button on GitHub&hellip;</p>

<h2>Extensible</h2>

<p>With the release of our new <a href="https://github.com/codeclimate/spec">Code Climate Engine Specification</a>, anyone can write static analysis engines that run on our servers. Code Climate’s set of officially supported languages can be augmented with community supported static analysis engines so that you can get confidence in your code, regardless of  your choice of technology. For years, our most common type of feature request has been, &ldquo;Can you add support for X?&rdquo;, where X is a programming language, version of a language, or sometimes a framework. We’ve always wanted Code Climate to work for all developers, but in the past we were limited by the effort required to add new languages.</p>

<p>We believe that you shouldn’t have to wait for a vendor to add support for the languages you love, so are finally removing ourselves as the bottleneck to new static analysis features. Anyone who is interested in using Code Climate with their favorite languages, frameworks and libraries is free to build an engine to do so. Results from engines retain all the benefits of the Code Climate product, including automatic analysis of every Pull Request, comparison views, ratings/GPAs, and notifications.
Of course, there’s already a vibrant community of OSS static analysis tools, and we’re excited to see what people are able to build and integrate. It’s really astounding how simple it is to build a Code Climate engine, as we’ve watched developers build functioning analysis from scratch in a matter of a couple hours.</p>

<p>If you want to give it a try, join our new <a href="https://codeclimate.com/dev_form">Developer Program</a> and we’ll be there to guide you along the way.</p>

<h2>Run Anywhere</h2>

<p>In addition to the spec, we’re also releasing the <a href="https://github.com/codeclimate/codeclimate">Code Climate CLI</a>, which makes it easy to get static analysis results (both from Code Climate’s official engines and community-supported engines) in one clear, unified report right on your laptop. When you’re ready, you can load your repository into codeclimate.com and we’ll automatically apply the exact same configuration you use locally to analyze every commit and Pull Request, making the results available to your entire team.</p>

<p>To make static analysis truly ubiquitous, we realized it was not enough to support a wide variety of tools, we need to make it trivial to run these tools anywhere the developer is working. You shouldn’t have to wait to push your source code to a remote server to get clear, actionable static analysis results. Now it’s possible to easily run the same static analysis we run on our servers on your command line.</p>

<h2>New Static Analysis Engines</h2>

<p>We’re fortunate to be partnering with creators of two prominent Open Source projects who understand the value of static analysis in ensuring healthy code, Tom Dale from Ember.js and Laurent Sansonetti from <a href="http://rubymotion.com">RubyMotion</a>. Here’s what they have to say about the Code Climate Platform:</p>

<blockquote>
<p>&ldquo;The Ember community takes good tooling seriously. I&rsquo;m excited to partner with Code Climate and bring their service to our users because better static analysis means better Ember apps.&rdquo;</p>
</blockquote>

<p>&ndash; Tom Dale from Ember.js</p>

<blockquote>
<p>&ldquo;HipByte is excited to partner with CodeClimate to provide clear and reliable code reviews for RubyMotion projects. RubyMotion allows Ruby developers to write cross-platform apps for iOS and Android by leveraging the native platform APIs, and a tool for static analysis means fewer crashes and more reliable applications.&rdquo;</p>
</blockquote>

<p>&ndash; Laurent Sansonetti from <a href="http://rubymotion.com">RubyMotion</a></p>

<p>Accordingly, we’re releasing an Ember.js engine that brings the <a href="https://github.com/abuiles/ember-watson">Ember Watson</a> tool to all Code Climate users, and a set of custom checks for RubyMotion that will help ensure that your application code is reliable.</p>

<p>In addition, we’re proud to release eight new static analysis engines that you can start using with Code Climate today:</p>

<ul>
<li>Gofmt, Govet and Golint - The official style, bug and lint checkers from the Go team</li>
<li>CoffeeLint - Style checking for the CoffeeScript dialect of JavaScript</li>
<li>CSSLint - Style checking for all CSS stylesheets</li>
<li>Rubocop - Style and quality checks for Ruby code (including support for RRuby 2.2+)</li>
<li>ESLint - Linting and style checking for your modern EcmaScript/JavaScript code</li>
<li>Bundler Audit - Find security vulnerabilities in your Ruby dependencies</li>
<li>PHP CodeSniffer - Style checking for PHP</li>
</ul>

<h2>Healthy Code Ships Faster</h2>

<p>In many ways, our new platform is a culmination of the experience we’ve gained over the past four years building and operating the most popular static analysis app. We’re excited to bring this to you, and look forward to continuing to bring you the best tools to ship better code, faster.
If you want to try out the new Code Climate, <a href="https://github.com/codeclimate/codeclimate">download our CLI</a> to get started. We’d love to hear what you think!</p>

<p><a class="hn-link" href="javascript:window.location=%22http://news.ycombinator.com/submitlink?u=%22+encodeURIComponent(document.location)+%22&t=%22+encodeURIComponent(document.title)">Discuss on Hacker News</a></p>
]]>
    </content>
  </entry>
  <entry>
    <title>An Introduction To Object-Oriented Programming in Swift</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/oo-swift/"/>
    <id>https://codeclimate.com/blog/oo-swift/</id>
    <updated>2014-06-19T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>In exciting programming language news (how often do you get to say that?) Apple recently released Swift, a compiled language meant to augment Objective-C for development on Desktop and Mobile iOS platforms. While Swift&rsquo;s primary audience at this (very early) point is iOS developers, the language contains some interesting functionality for program design that will appeal to a wider audience, including Ruby, JavaScript, and PHP developers.</p>

<p>In this post I&rsquo;ll take a look at three of the program design constructs that Swift provides: Classes, Structures, and Protocols. I&rsquo;ll discuss how they can contribute to well-designed Object-Oriented (OO) programs in a way that might be interesting to dynamic language programmers, and show how aspects of their design reflect concerns of the platform for which they were developed.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/ooswift-56961db1.png" alt="OOSWIFT" /></p>

<h3>Classes and Structures</h3>

<p>The best source of information about Swift so far is <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language">The Swift Programming Language</a>, a free e-book provided by Apple. It contains a first pass introduction to the language, a language reference, and a good deal of example code. After introducing the basic facilities of the language - its philosophy, the basic available types and data structures, control flow, closures, and so on - we get to the section on Classes and Structures.</p>

<blockquote>
<p>&ldquo;Classes and structures are general-purpose, flexible constructs that become the building blocks of your program’s code.&rdquo; [1]</p>
</blockquote>

<p>This sounds similar to the functionality of a Class or Module in Ruby. From this list of the features of Classes and Structures, we see even more similarities. Classes and Structures can both:</p>

<ul>
<li>Define properties to store values</li>
<li>Define methods to provide functionality</li>
<li>Define initializers to set up their initial state</li>
<li>Be extended to expand their functionality beyond a default implementation</li>
</ul>

<p>This means that Swift provides similar functionality to familiar OO Programming Languages. We can model problems using objects which can encapsulate data and functionality, and build complex relationships between these objects in a modular fashion. Curious readers might have the same reaction  to this as I did - if it&rsquo;s the case that both classes and structures can do the above, which is a reasonable set of functionality to expect from classes, why are there two constructs? What are the differences between them, and why does Swift as a programming language need both?</p>

<p>First, let&rsquo;s take a look at what Classes can do that Structures cannot. Classes provide functionality for two crucial pieces of OO functionality that Ruby developers, for instance, tend to rely on somewhat heavily:</p>

<ul>
<li>Inheritance, where one class can inherit the characteristics of another</li>
<li>Type casting, where you can check and interpret the type of a class instance at runtime</li>
</ul>

<p>Additionally, classes provide the following facilities which are stated in terms familiar to those with experience managing resources and memory manually:</p>

<ul>
<li>Deinitializers, to enable an instance of a class to free up any resources it has assigned</li>
<li>Reference counting, to allow for more than one reference to a class instance</li>
</ul>

<p>Stated in other terms, inheritance, type casting, deinitializers, and reference counting make it possible to expressively create designs which employ the full compliment of OO techniques.</p>

<p>From my perspective, Classes and Structures have just the right amount of overlap in functionality, leaving enough room for developers to make reasoned decisions about which construct to employ according to the purpose it may be used for. The differences hinge on how instances of Classes and Structures are represented in memory after they are initialized &ndash; structure instances are always <strong>passed by value</strong> and class instances are always <strong>passed by reference</strong>. This distinction is something that dynamic language developers typically do not have to spend much time thinking about - on a mobile platform, however, this kind of thinking becomes very important.</p>

<p>Different memory semantics is not the only advantage of having these distinct types, however. Because structures are simpler than classes, and cannot be as heavily modified after declaration, they provide an opportunity to create value objects which represent pieces of data independent from their behavior. This is very useful.</p>

<p>While Classes and Structures cover much of the familiar ground with respect to OO functionality in Ruby or Python, there is one more construct that might not be so familiar that I&rsquo;d like to point out before we draw any conclusions on Swift&rsquo;s OO design capabilities.</p>

<h3>Protocols</h3>

<p>Protocols are an interesting addition to the already rich world of classes and structures. They provide a way to define behavior separately from the classes which implement them:</p>

<blockquote>
<p>&ldquo;A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality&rdquo;</p>
</blockquote>

<p>Similar constructs exist in Java, Go, and other languages, but many dynamic languages do not embrace this design style. Protocols embrace flexible design by encapsulating the necessary data and behavior for a domain idea outside the scope of a Class or Structure definition. This means that a concept can be represented separately from its implementation, allowing for more creative reuse, composition, and more.</p>

<p>To illustrate the usefulness of Protocols, consider the development of a small networked process to record some information from a system over time. You might want to have the system write to a Key-Value store, or to disk, or to STDOUT, depending on a variety of circumstances. In this case, you would simply define a Protocol:</p>
<div class="highlight"><pre class="highlight plaintext"><code>protocol BackEnd {
    func get(Int) -&gt; Int
    func set(Int) -&gt; Bool
}
</code></pre></div>
<p>This protocol requires that anything which implements them must contain at least two instance methods - <code>get</code>, which accepts an Integer and returns an Integer, and <code>set</code>, which accepts an Integer and returns a Boolean value. A class that implements this Protocol might look something like the following:</p>
<div class="highlight"><pre class="highlight plaintext"><code>class RedisBackEnd : BackEnd {
    func get(id: Int) -&gt; Int {
        // Get 'val' from Redis based on 'id'
        let val = getFromRedis(id)
        return val
    }

    func set(val: Int) -&gt; Bool {
        // Store 'val' in Redis here
        let boolFromRedis = storeInRedis(val)
        return boolFromRedis
    }
}
</code></pre></div>
<p>You could imagine similar classes for the other backends I mentioned above. This is a very convenient solution for swapping out backends when you need to run your process in different locations and under different circumstances - simply implement new ones as needed, and pass them in wherever a Backend is needed.</p>

<p>Defining a Protocol and implementing it is really the tip of the iceberg, however - things can get very subtle and complex. Protocols can be treated as types, and intricate hierarchies can be created with them. While it is interesting to look through the Swift book to see these examples, I don&rsquo;t believe they are the real selling points of protocols. Used simply and in combination with classes and structures, protocols provide a missing piece of the design puzzle that often vexes programmers in dynamic languages.</p>

<h3>Conclusion</h3>

<p>Swift is a very interesting programming language that at first blush appears to have all of the necessary components to build expressive OO programs. In addition to classes, structures, and protocols, Ruby developers might also want to look into <code>Extensions</code> which offer mixin-like capabilities.</p>

<p>Whether you prefer inheritance, composition, or even a more esoteric SmallTalk style flavor of OO, it seems that Swift will be able to support you. What kinds of domains have you modeled in Ruby that you&rsquo;d like to try in Swift? Do you notice any shortcomings? If you were to try to translate a program from Ruby, Python, or JavaScript to swift, do you think it would be easy? Would it change the way you think about program design? I&rsquo;d love to hear more - to the comments!</p>

<h3>Works Cited</h3>

<p>[1] Apple Inc. &ldquo;The Swift Programming Language.&rdquo; iBooks.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>5 Reasons to Use Protocol Buffers Instead of JSON For Your Next Service</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/choose-protocol-buffers/"/>
    <id>https://codeclimate.com/blog/choose-protocol-buffers/</id>
    <updated>2014-06-05T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Service-Oriented Architecture has a well-deserved reputation amongst Ruby and Rails developers as a solid approach to easing painful growth by extracting concerns from large applications. These new, smaller services typically still use Rails or Sinatra, and use JSON to communicate over HTTP. Though JSON has many obvious advantages as a data interchange format - it is human readable, well understood, and typically performs well - it also has its issues.</p>

<p>Where browsers and JavaScript are not consuming the data directly &ndash; particularly in the case of internal services &ndash; it&rsquo;s my opinion that structured formats, such as Google&rsquo;s Protocol Buffers, are a better choice than JSON for encoding data. If you&rsquo;ve never seen Protocol Buffers before, <a href="https://developers.google.com/protocol-buffers/docs/overview">you can check out some more information here</a>, but don&rsquo;t worry - I&rsquo;ll give you a brief introduction to using them in Ruby before listing the reasons why you should consider choosing Protocol Buffers over JSON for your next service.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/pb_json-45e02904.png" alt="PBJSON" /></p>

<h3>A Brief Introduction to Protocol Buffers</h3>

<p>First of all, what are Protocol Buffers? The docs say:</p>

<blockquote>
<p>&ldquo;Protocol Buffers are a way of encoding structured data in an efficient yet extensible format.&rdquo;</p>
</blockquote>

<p>Google developed Protocol Buffers for use in their internal services. It is a binary encoding format that allows you to specify a <em>schema</em> for your data using a specification language, like so:</p>
<div class="highlight"><pre class="highlight plaintext"><code>message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}
</code></pre></div>
<p>You can package messages within namespaces or declare them at the top level as above. The snippet defines the schema for a <code>Person</code> data type that has three fields: <code>id</code>, <code>name</code>, and <code>email</code>. In addition to naming a field, you can provide a type that will determine how the data is encoded and sent over the wire - above we see an <code>int32</code> type and a <code>string</code> type. Keywords for validation and structure are also provided (<code>required</code> and <code>optional</code> above), and fields are numbered, which aids in backward compatibility, which I&rsquo;ll cover in more detail below.</p>

<p>The Protocol Buffers specification is implemented in various languages: Java, C, Go, etc. are all supported, and most modern languages have an implementation if you look around. Ruby is no exception and there are a few different Gems that can be used to encode and decode data using Protocol Buffers. What this means is that one spec can be used to transfer data between systems regardless of their implementation language.</p>

<p>For example, installing the <code>ruby-protocol-buffers</code> Ruby Gem installs a binary called <code>ruby-protoc</code> that can be used in combination with the main Protocol Buffers library (<code>brew install protobuf</code> on OSX) to automatically generate stub class files that are used to encode and decode your data for you. Running the binary against the <code>proto</code> file above yields the following Ruby class:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #999988;font-style: italic">#!/usr/bin/env ruby</span>
<span style="color: #999988;font-style: italic"># Generated by the protocol buffer compiler. DO NOT EDIT!</span>
<span style="color: #0086B3">require</span> <span style="color: #d14">'protocol_buffers'</span>

<span style="color: #999988;font-style: italic"># forward declarations</span>
<span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Person</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">ProtocolBuffers</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Message</span><span style="background-color: #f8f8f8">;</span> <span style="color: #000000;font-weight: bold">end</span>

<span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Person</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">ProtocolBuffers</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Message</span>
  <span style="background-color: #f8f8f8">set_fully_qualified_name</span> <span style="color: #d14">"Person"</span>

  <span style="background-color: #f8f8f8">required</span> <span style="color: #990073">:int32</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span><span style="background-color: #f8f8f8">,</span> <span style="color: #009999">1</span>
  <span style="background-color: #f8f8f8">required</span> <span style="color: #990073">:string</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #009999">2</span>
  <span style="background-color: #f8f8f8">optional</span> <span style="color: #990073">:string</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:email</span><span style="background-color: #f8f8f8">,</span> <span style="color: #009999">3</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>As you can see, by providing a schema, we now automatically get a class that can be used to encode and decode messages into Protocol Buffer format (inspect the code of the <code>ProtocolBuffers::Message</code> base class in the Gem for more details). Now that we&rsquo;ve seen a bit of an overview, let&rsquo;s dive in to the specifics a bit more as I try to convince you to consider taking a look at Protocol Buffers - here are five reasons to start.</p>

<p><a id="schemas-awesome"></a></p>

<h3>Reason #1: Schemas Are Awesome</h3>

<p>There is a certain painful irony to the fact that we carefully craft our data models inside our databases, maintain layers of code to keep these data models in check, and then allow all of that forethought to fly out the window when we want to send that data over the wire to another service. All too often we rely on inconsistent code at the boundaries between our systems that don&rsquo;t enforce the structural components of our data that are so important. Encoding the semantics of your business objects once, in <code>proto</code> format, is enough to help ensure that the signal doesn&rsquo;t get lost between applications, and that the boundaries you create enforce your business rules.</p>

<p><a id="backward-compatible"></a></p>

<h3>Reason #2: Backward Compatibility For Free</h3>

<p>Numbered fields in <code>proto</code> definitions obviate the need for version checks which is one of the explicitly stated motivations for the design and implementation of Protocol Buffers. As the developer documentation states, the protocol was designed in part to avoid &ldquo;ugly code&rdquo; like this for checking protocol versions:</p>
<div class="highlight"><pre class="highlight plaintext"><code>if (version == 3) {
  ...
} else if (version &gt; 4) {
  if (version == 5) {
    ...
  }
  ...
}
</code></pre></div>
<p>With numbered fields, you never have to change the behavior of code going forward to maintain backward compatibility with older versions. As the documentation states, once Protocol Buffers were introduced:</p>

<blockquote>
<p>&ldquo;New fields could be easily introduced, and intermediate servers that didn&rsquo;t need to inspect the data could simply parse it and pass through the data without needing to know about all the fields.&rdquo;</p>
</blockquote>

<p>Having deployed multiple JSON services that have suffered from problems relating to evolving schemas and backward compatibility, I am now a big believer in how numbered fields can prevent errors and make rolling out new features and services simpler.</p>

<p><a id="less-boilerplate"></a></p>

<h3>Reason #3: Less Boilerplate Code</h3>

<p>In addition to explicit version checks and the lack of backward compatibility, JSON endpoints in HTTP based services typically rely on hand-written ad-hoc boilerplate code to handle the encoding and decoding of Ruby objects to and from JSON. Parser and Presenter classes often contain hidden business logic and expose the fragile nature of hand parsing each new data type when a stub class as generated by Protocol Buffers (that you generally never have to touch) can provide much of the same functionality without all of the headaches. As your schema evolves so too will your <code>proto</code> generated classes (once you regenerate them, admittedly), leaving more room for you to focus on the challenges of keeping your application going and building your product.</p>

<p><a id="validations"></a></p>

<h3>Reason #4: Validations and Extensibility</h3>

<p>The <code>required</code>, <code>optional</code>, and <code>repeated</code> keywords in Protocol Buffers definitions are extremely powerful. They allow you to encode, at the schema level, the shape of your data structure, and the implementation details of how classes work in each language are handled for you. The Ruby <code>protocol_buffers</code> library will raise exceptions, for example, if you try to encode an object instance which does not have the required fields filled in. You can also always change a field from being <code>required</code> to being <code>optional</code> or vice-versa by simply rolling to a new numbered field for that value. Having this kind of flexibility encoded into the semantics of the serialization format is incredibly powerful.</p>

<p>Since you can also embed <code>proto</code> definitions inside others, you can also have generic <code>Request</code> and <code>Response</code> structures which allow for the transport of other data structures over the wire, creating an opportunity for truly flexible and safe data transfer between services. Database systems like Riak use protocol buffers to great effect - I recommend checking out their interface for some inspiration.</p>

<p><a id="interop"></a></p>

<h3>Reason #5: Easy Language Interoperability</h3>

<p>Because Protocol Buffers are implemented in a variety of languages, they make interoperability between polyglot applications in your architecture that much simpler. If you&rsquo;re introducing a new service with one in Java or Go, or even communicating with a backend written in Node, or Clojure, or Scala, you simply have to hand the <code>proto</code> file to the code generator written in the target language and you have some nice guarantees about the safety and interoperability between those architectures. The finer points of platform specific data types should be handled for you in the target language implementation, and you can get back to focusing on the hard parts of your problem instead of matching up fields and data types in your ad hoc JSON encoding and decoding schemes.</p>

<h3>When Is JSON A Better Fit?</h3>

<p>There do remain times when JSON is a better fit than something like Protocol Buffers, including situations where:</p>

<ul>
<li>You need or want data to be human readable</li>
<li>Data from the service is directly consumed by a web browser</li>
<li>Your server side application is written in JavaScript</li>
<li>You aren&rsquo;t prepared to tie the data model to a schema</li>
<li>You don&rsquo;t have the bandwidth to add another tool to your arsenal</li>
<li>The operational burden of running a different kind of network service is too great</li>
</ul>

<p>And probably lots more. In the end, as always, it&rsquo;s very important to keep tradeoffs in mind and blindly choosing one technology over another won&rsquo;t get you anywhere.</p>

<h3>Conclusion</h3>

<p>Protocol Buffers offer several compelling advantages over JSON for sending data over the wire between internal services. While not a wholesale replacement for JSON, especially for services which are directly consumed by a web browser, Protocol Buffers offers very real advantages not only in the ways outlined above, but also typically in terms of speed of encoding and decoding, size of the data on the wire, and more.</p>

<p>What are some services you could extract from your monolithic application now? Would you choose JSON or Protocol Buffers if you had to do it today? We&rsquo;d love to hear more about your experiences with either protocol in the comments below - let&rsquo;s get discussing!</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Does Team Size Impact Code Quality?</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/does-team-size-impact-code-quality/"/>
    <id>https://codeclimate.com/blog/does-team-size-impact-code-quality/</id>
    <updated>2014-05-21T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>There are a few common questions that we get when speaking with Code Climate customers. They range from &ldquo;What&rsquo;s the Code Climate score for the Code Climate repo?&rdquo; to &ldquo;What&rsquo;s the average GPA of a Rails application?&rdquo; When I think back on the dozens of conversations I&rsquo;ve had about Code Climate, one thing is clear - people are interested in our data!</p>

<p>Toward that end, this is the first post in a series intended to explore Code Climate&rsquo;s data set in ways that can deepen our understanding of software engineering, and hopefully quench some people&rsquo;s curiosities as well. We have lots of questions to ask of our data set, and we know that our users have lots of their own, but we wanted to start with one that&rsquo;s fundamental to Code Climate&rsquo;s mission, and that we&rsquo;re asked a lot:</p>

<blockquote>
<p>Does Team Size Impact Code Quality?</p>
</blockquote>

<p>Is it true that more developers means more complexity? Is there an ideal number of developers for a team? What can we learn from this? Let&rsquo;s find out!</p>

<h3>The Methodology</h3>

<p>There are a variety of different ways that this question can be interpreted, even through the lens of our data set. Since this is the first post in a series, and we&rsquo;re easing into this whole &ldquo;<a href="https://twitter.com/cdixon/status/428914681911070720">data science</a>&rdquo; thing, I decided to start with something pretty straightforward - plotting author count against Code Climate&rsquo;s calculated GPA for a repo.</p>

<p>Author count is calculated by summing the authors present in commits over a given period, in this case 30 days. The GPA is calculated by looking up the most recent quality report for a repo and using the GPA found there. Querying this data amounted to a few simple lines of Ruby code to extract from our database, including exporting the data as a CSV for processing elsewhere.</p>

<p>I decided to limit the query to our private repositories because the business impact of the answer to the question at hand seems potentially significant. By analyzing private repositories we will be able to see many more Rails applications than are available in Open Source, and additionally, the questions around Open Source repos are manifold and deserve to be treated separately.</p>

<p><em>Please note that the data I&rsquo;m presenting is completely anonymized and amounts to aggregate data from which no private information can be extrapolated.</em></p>

<p>Once I had the information in an easily digestible CSV format, I began to plot the data in a program called <a href="http://wizardmac.com/">Wizard</a>, which makes statistical exploration dead simple. I was able to confirm that there was a negative correlation between the size of a team and the Code Climate GPA, but the graph it produces isn&rsquo;t customizable enough to display here. From there I went to R, where a few R wizard friends of mine helped me tune a few lines of code that transform the CSV into the graph below:</p>

<p><img src="https://dl.dropboxusercontent.com/u/1401061/Screenshot%202014-05-21%2017.45.22.png" alt="Author Count GPA Scatterplot" /></p>

<p>The fit line above indicates that there is indeed <em>an indirect relationship between code quality and team size</em>. While not a very steep curve, the line shows that a decline of over 1 GPA point is possible when team sizes grow beyond a certain point; let&rsquo;s dig a little deeper into this data.</p>

<p>The graph is based on data from 10,000 observations, where each is a distinct repo and the GPA measurement and author count measurements are the latest available. The statistical distributions of the two columns show that the data needed some filtering. For example, the GPA summary seems quite reasonable:</p>
<div class="highlight"><pre class="highlight plaintext"><code>&gt; summary(observations$GPA)
   Min. 1st Qu.  Median    Mean  3rd Qu.    Max.
  0.000   2.320   3.170   2.898    3.800   4.000
</code></pre></div>
<p>As you would expect, a pretty healthy distribution of GPAs. The author count, on the other hand, is pretty out of whack:</p>
<div class="highlight"><pre class="highlight plaintext"><code>&gt; summary(observations$AuthorCount)
   Min. 1st Qu.  Median    Mean  3rd Qu.     Max.
  1.000   1.000   2.000   3.856   4.000   130.000
</code></pre></div>
<p>The 3rd Quantile ranges 4-130! That&rsquo;s way too big of a spread, so I&rsquo;ve corrected for that a bit by filtering the max to 50 in the graph above. This gives enough of a trend to show how new teams may tend to fall according to the model, but doesn&rsquo;t completely blow it out with outliers. After working on this graph with the full data set and showing it to a couple people, some themes emerged:</p>

<ul>
<li>The data should be binned, with 10+ authors being the largest team size</li>
<li>Lines or bars could be used to show the &ldquo;density&rdquo; of GPAs for a specific binned team size</li>
</ul>

<p>Some CSV and SQL magic made it pretty straightforward to bin the data, which can then be plotted in R using a geometric density function applied to team sizes per GPA score. This lets us see areas of concentration of GPA scores per team size bin.</p>

<p><img src="https://dl.dropboxusercontent.com/u/1401061/density.png" alt="Team Size GPA Density Graph" /></p>

<p>Now that the team sizes are broken up into smaller segments, we can see some patterns emerge. It appears <em>easier to achieve a 4.0 GPA if you are a solo developer</em> and additionally, the <em>density of teams greater than 10 concentrates under the 3.0 GPA mark.</em> This is a much richer way to look at the data than the scatterplot above and I learned a lot comparing the two approaches.</p>

<p>Nice first impressions, but now that we&rsquo;ve seen the graphs, what can we learn?</p>

<h3>Conclusions</h3>

<p>How to interpret the results of this query is quite tricky. On one hand, there does appear to be a correlation supporting the notion that smaller teams can produce more organized code. On the other hand, the strength of this correlation is not extreme, and it is worth noting that teams of up to 10, 20, and 30 members are capable of maintaining very respectable GPAs which are greater than 3.0 (recall from the summary above that the mean GPA is 2.898 and that only the top 25% score greater than 3.8).</p>

<p>The scatterplot graph shows a weak fit line which suggests a negative correlation, while the density line graph (which could also be rendered with bars) shows that <em>teams of up to 10 members have an easier time maintaining a 3.0+ GPA than teams with more than 10 members</em>. Very intriguing.</p>

<p>It is worth considering what other factors could be brought into play when it comes to this model. Some obvious contenders include the size of the code base, the age of the code base, and the number of commits in a given period. It&rsquo;s also worth looking into how this data would change if all of the historical data was pulled up, to sum the total number of authors over the life of a project.</p>

<p>One conclusion to draw might be that recent arguments for breaking down large teams into smaller, service oriented teams may have some statistical backing. If we wanted to be as scientific about it as possible, we can look at how productive teams tend to be in certain size ranges and produce an ideal team size as a function of productivity and 75% percentile quality scores. Teams can be optimized to produce a certain amount of code of a certain quality for a certain price - but now we&rsquo;re sounding a little creepy.</p>

<p>My take is that this data supports what most developers already know - that large teams with large projects are hard to keep clean; that&rsquo;s why we work as hard as we do. If you&rsquo;re nearing that 10-person limit, know that you&rsquo;ll have to work extra hard to beat the odds and have a higher than 3.0 GPA.</p>

<p>On a parting note, we are sure that there are more sophisticated statistical analyses that could be brought to bear on this data, which is why  <strong>we have <a href="https://gist.github.com/mrb/149758f776d42a35416e">decided to publish the data set and the code</a> for this blog post here. Check it out and let us know if you do anything cool with it!</strong></p>

<p><em>Special thanks to Allen Goodman (<a href="http://twitter.com/goodmanio">@goodmanio</a>), JD Maturen (<a href="http://twitter.com/jdmaturen">@jdmaturen</a>), and Leif Walsh (<a href="http://twitter.com/goodmanio">@leifw</a>) for their code and help and to Julia Evans (<a href="http://twitter.com/b0rk">@b0rk</a>) for the inspiration.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Gradual Type Checking for Ruby</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/gradual-type-checking-for-ruby/"/>
    <id>https://codeclimate.com/blog/gradual-type-checking-for-ruby/</id>
    <updated>2014-05-06T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Ruby developers often wax enthusiastic about the speed and agility with which they are able to write programs, and have relied on two techniques more than any other to support this: tests and documentation.</p>

<p>After spending some time looking into other languages and language communities, it&rsquo;s my belief that as Ruby developers, we are missing out on a third crucial tool that can extend our design capabilities, giving us richer tools with which to reason about our programs. This tool is a rich type system.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/design_tools_for_ruby-1e08da56.jpg" alt="Design Tools for Ruby" /></p>

<p>To be clear, I am in no way saying that tests and documentation do not have value, nor am I saying that the addition of a modern type system to Ruby is necessary for a certain class of applications to succeed &ndash; the number of successful businesses started with Ruby and Rails is proof enough. Rather, I am saying that a richer type system with a well designed type-checker could give our design several advantages that are hard to accomplish with tests and documentation alone:</p>

<ul>
<li><p><strong>Truly executable documentation</strong></p>

<p>Types declared for methods or fields are enforced by the type checker. Annotated classes are easy to parse by developers and documentation can be extracted from type annotations.</p></li>
<li><p><strong>Stable specification</strong></p>

<p>Tests which assert the input and return values of methods are brittle, raise confusing errors, and bloat test suites; documentation gets out of sync. Type annotations change with your implementation and can help maintain interface stability.</p></li>
<li><p><strong>Meaningful error messages</strong></p>

<p>Type checkers are valuable in part because they bridge the gap between the code and the meaning of a program. Error messages which inform you not only that you made a mistake, but how (and potentially how to fix it) are possible with the right tools.</p></li>
<li><p><strong>Type driven design</strong></p>

<p>Considering the design of a module of a program through its types can be an interesting exercise. With advancements in type checking and inference for dynamic programming languages, it may be possible to rely on these tools to help guide our program design.</p></li>
</ul>

<p>Integrating traditional typing into a dynamic language like Ruby is inherently challenging. However, in searching for a way to integrate these design advantages into Ruby programs, I have come across a very interesting body of research about &ldquo;gradual typing&rdquo; systems. These systems exist to include, typically on a library level, the kinds of type checking and inference functionality that would allow Ruby developers to benefit from typing without the expected overhead. [1]</p>

<p>In doing this research I was pleasantly surprised to find that four researchers from the University of Maryland&rsquo;s Department of Computer Science have designed such a system for Ruby, and have published a paper summarizing their work. It is presented as &ldquo;The Ruby Type Checker&rdquo; which they describe as  &ldquo;&hellip;a tool that adds type checking to Ruby, an object-oriented, dynamic scripting language.&rdquo;  [2] Awesome, let&rsquo;s take a look at it!</p>

<h4>The Ruby Type Checker</h4>

<p>The implementation of the Ruby Type Checker (rtc) is described by the authors as &ldquo;a Ruby library in which all type checking occurs at run time; thus it checks types later than a purely static system, but earlier than a traditional dynamic type system.&rdquo; So right away we see that this tool isn&rsquo;t meant to change the principal means of development relied on by Ruby developers, but rather to augment it. This is similar to how we think about Code Climate - as a tool which brings information about problems in your code earlier in your process.</p>

<p>What else can it do? A little more from the abstract:</p>

<blockquote>
<p>&ldquo;Rtc supports type annotations on classes, methods, and objects and rtc provides a rich type language that includes union and intersection types, higher- order (block) types, and parametric polymorphism among other features.&rdquo;</p>
</blockquote>

<p>Awesome. Reading a bit more into the paper we see that rtc operates by two main mechanisms:</p>

<ol>
<li>Compiling field and method annotations to a data structure that is later used for checks</li>
<li>Optionally proxying calls through a system that gathers type information, allowing type errors to be raised on method entry and exit</li>
</ol>

<p>So now let&rsquo;s see how these mechanisms might be used in practice. We&rsquo;ll walk through the ways that you can annotate the type of a class&rsquo;s fields, and show what method type declarations look like.</p>

<p>First, field annotations on a class look like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Foo</span>
  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@title: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>And method annotations should look familiar to you if you&rsquo;ve seen type declarations for methods in other languages:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Foo</span>
  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"self.build: (Hash) -&gt; Post"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #999988;font-style: italic"># ... method definition</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Where the input type appears in parens, and then the return type appears after the <code>-&gt;</code> arrow that represents function application.</p>

<p>Similar to the work in typed Clojure and typed Racket (two of the more well-developed &lsquo;gradual&rsquo; type systems), rtc is available as a library and can be used or not used a la carte. This flexibility is fantastic for Ruby developers. It means that we can isolate parts of our programs which might be amenable to type-driven design, and selectively apply the kinds of run time guarantees that type systems can give us, without having to go whole hog. Again, we don&rsquo;t have to change the entire way we work, but we might augment our tools with just a little bit more.</p>

<h4>How Would We Use Gradual Typing?</h4>

<p>Asking the following question on Twitter got me A LOT of opinions, perhaps unsurprisingly:</p>

<blockquote class="twitter-tweet" lang="en"><p>What are the canonical moments of &ldquo;Damn, I wish I had types here?&rdquo; in a dynamic language?</p>&mdash; mrb (@mrb_bk) <a href="https://twitter.com/mrb_bk/statuses/461222564736798722">April 29, 2014</a></blockquote>

<script async src="https://d341kum51qu34d.cloudfront.net//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>The answers ranged from &ldquo;never&rdquo; to &ldquo;always&rdquo; to more thoughtful responses such as &ldquo;during refactoring&rdquo; or &ldquo;when dealing with data from the outside world.&rdquo; The latter sounded like a use case to me, so I started daydreaming about what a type checked model in a Rails application would look like, especially one that was primarily accessed through a controller that serves a JSON API.</p>

<p>Let&rsquo;s look at a <code>Post</code> class:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Post</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">PersistenceLogic</span>

  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:id</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:timestamp</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This post class includes some <code>PersistanceLogic</code> so that you can write:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create</span><span style="background-color: #f8f8f8">({</span><span style="color: #990073">id: </span><span style="color: #d14">"foo"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">title: </span><span style="color: #d14">"bar"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">timestamp: </span><span style="color: #009999">1398822693</span><span style="background-color: #f8f8f8">})</span>
</code></pre></div>
<p>And be happy with yourself, secure that your data is persisted. To wire this up to the outside world, now imagine that this class is hooked up via a <code>PostsController</code>:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">PostsController</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create</span>
    <span style="color: #008080">Post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:post</span><span style="background-color: #f8f8f8">])</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Let&rsquo;s assume that we don&rsquo;t need to be concerned about security here (though that&rsquo;s something that a richer type system can potentially help us with as well). This <code>PostsController</code> accepts some JSON:</p>
<div class="highlight"><pre class="highlight json"><code><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
  </span><span style="color: #d14">"post"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"id"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"0f0abd00"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"title"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"Cool Story"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb">
    </span><span style="color: #d14">"timestamp"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"1398822693"</span><span style="color: #bbbbbb">
  </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb">
</span></code></pre></div>
<p>And instead of having to write a bunch of boilerplate code around how to handle <code>timestamp</code> coming in as a string, or <code>title</code> not being present, etc. you could just write:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Post</span>
  <span style="background-color: #f8f8f8">rtc_annotated</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">PersistenceLogic</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@id: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:id</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@title: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@timestamp: Fixnum'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:timestamp</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Which might lead you to want a type-checked <code>build</code> method (<code>rtc_annotate</code> triggers type checking on a specific object instance):</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Post</span>
  <span style="background-color: #f8f8f8">rtc_annotated</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">PersistenceLogic</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@id: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:id</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@title: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@timestamp: Fixnum'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:timestamp</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"self.build: (Hash) -&gt; Post"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span>           <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">rtc_annotate</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"Post"</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span>        <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">title</span>     <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:title</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">timestamp</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:timestamp</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>But, oops! When you run it you see that you didn&rsquo;t write that correctly:</p>
<div class="highlight"><pre class="highlight shell"><code><span style="color: #000000;font-weight: bold">[</span>2] pry<span style="color: #000000;font-weight: bold">(</span>main<span style="color: #000000;font-weight: bold">)&gt;</span> Post.build<span style="color: #000000;font-weight: bold">({</span>id: <span style="color: #d14">"0f0abd00"</span>, title: <span style="color: #d14">"Cool Story"</span>,
timestamp: 1398822693<span style="color: #000000;font-weight: bold">})</span> Rtc::TypeMismatchException: invalid <span style="color: #000000;font-weight: bold">return </span><span style="color: #0086B3">type
</span><span style="color: #000000;font-weight: bold">in </span>build, expected Post, got Fixnum
</code></pre></div>
<p>You can fix that:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Post</span>
  <span style="background-color: #f8f8f8">rtc_annotated</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">PersistenceLogic</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@id: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:id</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@title: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@timestamp: Fixnum'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:timestamp</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"self.build: (Hash) -&gt; Post"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span>           <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">rtc_annotate</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"Post"</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span>        <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">title</span>     <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:title</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">timestamp</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:timestamp</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Okay let&rsquo;s run it with that test JSON:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">({</span> <span style="color: #990073">id: </span><span style="color: #d14">"0f0abd00"</span><span style="background-color: #f8f8f8">,</span>
             <span style="color: #990073">title: </span><span style="color: #d14">"Cool Story"</span><span style="background-color: #f8f8f8">,</span>
             <span style="color: #990073">timestamp: </span><span style="color: #d14">"1398822693"</span> <span style="background-color: #f8f8f8">})</span>
</code></pre></div>
<p>Whoah, whoops!</p>
<div class="highlight"><pre class="highlight shell"><code>Rtc::TypeMismatchException: In method <span style="color: #008080">timestamp</span><span style="color: #000000;font-weight: bold">=</span>, annotated types are
<span style="color: #000000;font-weight: bold">[</span>Rtc::Types::ProceduralType<span style="color: #000000;font-weight: bold">(</span>10<span style="color: #000000;font-weight: bold">)</span>: <span style="color: #000000;font-weight: bold">[</span> <span style="color: #000000;font-weight: bold">(</span>Fixnum<span style="color: #000000;font-weight: bold">)</span> -&gt; Fixnum <span style="color: #000000;font-weight: bold">]]</span>, but actual
arguments are <span style="color: #000000;font-weight: bold">[</span><span style="color: #d14">"1398822693"</span><span style="color: #000000;font-weight: bold">]</span>, with argument types <span style="color: #000000;font-weight: bold">[</span>NominalType<span style="color: #000000;font-weight: bold">(</span>1<span style="color: #000000;font-weight: bold">)</span>&lt;String&gt;]
<span style="color: #000000;font-weight: bold">for </span>class Post
</code></pre></div>
<p>Ah, there ya go:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Post</span>
  <span style="background-color: #f8f8f8">rtc_annotated</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">PersistenceLogic</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@id: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:id</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@title: String'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:title</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">'@timestamp: Fixnum'</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #0086B3">attr_accessor</span> <span style="color: #990073">:timestamp</span>

  <span style="background-color: #f8f8f8">typesig</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"self.build: (Hash) -&gt; Post"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span>           <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">rtc_annotate</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"Post"</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span>        <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">title</span>     <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:title</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">timestamp</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">attrs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:timestamp</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">to_i</span>
    <span style="background-color: #f8f8f8">post</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>So then you could say:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">build</span><span style="background-color: #f8f8f8">({</span> <span style="color: #990073">id: </span><span style="color: #d14">"0f0abd00"</span><span style="background-color: #f8f8f8">,</span>
             <span style="color: #990073">title: </span><span style="color: #d14">"Cool Story"</span><span style="background-color: #f8f8f8">,</span>
             <span style="color: #990073">timestamp: </span><span style="color: #d14">"1398822693"</span> <span style="background-color: #f8f8f8">}).</span><span style="color: #990000;font-weight: bold">save</span>
</code></pre></div>
<p>And be type-checked, guaranteed, and on your way.</p>

<h4>Just a Taste</h4>

<p>The idea behind this blog post was to get Ruby developers thinking about some of the advantages of using a sophisticated type checker that could programmatically enforce the kinds of specifications that are currently leveraged by documentation and tests. Through all of the debate about how much we should be testing and what we should be testing, we have been potentially overlooking another very sophisticated set of tools which can help augment our designs and guarantee the soundness of our programs over time.</p>

<p>The Ruby Type Checker alone will not give us all of the tools that we need, but it gives us a taste of what is possible with more focused attention on types from the implementors and users of the language.</p>

<p>Works Cited</p>

<p>[1]  <a href="http://samth.github.io/gradual-typing-bib/">Gradual typing bibliography</a></p>

<p>[2] <a href="http://www.cs.umd.edu/~jfoster/papers/oops13.pdf">The ruby type checker</a> [pdf]</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Faster Rails Tests</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/faster-rails-tests/"/>
    <id>https://codeclimate.com/blog/faster-rails-tests/</id>
    <updated>2014-04-16T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Editor&rsquo;s Note: Our post today is from Peter Bell. Peter Bell is Founder and CTO of <a href="http://speakgeek.co">Speak Geek</a>, a contract member of the GitHub training team, and trains and consults regularly on everything from JavaScript and Ruby development to devOps and NoSQL data stores.</em></p>

<p>When you start a new project, automated tests are a wonderful thing. You can run your comprehensive test suite in a couple of minutes and have real confidence when refactoring, knowing that your code has really good test coverage.</p>

<p>However, as you add more tests over time, the test suite invariably slows. And as it slows, it actually becomes less valuable — not more. Sure, it&rsquo;s great to have good test coverage, but if your tests take more than about 5 minutes to run, your developers either won&rsquo;t run them often, or will waste lots of time waiting for them to complete. By the time tests hit fifteen minutes, most devs will probably just rely on a CI server to let them know if they&rsquo;ve broken the build. If your test suite exceeds half an hour, you&rsquo;re probably going to have to break out your tests into levels and run them sequentially based on risk &ndash; making it more complex to manage and maintain, and substantially increasing the time between creating and noticing bugs, hampering flow for your developers and increasing debugging costs.</p>

<p>The question then is how to speed up your test suite. There are a several ways to approach the problem. A good starting point is to give your test suite a spring clean. Reduce the number of tests by rewriting those specific to particular stories as &ldquo;user journeys&rdquo;. A complex, multi-page registration feature might be broken down into a bunch of smaller user stories while being developed, but once it&rsquo;s done you should be able to remove lots of the story-specific acceptance tests, replacing them with a handful of high level smoke tests for the entire registration flow, adding in some faster unit tests where required to keep the comprehensiveness of the test suite.</p>

<p>In general it&rsquo;s also worth looking at your acceptance tests and seeing how many of them could be tested at a lower level without having to spin up the entire app, including the user interface and the database.</p>

<p>Consider breaking out your model logic and treating your active record models as lightweight Data Access Objects. One of my original concerns when moving to Rails was the coupling of data access and model logic and it&rsquo;s nice to see a trend towards separating logic from database access. A great side effect is a huge improvement in the speed of your &ldquo;unit&rdquo; tests as, instead of being integration tests which depend on the database, they really will just test the functionality in the methods you&rsquo;re writing.</p>

<p>It&rsquo;s also worth thinking more generally about exactly what is being spun up every time you run a particular test. Do you really need to connect to an internal API or could you just stub or mock it out? Do you really need to create a complex hairball of properly configured objects to test a method or could you make your methods more functional, passing more information in explicitly rather than depending so heavily on local state? Moving to a more functional style of coding can simplify and speed up your tests while also making it easier to reason about your code and to refactor it over time.</p>

<p>Finally, it&rsquo;s also worth looking for quick wins that allow you to run the tests you have more quickly. Spin up a bigger instance on EC2 or buy a faster test box and make sure to parallelize your tests so they can leverage multiple cores on developers laptops and, if necessary, run across multiple machines for CI.</p>

<p>If you want to ensure your tests are run frequently, you&rsquo;ve got to keep them easy and fast to run. Hopefully, by using some of the practices above, you&rsquo;ll be able to keep your tests fast enough that there&rsquo;s no reason for your dev team <em>not</em> to run them regularly.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Launching Today: Automated Refactoring</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/launching-today-automated-refactoring/"/>
    <id>https://codeclimate.com/blog/launching-today-automated-refactoring/</id>
    <updated>2014-04-01T09:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Code Climate is proud to announce a revolution in how software is built. To date, we’ve been providing developers actionable insights to help write maintainable code. The feedback, while useful, still requires care and collaboration to incorporate.</p>

<p>Today, we’re significantly streamlining the development process with our new <strong>Automated, 1-Click Refactoring</strong> feature.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/automated-refactoring/magic_wand-79dd3271.gif" alt="Magic Wand" /></p>

<p>Compared to the legacy approach of refactoring by hand, Automated Refactoring provides many advantages:</p>

<ol>
<li>Saves lots of time by replacing nuanced discussion with a definitive solution</li>
<li>Appeases your CTO who has imposed an arbitrary, ill-defined requirement that all features must be “refactored” before they are shipped</li>
<li>Works when you’re too lazy to go talk to that guy who worked on that thing one time</li>
<li>Boosts your Git commit stats to get a bigger bonus at the end of the year</li>
<li>As a substitute for head desk-inducing conversations with difficult team members</li>
</ol>

<p>Here’s what David Heinemeier Hansson (DHH) had to say after testing it out:</p>

<blockquote>
<p>“When most programmers refactor, they produce shit. Code Climate’s automated refactoring tool produces code that is decidedly not shit.”</p>
</blockquote>

<p>Automated Refactoring is in public beta for all Code Climate customers, and select Open Source repos. To see it in action, navigate to a class you’ve been struggling to refactor and click the magic wand:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/automated-refactoring/auto-refactor-in-action-f3b0bc3a.jpg" alt="In Action" /></p>

<p>Automated Refactoring is free during our public beta period. Pricing is yet to be determined, but will be significant.</p>

<p><em>Editor&rsquo;s Note</em>: Automated Refactoring is no longer available. After April 1st, we determined that the feature was too revolutionary, and it was taken down. For posterity, the revolution was captured on <a href="https://www.youtube.com/watch?v=PUCy4PLNXJk">YouTube</a>.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Refactoring tests for better application design</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/refactoring-tests-for-better-application-design/"/>
    <id>https://codeclimate.com/blog/refactoring-tests-for-better-application-design/</id>
    <updated>2014-03-27T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Editor&rsquo;s Note</em>: Today we have a guest post from Marko Anastasov. Marko is a developer and cofounder of <a href="https://semaphoreapp.com/">Semaphore</a>, a continuous integration and deployment service, and one of Code Climate’s <a href="http://codeclimate.com/blog/test-coverage-and-code-quality-better-together/">CI partners</a>.</p>

<blockquote>
<p>The act of writing a unit test is more an act of design than of verification. - Bob Martin</p>
</blockquote>

<p>A still common misconception is that test-driven development (TDD) is about testing; that by adhering to TDD you can minimize the probability of going astray and forgetting to write tests by mandating that is the first thing we need to do. While I&rsquo;d pick a solution that&rsquo;s designed for mere mortals over one that assumes we are superhuman any day, the case here is a bit different. TDD is designed to make us think about our code before writing it, using automated tests as a vehicle — which is,  by the way, so much better than firing up the debugger to make sure that every code connected to a certain feature is working as expected. The goal of TDD is better software design. Tests are a byproduct.</p>

<p>Through the act of writing a test first, we ponder on the interface of the object under test, as well as of other objects that we need but that do not yet exist. We work in small, controllable increments. We do not stop the first time the test passes. We then go back to the implementation and <em>refactor</em> the code to keep it clean, confident that we can change it any way we like because we have a test suite to tell us if the code is still correct.</p>

<p>Anyone who&rsquo;s been doing this has found their code design skills challenged and sharpened. Questions like <em>agh maybe that private code shouldn&rsquo;t be private</em> or <em>is this class now doing too much</em> are constantly flying through your mind.</p>

<h3>Test-driven refactoring</h3>

<p>The red-green-refactor cycle may come to a halt when you find yourself in a situation where you don&rsquo;t know how to write a test for some piece of code, or you do, but it feels like a lot of hard work. Pain in testing often reveals a problem in code design, or simply that you&rsquo;ve come across a piece of code that was not written with the TDD approach. Some smells in test code are frequent enough to be called an anti-pattern and can identify an opportunity to refactor, both test and application code.</p>

<p>Take, for example, a complex test setup in a Rails controller spec.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">describe</span> <span style="color: #008080">VenuesController</span> <span style="color: #000000;font-weight: bold">do</span>

  <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:leaderboard</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">mock_model</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Leaderboard</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>
  <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:leaderboard_decorator</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">double</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>
  <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">mock_model</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>

  <span style="background-color: #f8f8f8">describe</span> <span style="color: #d14">"GET show"</span> <span style="color: #000000;font-weight: bold">do</span>

    <span style="background-color: #f8f8f8">before</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub_chain</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:enabled</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:find</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">venue</span> <span style="background-color: #f8f8f8">}</span>
      <span style="background-color: #f8f8f8">venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:last_leaderboard</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">leaderboard</span> <span style="background-color: #f8f8f8">}</span>
      <span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:new</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">leaderboard_decorator</span> <span style="background-color: #f8f8f8">}</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"finds venue by id and assigns it to @venue"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
      <span style="background-color: #f8f8f8">assigns</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">should</span> <span style="background-color: #f8f8f8">eql</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">venue</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"initializes @leaderboard"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
      <span style="background-color: #f8f8f8">assigns</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:leaderboard</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">should</span> <span style="color: #000000;font-weight: bold">==</span> <span style="background-color: #f8f8f8">leaderboard_decorator</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"user is logged in as patron"</span> <span style="color: #000000;font-weight: bold">do</span>

      <span style="background-color: #f8f8f8">include_context</span> <span style="color: #d14">"patron is logged in"</span>

      <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"patron is not in top 10"</span> <span style="color: #000000;font-weight: bold">do</span>

        <span style="background-color: #f8f8f8">before</span> <span style="color: #000000;font-weight: bold">do</span>
          <span style="background-color: #f8f8f8">leaderboard_decorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:include?</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">and_return</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">false</span><span style="background-color: #f8f8f8">)</span>
        <span style="color: #000000;font-weight: bold">end</span>

        <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"gets patron stats from leaderboard"</span> <span style="color: #000000;font-weight: bold">do</span>
          <span style="background-color: #f8f8f8">patron_stats</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">double</span>
          <span style="background-color: #f8f8f8">leaderboard_decorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">should_receive</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:patron_stats</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">and_return</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">patron_stats</span><span style="background-color: #f8f8f8">)</span>
          <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
          <span style="background-color: #f8f8f8">assigns</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:patron_stats</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">should</span> <span style="background-color: #f8f8f8">eql</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">patron_stats</span><span style="background-color: #f8f8f8">)</span>
        <span style="color: #000000;font-weight: bold">end</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="color: #999988;font-style: italic"># one more case omitted for brevity</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>

</code></pre></div>
<p>The controller action is technically not very long:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">VenuesController</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ApplicationController</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">show</span>
    <span style="color: #000000;font-weight: bold">begin</span>
      <span style="color: #008080">@venue</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">enabled</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">])</span>
      <span style="color: #008080">@leaderboard</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">last_leaderboard</span><span style="background-color: #f8f8f8">)</span>

      <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">logged_in?</span> <span style="background-color: #f8f8f8">and</span> <span style="background-color: #f8f8f8">is_patron?</span> <span style="background-color: #f8f8f8">and</span> <span style="color: #008080">@leaderboard</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">present?</span> <span style="background-color: #f8f8f8">and</span> <span style="background-color: #f8f8f8">not</span> <span style="color: #008080">@leaderboard</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">include?</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@current_user</span><span style="background-color: #f8f8f8">)</span>
        <span style="color: #008080">@patron_stats</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">@leaderboard</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">patron_stats</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@current_user</span><span style="background-color: #f8f8f8">)</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Notice how the extensive spec setup code basically led the developers to forget to write expectations that <code>Venue.enabled.find</code> is called, or <code>LeaderboardDecorator.new</code> is given a correct argument, for example. It is not clear if the assigned <code>@leaderboard</code> comes from the assigned venue at all.</p>

<p>Trapped in the MVC paradigm, the developers (myself included) were adding up some deep business logic in the controller, making it hard to write a good spec and thus maintain both of them. The difficulty comes from the fact that even a one-line Rails controller method does many things:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">show</span>
  <span style="color: #008080">@venue</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">])</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>That method is:</p>

<ul>
<li>extracting parameters;</li>
<li>calling an application-specific method;</li>
<li>assigning a variable to be used in the view template; and</li>
<li>rendering a response template.</li>
</ul>

<p>Adding code that reaches deep inside the database and business rules can only turn a controller method into a mess.</p>

<p>The controller above includes one <code>if</code> statement with four conditions. A full spec, then, should include 15 combinations just for this one part of code. Of course they were not written. But things could be different, if this code was outside the controller.</p>

<p>Let&rsquo;s try to imagine what a better version of the controller spec would look like, and what interfaces it would prefer to work with in order to carry its&rsquo; job of processing the incoming request and preparing a response.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">describe</span> <span style="color: #008080">VenuesController</span> <span style="color: #000000;font-weight: bold">do</span>

  <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">mock_model</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>

  <span style="background-color: #f8f8f8">describe</span> <span style="color: #d14">"GET show"</span> <span style="color: #000000;font-weight: bold">do</span>

    <span style="background-color: #f8f8f8">before</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:find_enabled</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">venue</span> <span style="background-color: #f8f8f8">}</span>
      <span style="background-color: #f8f8f8">venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:last_leaderboard</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"finds the enabled venue by given id"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">should_receive</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:find_enabled</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">with</span><span style="background-color: #f8f8f8">(</span><span style="color: #009999">1</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"assigns the found @venue"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
      <span style="background-color: #f8f8f8">assigns</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">should</span> <span style="background-color: #f8f8f8">eql</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">venue</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"decorates the venue's leaderboard"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">leaderboard</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">double</span>
      <span style="background-color: #f8f8f8">venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:last_leaderboard</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">leaderboard</span> <span style="background-color: #f8f8f8">}</span>
      <span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">should_receive</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:new</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">with</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">leaderboard</span><span style="background-color: #f8f8f8">)</span>

      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"assigns the @leaderboard"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">decorated_leaderboard</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">double</span>
      <span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">stub</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:new</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">decorated_leaderboard</span> <span style="background-color: #f8f8f8">}</span>

      <span style="background-color: #f8f8f8">get</span> <span style="color: #990073">:show</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:id</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">1</span>

      <span style="background-color: #f8f8f8">assigns</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:leaderboard</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">should</span> <span style="background-color: #f8f8f8">eql</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">decorated_leaderboard</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Where did all the other code go? We&rsquo;re simplifying the find logic by extending the model:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">describe</span> <span style="color: #008080">Venue</span> <span style="color: #000000;font-weight: bold">do</span>

  <span style="background-color: #f8f8f8">describe</span> <span style="color: #d14">".find_enabled"</span> <span style="color: #000000;font-weight: bold">do</span>

    <span style="background-color: #f8f8f8">before</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="color: #008080">@enabled_venue</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">create</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:enabled</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #000000;font-weight: bold">true</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">create</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:enabled</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #000000;font-weight: bold">true</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">create</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:venue</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:enabled</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #000000;font-weight: bold">false</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"finds within the enabled scope"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find_enabled</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@enabled_venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">should</span> <span style="background-color: #f8f8f8">eql</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@enabled_venue</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>The various <code>if</code> statements can be simplified as follows:</p>

<ul>
<li><code>if logged_in?</code> - variations on this can be decided in the view template;</li>
<li><code>if @leaderboard.present?</code> - obsolete, the view can decide what to do if it is not;</li>
<li>The rest can be moved to the decorator class under a new, more descriptive method.</li>
</ul>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">describe</span> <span style="color: #008080">LeaderboardDecorator</span> <span style="color: #000000;font-weight: bold">do</span>

  <span style="background-color: #f8f8f8">describe</span> <span style="color: #d14">"#includes_patron?"</span> <span style="color: #000000;font-weight: bold">do</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"user is not a patron"</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">}</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"user is a patron"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"user is on the list"</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">}</span>
      <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"user is NOT on the list"</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">}</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This new method will help the view decide whether or not to render <code>@leaderboard.patron_stats</code>, which we do not need to change:</p>
<div class="highlight"><pre class="highlight erb"><code># app/views/venues/show.html.erb
<span style="color: #999999;font-weight: bold">&lt;%=</span> <span style="background-color: #f8f8f8">render</span> <span style="color: #d14">"venues/show/leaderboard"</span> <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">@leaderboard</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">present?</span> <span style="color: #999999;font-weight: bold">%&gt;</span>

# app/views/venues/show/_leaderboard.html.erb
<span style="color: #999999;font-weight: bold">&lt;%</span> <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">@leaderboard</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">includes_patron?</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@current_user</span><span style="background-color: #f8f8f8">)</span> <span style="color: #999999;font-weight: bold">-%&gt;</span>
  <span style="color: #999999;font-weight: bold">&lt;%=</span> <span style="background-color: #f8f8f8">render</span> <span style="color: #d14">"venues/show/patron_stats"</span> <span style="color: #999999;font-weight: bold">%&gt;</span>
<span style="color: #999999;font-weight: bold">&lt;%</span> <span style="color: #000000;font-weight: bold">end</span> <span style="color: #999999;font-weight: bold">-%&gt;</span>
</code></pre></div>
<p>The resulting controller method is now fairly simple:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">show</span>
  <span style="color: #008080">@venue</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find_enabled</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:id</span><span style="background-color: #f8f8f8">])</span>
  <span style="color: #008080">@leaderboard</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">LeaderboardDecorator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@venue</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">last_leaderboard</span><span style="background-color: #f8f8f8">)</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>The next time we work with this code, we might be annoyed that controller needs to know what is the right argument to give to a <code>LeaderboardDecorator</code>. We could introduce a new decorator for venues that will have a method that returns a decorated leaderboard. The implementation of that step is left as an exercise for the reader. ;)</p>

<h2>EPILOGUE</h2>

<p>For further reading, check out Marko’s series about antipatterns in testing Rails applications on the <a href="https://semaphoreapp.com/blog/2014/01/14/rails-testing-antipatterns-fixtures-and-factories.html">Semaphore blog</a>.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Kickstart your next project with a Walking Skeleton</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/kickstart-your-next-project-with-a-walking-skeleton/"/>
    <id>https://codeclimate.com/blog/kickstart-your-next-project-with-a-walking-skeleton/</id>
    <updated>2014-03-20T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Editor&rsquo;s Note: Today we have a guest post from Oren Dobzinski. Oren is a code quality evangelist, actively involved in writing and educating developers about maintainable code. He blogs about how to improve code quality at <a href="http://re-factor.com">re-factor.com</a>.</em></p>

<p>It&rsquo;s the beginning of the project. You already have a rough idea of the architecture you&rsquo;re going to build and you know the requirements. If you&rsquo;re like me you&rsquo;ll want to just start coding, but you hold yourself back, knowing that you should really start with an acceptance test.</p>

<p>Unfortunately, it&rsquo;s not that simple. Your system needs to talk to a datastore or two, communicate with a couple internal services, and maybe an external service as well. Since it&rsquo;s hard to build both the infrastructure and the business logic at the same time you make a few assumptions in your test and stub out these dependencies, adding them to your TODO list.</p>

<p>A couple of weeks pass, the deadline is getting close, and you come back to your list. But while working on the integration you find out that it&rsquo;s really a pain to setup one of the datastores, and that there are a few security-related issues with the external service you need to sort out with the in-house security team. You also discover that the behavior of the external service is not what you expected. Maybe the service is slower than you anticipated, or requires multiple requests that weren&rsquo;t well-documented or just because you don&rsquo;t have a premium account. Oh, and you left the deployment scripts for the end so now you need to start cranking on that.</p>

<p>Naturally, it&rsquo;s more complicated than you originally thought. At this point you&rsquo;re deep in crunch mode and realize you might not hit the deadline because of the additional work you&rsquo;ve just discovered and the need to wait for other teams for their input.</p>

<h2>Deploy A Walking Skeleton First</h2>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/skeleton-83d0cd49.gif" alt="Walking Skeleton" /></p>

<p>In order to reduce risks on projects like the above you need to figure out all the unknowns as early as possible. The best way to do this is to have a <em>real end-to-end test</em> with no stubs against a system that&rsquo;s <em>deployed in production</em>. Enter the Walking Skeleton: a &ldquo;tiny implementation of the system that performs a small end-to-end function. It need not use the final architecture, but it should link together the main architectural components. The architecture and the functionality can then evolve in parallel.&rdquo; - <a href="http://alistair.cockburn.us/index.php/Walking_skeleton">Alistair Cockburn</a>. It is discussed extensively in the excellent <a href="http://www.growing-object-oriented-software.com/">GOOS book</a>.[1]</p>

<p>If the system needs to talk to one or more datastores then the walking skeleton should perform a simple query against each of them, as well as simple requests against any external or internal service. If it needs to output something to the screen, insert an item to a queue or create a file, you need to exercise these in the simplest possible way. As part of building it you should write your deployment and build scripts, setup the project, including its tests, and make sure all the automations are in place — such as CI integration, monitoring and exception handling. The focus is the infrastructure, not the features. Only after you have your walking skeleton should you write your first acceptance test and begin the TDD cycle.</p>

<p>This is only the skeleton of the application, but the parts are connected and the skeleton does walk in the sense that it exercises all the system&rsquo;s parts as you currently understand them. Because of this partial understanding, you must make the walking skeleton minimal. But it&rsquo;s not a prototype and not a proof of concept — it&rsquo;s production code, so you should definitely write tests as you work on it. These tests will assert things like “accepts a request”, “pushes some content to S3”, or “pushes an empty message to the queue”.</p>

<p>[1] A similar concept called &ldquo;Tracer Bullets&rdquo; was introduced in <a href="http://pragprog.com/book/tpp/the-pragmatic-programmer">The Pragmatic Programmer</a>.</p>

<h2>Start with the Riskiest Task</h2>

<p>According to Hofstadter&rsquo;s Law, &ldquo;It always takes longer than you expect, even when you take into account Hofstadter&rsquo;s Law&rdquo;. Amazingly, the law is always spot on. It makes sense then to work on the riskiest parts of the project first, which are usually the parts which have dependencies: on third party services, on in house services, on other groups in the organization you belong to. It makes sense to get the ball rolling with these groups simply because you don&rsquo;t know how long it will take and what problems should arise.</p>

<h2>Don&rsquo;t Cut Corners</h2>

<p>It&rsquo;s important to stress that until the walking skeleton is deployed to production (possibly behind a feature flag or just hidden from the outside world) you are not ready to write the first acceptance test. You want to exercise your deployment and build scripts and discover as many potential problems as you can as early as possible.</p>

<p>The Walking Skeleton is a way to validate the design and get early feedback so that it can be improved. You will be missing this feedback if you cut corners or take shortcuts.</p>

<h2>Kickstart the TDD process</h2>

<p>You can also think about it as a way to start the TDD process. It can be daunting or just too much work to build the infrastructure along with the first acceptance test. Furthermore, changes in one may require changes in the other (it&rsquo;s the “first-feature paradox” from GOOS). This is why you first work on the infrastructure and only then move on to work on the first feature.</p>

<h2>Obstacles and Tradeoffs</h2>

<p>By front-loading all infrastructure work you&rsquo;re postponing the delivery of the first feature. Some managers might feel uncomfortable when this happens, as they expect very rapid pace at the beginning of the project. You might feel some pressure to cut corners. However, their confidence should increase when you deliver the walking skeleton and they have a real, albeit minimal, system to play with. Most hard problems in software development are communication problems, and this is no exception. You should explain how the walking skeleton will reduce unexpected delays at the end of the project.</p>

<p>The walking skeleton may not save you from the recursiveness of Hofstadter&rsquo;s Law but it may make the last few days of the project a little more sane.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Five reasons object-oriented design makes sense for PHP</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/five-reasons-object-oriented-design-makes-sense-for-php/"/>
    <id>https://codeclimate.com/blog/five-reasons-object-oriented-design-makes-sense-for-php/</id>
    <updated>2014-03-13T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Editor&rsquo;s Note: Today we have a guest post from Brandon Savage, an expert in crafting maintainable PHP applications. We invited Brandon to post on the blog to share some of his wisdom around bringing object-oriented design to PHP, a language with procedural roots.</em></p>

<p>One of the most common questions that PHP developers have about object-oriented programming is, &ldquo;why should I bother?&rdquo; Unlike languages such as Python and Ruby, where every string and array is an object, PHP is very similar to its C roots, and procedural programming is possible, if not encouraged.</p>

<p>Even though an object model exists in PHP, it&rsquo;s not a requirement that developers use it. In fact, it&rsquo;s possible to build great applications (see WordPress) without object-orientation at all.</p>

<p>So why bother?</p>

<p>There are five good reasons why object-oriented PHP applications make sense, and why you should care about writing your applications in an object-oriented style.</p>

<h2>1. Objects are extensible.</h2>

<p>It should be possible to extend the behavior of objects through both composition and inheritance, allowing objects to take on new life and usefulness in new settings.</p>

<p>Of course, developers have to be careful when extending existing objects, since changing the public API of an object creates a whole new object type. But, if done well, developers can revitalize old libraries through the power of inheritance.</p>

<h2>2. Objects are replaceable.</h2>

<p>The whole point of object-oriented development is to make it easy to swap objects out for one another. The Liskov Substitution Principle tells us that one object should be replaceable with another object of the same type and that the program should still work.</p>

<p>It can be hard to see the value in removing a component and replacing it with another component, especially early on in the development lifecycle. But the truth is that things change; needs, technologies, resources. There may come a point where you&rsquo;ll need to incorporate a new technology, and having a well-designed object-oriented application will only make that easier.</p>

<h2>3. Objects are testable.</h2>

<p>It&rsquo;s possible to test procedural applications, albeit not well. Most procedural applications don&rsquo;t have an easy way to separate external components (like the file system, database, etc.) from the components under test. This means that under the best circumstances, testing a procedural application is more of an integration test than a unit test.</p>

<p>Object-oriented development makes unit testing far easier and more practical. Since you can easily mock and stub objects (see <a href="https://github.com/padraic/mockery">Mockery</a>, a great mock object library), you can replace the objects you don&rsquo;t need and test the ones you do. Since a unit test should be testing only one segment of code at a time, mock and stub objects make this possible.</p>

<h2>4. Objects are maintainable.</h2>

<p>There are a few problems with procedural code that make it more difficult to maintain. One is the likelihood of code duplication, that insidious parasite of unmaintainability. Object-oriented code, on the other hand, makes it easy for developers to put code in one place, and to create an expressive API that explains what the code is doing, even without having to know the underlying behavior.</p>

<p>Another problem that object-oriented programming solves is the fact that procedural code is often complicated. Multiple conditional statements and varying paths create code that is hard to follow. There&rsquo;s a measure of complexity — cyclomatic complexity — that shows us the number of decision points in the code. A score greater than 12 is usually considered  bad, but good object-oriented code will generally have a score under 6.</p>

<p>For example, if you know that a method accepts an object as one of its arguments, you don&rsquo;t have to know anything about how that object works to meet the requirements. You don&rsquo;t have to format that object, or manipulate the data to meet the needs of the method; instead, you can just pass the object along. You can further manipulate that object with confidence, knowing that the object will properly validate your inputs as valid or invalid, without you having to worry about it.</p>

<h2>5. Objects produce catchable (and recoverable) errors.</h2>

<p>Most procedural PHP developers are passingly familiar with throwing and catching exceptions. However, exceptions are intended to be used in object-oriented development, and they are best used as ways to recover from various error states.</p>

<p>Exceptions are catchable, meaning that they can be handled by our code. Unlike other mechanisms in PHP (like trigger_error()), we can decide how to handle an exception and determine if we can move forward (or terminate the application).</p>

<h2>The Bottom Line</h2>

<p>Object-oriented programming opens up a whole world of new possibilities for developers. From testing to extensibility, writing object-oriented PHP is superior to procedural development in almost every respect.</p>

<p><em>PHP is the next language we’ll be supporting on Code Climate. We’ll be rolling out support in phases over the next couple of months, but the sooner you join our PHP early access mailing list the sooner you&rsquo;ll be able to try it out &ndash; <a href="https://codeclimate.com/php">so reserve your spot today</a>.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Gold Master Testing</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/gold-master-testing/"/>
    <id>https://codeclimate.com/blog/gold-master-testing/</id>
    <updated>2014-02-20T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<blockquote>
<p>Eyelids closed, gold sun shines on</p>

<p>The world’s coated in the gold Krylon.</p>

<p>&ndash;Macklemore and Ryan Lewis, featuring Eighty4 Fly</p>
</blockquote>

<p>At Code Climate, we feel it&rsquo;s critical to deliver dependable and accurate static analysis results. To do so, we employ a variety of quality assurance techniques, including unit tests, acceptance tests, manual testing and incremental rollouts. They all are valuable, but we still had too much risk of introducing hard-to-detect bugs. To fill the gap, we&rsquo;ve added a new tactic to our arsenal: gold master testing.</p>

<p>Gold master testing refers to capturing the result of a process, and then comparing future runs against the saved &ldquo;gold master&rdquo; (or known good) version to discover unexpected changes. For us, that means running full Code Climate analyses of a number of open source repos, and validating every aspect of the result. We only started doing this last week, but it&rsquo;s already caught some hard-to-detect bugs that we otherwise may not have discovered until code hit production.</p>

<h2>Why gold master testing?</h2>

<p>Gold master testing is common when working with legacy code. Rather than trying to specify all of the logical paths through an untested module, you can feed it a varied set of inputs and turn the outputs into automatically verifying tests. There&rsquo;s no guarantee the outputs are correct in this case, but at least you can be sure they don&rsquo;t change (which, in some systems is even more important).</p>

<p>For us, given that we have a relatively reliable and comprehensive set of unit tests for our analysis code, the situation is a bit different. In short, we find gold master testing valuable because of three key factors:</p>

<ul>
<li>The inputs and output from our analysis is extremely detailed. There are a huge number of syntactical structures in Ruby, and we derive a ton of information from them.</li>
<li>Our analysis depends on external code that we do not control, but do want to update from time-to-time (e.g. RubyParser)</li>
<li>We are extremely sensitive to any changes in results. For example, even a tiny variance in our detection of complex methods across the 20k repositories we analyze would ripple into changes of class ratings, resulting in incorrect metrics being delivered to our customers.</li>
</ul>

<p>These add up to mean that traditional unit and acceptance testing is necessary but not sufficient. We use unit and acceptance tests to provide faster results and more localized detection of regressions, but we use our gold master suite (nicknamed Krylon) to sanity check our results against a dozen or so repositories before deploying changes.</p>

<h2>How to implement gold master testing</h2>

<p>The high level plan is pretty straightforward:</p>

<ol>
<li>Choose (or randomly generate, using a known seed) a set of inputs for your module or program.</li>
<li>Run the inputs through a known-good version of the system, persisting the output.</li>
<li>When testing a change, run the same inputs through the new version of the system and flag any output variation.</li>
<li>For each variation, have a human determine whether or not the change is expected and desirable. If it is, update the persisted gold master records.</li>
</ol>

<p>The devil is in the details, of course. In particular, if the outputs of your system are non-trivial (in our case a set of MongoDB documents spanning multiple tables), persisting them was a little tricky. We could keep them in MongoDB, of course, but that would not make them as accessible to humans (and tools like <code>diff</code> and GitHub) as a plain-test format like JSON would. So I wrote a little bit of code to dump records out as JSON:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">dir</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"krylon/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">slug</span><span style="color: #d14">}</span><span style="color: #d14">"</span>
<span style="background-color: #f8f8f8">repo_id</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Repo</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create!</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">url: </span><span style="color: #d14">"git://github.com/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">slug</span><span style="color: #d14">}</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">)</span>
<span style="background-color: #f8f8f8">run_analysis</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">repo_id</span><span style="background-color: #f8f8f8">)</span>
<span style="color: #008080">FileUtils</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">mkdir_p</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">dir</span><span style="background-color: #f8f8f8">)</span>

<span style="color: #d14">%w[smells constants etc.]</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">coll</span><span style="color: #000000;font-weight: bold">|</span>
  <span style="color: #008080">File</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">open</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">dir</span><span style="color: #d14">}</span><span style="color: #d14">/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">coll</span><span style="color: #d14">}</span><span style="color: #d14">.json"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #d14">"w"</span><span style="background-color: #f8f8f8">)</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">f</span><span style="color: #000000;font-weight: bold">|</span>
    <span style="background-color: #f8f8f8">docs</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">db</span><span style="background-color: #f8f8f8">[</span><span style="background-color: #f8f8f8">coll</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">repo_id: </span><span style="background-color: #f8f8f8">repo_id</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">map</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">doc</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">round_floats</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">doc</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">except</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">*</span><span style="background-color: #f8f8f8">ignored_fields</span><span style="background-color: #f8f8f8">))</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">sorted_docs</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">sort_by</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">&amp;</span><span style="color: #990073">:to_json</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">to_json</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">f</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">puts</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pretty_generate</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">sorted_docs</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Then there is the matter of comparing the results of a test run against the gold master. Ruby has a lot of built-in functionality that makes this relatively easy, but it took a few tries to get a harness set up properly. We ended up with something like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">dir</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"krylon/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">slug</span><span style="color: #d14">}</span><span style="color: #d14">"</span>
<span style="background-color: #f8f8f8">repo_id</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Repo</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create!</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">url: </span><span style="color: #d14">"git://github.com/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">slug</span><span style="color: #d14">}</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">)</span>
<span style="background-color: #f8f8f8">run_analysis</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">repo_id</span><span style="background-color: #f8f8f8">)</span>

<span style="color: #d14">%w[smells constants etc.]</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">coll</span><span style="color: #000000;font-weight: bold">|</span>
  <span style="background-color: #f8f8f8">actual_docs</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">db</span><span style="background-color: #f8f8f8">[</span><span style="background-color: #f8f8f8">coll</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">repo_id: </span><span style="background-color: #f8f8f8">repo_id</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">to_a</span>
  <span style="background-color: #f8f8f8">expected_docs</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">File</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">read</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">dir</span><span style="color: #d14">}</span><span style="color: #d14">/</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">coll</span><span style="color: #d14">}</span><span style="color: #d14">.json"</span><span style="background-color: #f8f8f8">))</span>

  <span style="background-color: #f8f8f8">actual_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">actual</span><span style="color: #000000;font-weight: bold">|</span>
    <span style="background-color: #f8f8f8">actual</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">actual</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_json</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">except</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">*</span><span style="background-color: #f8f8f8">ignored_fields</span><span style="background-color: #f8f8f8">)</span>

    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">index</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">expected_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">index</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">actual</span><span style="background-color: #f8f8f8">))</span>
      <span style="color: #999988;font-style: italic"># Delete the match so it can only match one time</span>
      <span style="background-color: #f8f8f8">expected_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">delete_at</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">index</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="color: #0086B3">puts</span> <span style="color: #d14">"Unable to find match:"</span>
      <span style="color: #0086B3">puts</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pretty_generate</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">actual</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_json</span><span style="background-color: #f8f8f8">))</span>
      <span style="color: #0086B3">puts</span>
      <span style="color: #0086B3">puts</span> <span style="color: #d14">"Expected:"</span>
      <span style="color: #0086B3">puts</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pretty_generate</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">expected_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_json</span><span style="background-color: #f8f8f8">))</span>
      <span style="color: #000000;font-weight: bold">raise</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">expected_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">empty?</span>
    <span style="color: #0086B3">puts</span> <span style="color: #d14">"    PASS </span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">coll</span><span style="color: #d14">}</span><span style="color: #d14"> (</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">actual_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">count</span><span style="color: #d14">}</span><span style="color: #d14"> docs)"</span>
  <span style="color: #000000;font-weight: bold">else</span>
    <span style="color: #0086B3">puts</span> <span style="color: #d14">"Expected not empty after search. Remaining:"</span>
    <span style="color: #0086B3">puts</span> <span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pretty_generate</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">expected_docs</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_json</span><span style="background-color: #f8f8f8">))</span>
    <span style="color: #000000;font-weight: bold">raise</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>All of this is invoked by a couple Rake tasks:</p>
<div class="highlight"><pre class="highlight plaintext"><code>rake krylon:save[brynary/rack-test] # Save the results to disk
rake krylon:validate[brynary/rack-test] # Validate against the gold master
</code></pre></div>
<p>Our CI system runs the <code>rake krylon:validate</code> task. If it fails, someone on the Code Climate team reviews the results, and either fixes an issue or uses <code>rake krylon:save</code> to update the gold master.</p>

<h2>Gotchas</h2>

<p>In building Krylon, we ran into a few issues. They were all pretty simple to fix, but I&rsquo;ll list them here to hopefully save someone some time:</p>

<ul>
<li>Floats &ndash; Floating point numbers can not be reliably compared using the equality operator. We took the approach of rounding them to two decimal places, and that has been working so far.</li>
<li>Timestamps &ndash; Columns like <code>created_at</code>, <code>updated_at</code> will vary every time your code runs. We just exclude them.</li>
<li>Record IDs &ndash; Same as above.</li>
<li>Non-deterministic ordering of hash keys and arrays &ndash; This took a bit more time to track down. Sometimes Code Climate would generate hashes or arrays, but the order of those data structures was undefined and variable. We had two choices: update the Krylon validation code to allow this, or make them deterministic. We went with updating the production code to be deterministic with respect to order because it was simple.</li>
</ul>

<h2>Wrapping up</h2>

<p>Gold master testing is not a substitute for unit tests and acceptance tests. However, it can be a valuable tool in your toolbox for dealing with legacy systems, as well as certain specialized cases. It&rsquo;s a fancy name, but implementing a basic system took less than a day and began yielding benefits right away. Like us, you can start with something simple and rough, and iterate it down the road.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Mob Refactoring</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/mob-refactoring/"/>
    <id>https://codeclimate.com/blog/mob-refactoring/</id>
    <updated>2014-01-30T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/mob-6ebc2633.jpg" alt="Mob refactoring" /></p>

<p>When teams try to take control of their technical debt and improve the maintainability of their codebase over time, one problem that can crop up is a lack of refactoring experience. Teams are often composed of developers with a mix of experience levels (both overall and within the application domain) and stylistic preferences, making it difficult for well-intentioned contributors to effect positive change.</p>

<p>There are a variety of techniques to help in these cases, but one I&rsquo;ve had success with is &ldquo;Mob Refactoring&rdquo;. It&rsquo;s a variant of <a href="http://mobprogramming.org/">Mob Programming</a>, which is like pair programming with more than two people (though still with one computer). This sounds crazy at first, and I certainly don&rsquo;t recommend working like this all the time, but it can be very effective for leveling up the refactoring abilities of the team and establishing shared conventions for style and structure of code.</p>

<p>Here&rsquo;s how it works:</p>

<ol>
<li>Assemble the team for an hour around a computer and a projector. It&rsquo;s a great opportunity to order food and eat lunch together, of course.</li>
<li>Bring an area of the codebase that is in need of refactoring. Have one person drive the computer, while the rest of the team navigates.</li>
<li>Attempt to refactor the code as much as possible within the hour.</li>
<li>Don’t expect to produce production-ready code during these sessions. When you’re done, throw out the changes. Do <em>not</em> try to finish the refactoring after the session &ndash; it&rsquo;s an easy way to get lost in the weeds.</li>
</ol>

<p>The idea is that the value of the exercise is in the conversations that will take place, not the resulting commits. Mob Refactoring sessions provide the opportunity for less experienced members of the team to ask questions like, &ldquo;Why do we do this like that?&rdquo;, or for more senior programmers to describe different implementation approaches that have been tried, and how they&rsquo;ve worked out in the past. The discussions will help close the experience gap and often lead to a new consensus about the preferred way of doing things.</p>

<p>Do this a few times, and rotate the area of focus and the lead each week. Start with a controller, then work on a model, or perhaps a troublesome view. Give each member of the team a chance to select the code to be refactored and drive the session. Even the least experienced member of your team can pick a good project &ndash; and they&rsquo;ll probably learn more while by working on a problem that is on the top of their mind.</p>

<p>If you have a team that wants to get better at refactoring, but experience and differing style patterns are a challenge, give Mob Refactoring a try. It requires little preparation, and only an hour of investment (although I would recommend trying it three times before judging the effect). If you give it a go, let me know how it went for you in the comments.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>How Should This Work?</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/how-should-this-work-an-object-design-epiphany/"/>
    <id>https://codeclimate.com/blog/how-should-this-work-an-object-design-epiphany/</id>
    <updated>2014-01-16T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Successful software projects are always changing. Every new requirement comes with the responsibility to determine exactly how the new or changed behaviors will be codified into the system, often in the form of objects.</p>

<p>For the longest time, when I had to change a behavior in a codebase I followed these rough steps:</p>

<ol>
<li>Locate the behavior in the application&rsquo;s code, usually inside some class (hopefully just one)</li>
<li>Determine how it needed to be adjusted in order to meet the new requirements</li>
<li>Write one or more failing tests that the class must satisfy</li>
<li>Update the class to satisfy the tests</li>
</ol>

<p>Simple, right? Eventually I realized that this simple workflow leads to messy code.</p>

<p>The temptation when changing an existing system is to implement the desired behavior within the structure of the current abstractions. Repeat this without adjustment, and you&rsquo;ll quickly end up contorting existing concepts or working around legacy behaviors. Conditionals pile up, and shotgun surgery becomes standard operating procedure.</p>

<p>One day, I had an epiphany. When making a change, rather than surveying the current landscape and asking &ldquo;How can I make this work like I need?&rdquo;, take a step back, look at each relevant abstraction and ask, &ldquo;How should this work?&rdquo;.</p>

<p>The names of the modules, classes and methods convey meaning. When you change the behavior within them in isolation, the cohesion between those names and the implementation beneath them may begin to fray.</p>

<p>If you are continually ensuring that your classes work exactly as their names imply, you&rsquo;ll often find that the change in behavior you seek is better represented by adjusting the landscape of types in your system. You may end up introducing a collaborator, or you might simply need to tweak the name of a class to align with it&rsquo;s new behavior.</p>

<p>This type of conscientiousness is difficult to apply rigorously, but like any habit it can be built up over time. Your reward will be a codebase maintainable years into the future.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>When Is It Time to Refactor?</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/when-is-it-time-to-refactor/"/>
    <id>https://codeclimate.com/blog/when-is-it-time-to-refactor/</id>
    <updated>2014-01-09T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>One struggle for software development teams is determining when it is appropriate to refactor. It is quite a quandary.</p>

<p>Refactor too early and you could over-abstract your design and slow down your team. YAGNI! You&rsquo;ll also make sub-optimal design decisions because of the limited information you have.</p>

<p>On the other hand, if you wait too long to refactor, you can end up with a big ball of mud. The refactoring may have grown to be a Herculean effort, and all the while your team has been suffering from decreased productivity as they tiptoe around challenging code.</p>

<p>So what&rsquo;s a pragmatic programmer to do? Let&rsquo;s take a look at a concrete set of guidelines that can try to answer this question. Generally, take the time to refactor now if <em>any</em> of the following are true:</p>

<ol>
<li><p><strong>Refactoring will speed up the task at hand.</strong> This is a no brainer, because you&rsquo;ll get your current work done more quickly, and the refactoring you performed will benefit your team over time. Of course, this is a judgement call, but experienced developers will hone their sense for these cases.</p></li>
<li><p><strong>The refactoring is quick and contained.</strong> Many refactorings consist of making small changes, generally within a single class. Because you&rsquo;re altering an encapsulated unit of structure, often these types of changes require no modifications to collaborators or unit tests. The most common example is applying the Extract Method refactoring in order to implement the Composed Method pattern, but other refactorings like Replace Temp with query fall into this category.</p>

<p>Katrina Owen once said:</p>

<blockquote>
<p>Small refactorings are like making a low cost investment that always pays dividends. Take advantage of that every time.</p>
</blockquote>

<p>Remember, source code is generally &ldquo;Write once, read hundreds (or thousands) of times&rdquo;. Spending a little extra time now cleaning up the internal structure of your classes makes them more approachable to every developer who opens that source code file in the future.</p></li>
<li><p><strong>The un-factored code has three strikes.</strong> Keep track (either in the back of your head or documented somewhere) of each time you run into a problem or friction that would have been avoided if your code had been better factored. When a given problem spot causes your team trouble three times, it&rsquo;s time to clean it up. This allows you to focus on the issues that are actually slowing your team down, not just the areas that seem messy.</p></li>
<li><p><strong>You&rsquo;re at risk of digging a hole that will take more than a day to fix.</strong> The worst code in every app is usually stuck in god objects that feel almost impossible to refactor, but it wasn&rsquo;t always this way.</p>

<p>A key practice to employ when considering a larger refactoring is asking yourself this question:</p>

<blockquote>
<p>&ldquo;If I pass on doing the refactoring now, how long would it take to do later?&rdquo;</p>
</blockquote>

<p>If it would take less than a day to perform later, there is less urgency to do it now. It means that if a change needs to be made later, you can be confident you won&rsquo;t be stuck in the weeds for days on end to whip the code into a workable state in order to implement the feature or bug fix.</p>

<p>Conversely, if passing on the refactoring creates a risk of digging technical debt that would take more than a day to resolve, it should probably be dealt with immediately. If you wait, that day could become two, or three or four days. The longer the time a refactoring takes, the less likely it is to ever be performed.</p>

<p>So it&rsquo;s important to limit the technical debt you carry to issues that can be resolved in short order if they need to be. Violate this guideline, and you increase the risk of having developers feel the need to spend days cleaning things up, a practice that is sure to (rightly) make your whole organization uneasy.</p></li>
</ol>
]]>
    </content>
  </entry>
  <entry>
    <title>10 High Value Development Chores to Start 2014 Right</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/ten-high-value-development-chores-to-start-2014-right/"/>
    <id>https://codeclimate.com/blog/ten-high-value-development-chores-to-start-2014-right/</id>
    <updated>2014-01-02T11:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>It&rsquo;s a new year and that makes it a great time to tackle some high value development chores that get your team started on the right foot. Each of the 10 quick development tasks below can all be done in a few hours at most, and will immediately start paying dividends on your teams productivity.</p>

<p><a id="delete-inactive-branches"></a></p>

<h2>1. Delete inactive branches and Pull Requests</h2>

<p>We&rsquo;ll start with an easy one. If your team is anything like ours, it creates branches and pull requests on a regular basis. The problem comes when they get abandoned or merged (perhaps via a rebase) and the branch and/or pull request gets left behind for all eternity. Code Climate only has three people working on it, but we have over 100 branches and a dozen open PRs across our three main repositories &ndash; almost none of those need to be looked at ever again.</p>

<p>Get all the developers in a room and go through Git branches and open pull requests in alphabetical order. Give anyone a chance to claim any branch they want around, but terminate any unclaimed branches with extreme prejudice. You&rsquo;ll be left with a lot less clutter in your repos and GitHub views.</p>

<p><em>Time required: 15 minutes as a team. If you hold a daily stand-up, do it immediately following.</em></p>

<p><a id="optimize-your-deploys"></a></p>

<h2>2. Optimize your deploys</h2>

<p>Deploys are like a mutex in your development pipeline and it pays to keep them as fast as possible. There&rsquo;s no excuse for a deploy that takes longer than 30 seconds, and in many cases you can optimize them to be significantly faster than that without too much effort. The main Code Climate Rails app can usually be deployed in less than 5 seconds.</p>

<p>Often the culprit is simply doing a lot of unnecessary work (updating dependencies with NPM or Bundler, copying large directories, or precompiling assets) on every deploy. Making better use of Git (and its ability to know exactly what is changing on each deploy) can eliminate these extra steps except when they are needed yielding big performance wins.</p>

<p>in October we <a href="http://codeclimate.com/blog/high-speed-rails-deploys-with-git/">described the upgrades we made to our Capistrano-based deployment process</a>. Give that post a read and apply the techniques to your own project. Everyone on your team will be happier &ndash; well, except for the fact that you&rsquo;ll take away one of their <a href="http://joshcheek.com/blog/3_bundle_installing">legitimate excuses for slacking off</a>.</p>

<p>(If anyone has tips for optimizing deploys to Heroku, please share them in the comments.)</p>

<p><em>Time required: Three hours.</em></p>

<p><a id="ratify-coding-style-guide"></a></p>

<h2>3. Ratify a coding style guide</h2>

<p>Your code has a style whether you define it or not, and chances are if you have more than one programmer on your team that your natural styles will differ in at least a few ways. Ideally, you wouldn&rsquo;t be able to tell the difference (at least stylistically) between code written by any of your team members.</p>

<p>Rather than waging coding style war in diffs and GitHub comments, take some time as a development team to ratify a style guide for your organization. It doesn&rsquo;t really matter what rules you choose, just that you all agree to follow them. The most important principle is:</p>

<blockquote>
<p>Proposed changes to the team&rsquo;s style guides will be litigated out-of-band.</p>
</blockquote>

<p>This helps avoid the problem of developers wasting time reformatting code every time they start working in a new file or code reviews that devolve into style nit picking sessions. After you ratify your style guide, pick a date about a month in the future to review it as a team and discuss potential changes. You could even create a GitHub repository to store it, and discuss change proposals in pull requests.</p>

<p>There’s no need to start from scratch. Feel free to crib from other widely available style guides — for example, <a href="https://github.com/airbnb/javascript">Airbnb’s JavaScript style guide</a> might be a good starting point for you. GitHub itself also publishes their <a href="https://github.com/styleguide">style guide</a>, which has sections on Ruby, JavaScript and even the voice and tone to use on the site.</p>

<p><em>Time required: One hour as a team.</em></p>

<p><a id="curate-core-test-suite"></a></p>

<h2>4. Curate a core test suite</h2>

<p>Quick: How long do you have to wait for tests to run in order to give you 95% confidence that your latest code change is safe to ship to production? If it&rsquo;s any longer than a few minutes, your team is paying a hefty tax each and every time they sit down at a keyboard.</p>

<p>Rigorously applying the principles of the <a href="http://codeclimate.com/blog/rails-testing-pyramid/">testing pyramid</a> will yield a fast test suite that still gives strong confidence the application is functioning as desired. What if your main test suite is already too slow? You&rsquo;ve got a few options:</p>

<ul>
<li>Delete slow tests that aren&rsquo;t pulling their weight. Remember, if a test&rsquo;s value drops below the investment it takes to keep around and run, it has got to go.</li>
<li>Segregate slow running tests into a separate suite. The goal is to reach 95% confidence within a few minutes of tests running. Often times teams end up with a bunch of slower tests they feel are important to get to 99% confidence, but a much smaller set of tests that cover core user flows can do a great job on their own. Running all tests every time is subject to diminishing returns.</li>
<li>Replace high level tests with lower level tests. This is an ongoing approach to improve the situation over time, and can&rsquo;t usually be done in one sitting. Still, if your suite is too slow continually keep an eye out for where a lower level (e.g. unit) test may be a better fit than an acceptance test.</li>
</ul>

<p>Remember that even a few seconds shaved off your build will save you several developer-hours over the course of the year.</p>

<p><em>Time required: Up to four hours upfront.</em></p>

<p><a id="audit-your-apps-for-vulnerabilities"></a></p>

<h2>5. Audit your app for vulnerabilities</h2>

<p>It seemed like 2013 was a particularly rough year for security on the Web, with a string of high profile breaches as startups and established companies alike. Now is a great time to take a step back and look at your code and operations to ensure you&rsquo;re taking the appropriate precautions to avoid become a victim.</p>

<p>Although common <a href="https://www.owasp.org/index.php/Top_10_2013-Top_10">Web application security risks</a> transcend development tools, the detection of vulnerabilities and appropriate remedies tends to be a framework and language specific. For Rails apps, we recommend running <a href="http://brakemanscanner.org/">Brakeman</a>, an open source vulnerability detection scanner based on static analysis, and <a href="https://github.com/rubysec/bundler-audit">bundler-audit</a>. If you&rsquo;ve never run tools like this against your code base, it&rsquo;s very likely they&rsquo;ll uncover at least one issue worth addressing, making it time well spent.</p>

<p>If you add your Rails repo to Code Climate, Code Climate’s <a href="https://codeclimate.com/tour/security">Security Monitor feature</a> will notify your team when new security vulnerabilities are introduced.</p>

<p>If you know of tools for other programming languages that are helpful, please share them in the comments.</p>

<p><em>Time required: 15 minutes to run a scan.</em></p>

<p><a id="extract-open-source-project"></a></p>

<h2>6. Extract an open source project</h2>

<p>Lots of us have a TODO on our list to extract some useful component of one of our applications and release it as an open source project. The turn of the calendar is a great time to take that opportunity.</p>

<p>Why open source code? There are lots of reasons. First, the act of extracting the code often tends to lead to cleanup and better definition of the boundaries, making the component more maintainable. Then, once the code is published, you may very well get contributions. For example, the short time since we released our <a href="https://github.com/codeclimate/ruby-test-reporter">codeclimate-test-reporter gem</a>, we&rsquo;ve already received a few valuable contributions in the form of pull requests. Those were features we had on our list, and we saved time because other generous individuals spent their time improving our code! Finally, open source is a great way to get your organization&rsquo;s name out into the community, which certainly doesn&rsquo;t hurt when it comes time to grow your team with hiring.</p>

<p>Often developers get hung up on the need for code being exemplary before they share it. While it&rsquo;s understandable that no one wants to be represented by messy code, remember that the sooner you flip the OSS bit the sooner other people can start benefiting from your work and making contributions. Plenty of the important OSS projects you use every day are messy codebases, but I bet your are happier that they are available as-is.</p>

<p>In short, <a href="http://shipitsquirrel.github.io/">obey the squirrel</a>!</p>

<p><em>Time required: Up to four hours.</em></p>

<p><a id="ditch-your-ci-server"></a></p>

<h2>7. Ditch your CI server</h2>

<p>Developers in 2014 benefit from access to a wide range of services that strive to solve a variety of pain points that we used to have to roll up our sleeves and tackle on our own. Continuous integration (CI) is one of those pains, and it can be a big one.</p>

<p>Rather than operating your own CI server (like Jenkins), consider trying out a hosted alternative. They&rsquo;ve advanced significantly over the past couple years and usually the time spent to make the switch is quickly paid back by not having to perform maintenance tasks like software updates and adding capacity on your own. Further, most of these tools have whole teams working every day to improve the continuous integration tooling. That&rsquo;s just not something most dev shops can afford to do &ndash; at least until you&rsquo;re Facebook-sized.</p>

<p>There are a lot of vendors competing in the CI space these days, but to give you some starting points, Code Climate has partnerships with <a href="https://semaphoreapp.com/">Semaphore</a>, <a href="https://www.solanolabs.com/">Solano Labs</a> and <a href="https://travis-ci.com/">Travis CI</a>.</p>

<p>Once you’re up and running, as a final step be sure to test intentionally breaking the build to ensure you are properly notified.</p>

<p><em>Time required: Two hours.</em></p>

<p><a id="clean-up-your-readmes"></a></p>

<h2>8. Clean up your READMEs</h2>

<p>Good READMEs lay a foundation for getting developers up and running with a codebase. However, unless they are actively maintained, they start to drift away from the reality of the underlying project.</p>

<p>We like to begin our READMEs with a one sentence summary of the role of the codebase. Beyond that, we may include some additional context about how the code fits into the overall architecture, but we try to keep this brief. The meat of the README is comprised of install steps and any instructions necessary to execute the code. (Hopefully the install steps are few, as we try to automate as much as possible.)</p>

<p>Take a few minutes to glance at the READMEs of your most important codebases (or write them if they don&rsquo;t exist or are empty). Most importantly, remove outdated information that could send your future teammates on a wild goose chase. No documentation is better than wrong documentation. But if you have the time while you&rsquo;re in there, sync up the content of the README with the context in your head.</p>

<p><em>Protip:</em> Whenever a new developer joins your team, have them follow the README instructions to get set up. Hopefully it should go smoothly, but should they run into any missing our outdated documentation, have them commit README updates before they move on.</p>

<p><em>Time required: 30 minutes.</em></p>

<p><a id="aggregate-and-index-your-logs"></a></p>

<h2>9. Aggregate and index your logs</h2>

<p>Here&rsquo;s one that I&rsquo;ve gone an embarrassingly long time in my development career without addressing. Searching through log files sucks. Searching through log files across three applications and eight servers leveraging all of the power of Terminal.app&rsquo;s tabs functionality sucks even more. There&rsquo;s no reason for this.</p>

<p>Today it&rsquo;s simple to get up and running with log aggregation tools, either hosted (like <a href="https://papertrailapp.com/">Papertail</a> or <a href="https://www.loggly.com/">Loggly</a>) or on-premise (with <a href="http://logstash.net/">Logstash</a> and <a href="http://www.elasticsearch.org/overview/kibana/">Kibana</a>. Both systems can be setup to accept log messages already flowing through rsyslog or, with a bit more configuration, being written to log files on disk.</p>

<p>Either way, once you&rsquo;re done, you&rsquo;ll have a single place for your developers and operations people to go to search logs for valuable clues when diagnosing issues. This is a lifesaver in emergencies. Once you&rsquo;ve got a handle on the basics, you can play around with fancier techniques like using values emitted in log files to push data into a time series database like <a href="https://metrics.librato.com/metrics">Librato Metrics</a> and archiving old logs to S3 (because storage is cheap and who knows if you&rsquo;ll need them).</p>

<p><em>Time required: Two hours.</em></p>

<p><a id="track-quality"></a></p>

<h2>10. Track the quality of your team’s code as you commit</h2>

<p>Every day we see experienced, well meaning teams struggling to achieve their code maintainability goals. A big part of the problem is that you can&rsquo;t tell whether your code is getting better or worse simply by pulling up your project in GitHub.</p>

<p>Developers these days leverage increasing visibility to tackle all sorts of thorny problems from failing tests to slow databases. <a href="https://codeclimate.com">Code Climate</a> lets you see how your code is changing from day-to-day in a way that&rsquo;s clear, timely and actionable. Derek Hopper, from Ideal Project Group, <a href="http://projectidealism.com/posts/2013/11/14/milestones">writes about</a> the impact Code Climate has had for them:</p>

<blockquote>
<p>We&rsquo;ve eliminated numerous code smells. We&rsquo;ve properly extracted business logic which transformed F classes into A classes. We have better test coverage for the important pieces of our application. The application is more stable overall.</p>
</blockquote>

<p>If you haven&rsquo;t tried it yet, we offer a <a href="https://codeclimate.com/signup/account">14-day free trial</a> and we&rsquo;d be happy to <a href="mailto:hello@codeclimate.com">talk with you</a> about how you can get off on the right foot with Code Climate in 2014.</p>

<p><em>Time required: Less than 15 minutes to get the results.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Are you experiencing technical drift?</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/are-you-experiencing-technical-drift/"/>
    <id>https://codeclimate.com/blog/are-you-experiencing-technical-drift/</id>
    <updated>2013-12-19T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>David Byrne, in the seminal Talking Heads song &ldquo;Once in a Lifetime&rdquo;, sings &ldquo;How did I get here?&rdquo; The meaning of those lyrics have been fodder for some great discussion, but I think there&rsquo;s one interpretation which has been sorely missing from that discourse — that the narrator is a software developer. The software developer, reflecting back on his work, is wondering how he accumulated so much technical debt.</p>

<blockquote>
<p>&ldquo;Letting the days go by, let the water hold me down.&rdquo;</p>
</blockquote>

<p>The water which holds him down is an obvious reference to what can happen to a software developer over time, caught under the weight of their own codebase. But what Byrne is singing about here isn&rsquo;t strictly technical debt. Technical debt is the outcome. He&rsquo;s singing about something else, about &ldquo;letting the days go by&rdquo;, about letting your codebase slip away from you.</p>

<p>Byrne, although he did not know it at the time (after all, even the phrase technical debt hadn&rsquo;t been invented yet) was singing about &ldquo;technical <em>drift</em>&rdquo;. Technical drift is a phenomenon that impacts a lot of well-meaning software development teams. It&rsquo;s a phenomenon that occurs when a development team continuously fails to recognize and adapt to change, causing the concepts in the software&rsquo;s domain and the concepts in code to start to slowly &ldquo;drift&rdquo; apart from one another, creating dissonance which ultimately leads to technical debt.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/technical-drift/technical_drift-6843d6e2.jpg" alt="Technical Drift" /></p>

<p>One of the goals of software development is to write software that most closely reflects the the domain in which we&rsquo;re working. This creates more understandable code that is easy reason and discuss, both within the tech team and with the rest of the organization. But it&rsquo;s important to remember that the domain is continually shifting. We&rsquo;re receiving new requirements based on new information.</p>

<p>If we don&rsquo;t adapt to these changes, a gap will appear between our domain and software, and the gap becomes our friend, technical debt.</p>

<p>While the signs of technical drift may be hard to spot, technical debt, the result, starts to become readily apparent.</p>

<p>In some cases, a software development team, or a team leader, recognizing that the gap has become too large, comes together and decides &ldquo;enough is enough&rdquo;. What is needed is Design —<em>Big Design</em>. The team stops feature development, buckles down, and refactors their code and architecture to more cleanly map to their domain.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/technical-drift/big_design-e03f670c.jpg" alt="Big Design" /></p>

<p>The problem with Big Design is that it&rsquo;s a &ldquo;stop the world&rdquo; operation. Feature development stops, and an anxious queue begins to build up waiting for the development team to free up. Furthermore, it grants false hope that such a thing might not be necessary again, but if the pattern continues, it often becomes inevitable.</p>

<h2>How do we prevent technical drift?</h2>

<p>If you&rsquo;re not taking an active role in refactoring your application every week chances are you&rsquo;re experiencing &ldquo;technical drift&rdquo;. Having a problem space that is continually changing necessitates continuous reworking of how your application is designed — what Agile practitioners call &ldquo;iterative design&rdquo;. When you&rsquo;re able to do this effectively, you can round off the peaks and avoid some of the pitfalls of Big Design.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/technical-drift/iterative_design-97624dc8.jpg" alt="Iterative Design" /></p>

<p>Note that the &ldquo;Code&rdquo; and &ldquo;Domain&rdquo; lines never intersect. We must accept that we do not yet have enough information to make some kinds of design decisions. But we can get close.</p>

<p>Understanding technical drift is more of a mindset than a particular practice, but it can help put into context why it&rsquo;s important to remain vigilant, to call attention to code and domain mismatches, and to advocate for accurate and precise names wherever possible. Gaps which you&rsquo;re creating may be well understood today, but as your team changes, and time progresses, that understandability suffers. Make the investment now, double down and pay attention.</p>

<p>Years later you don&rsquo;t want to look back in horror on your code and say to yourself &ldquo;my god, what have I done&rdquo;.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Roots of Static Analysis</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/the-roots-of-static-analysis/"/>
    <id>https://codeclimate.com/blog/the-roots-of-static-analysis/</id>
    <updated>2013-12-12T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>The Code Climate team relies on many Open Source tools to help our application give the best feedback to our customers. These tools often depend on ideas with fascinating histories, and investigating these histories can teach us how to use these tools properly. In this post we’d like to focus on the origins of one of the main features of Code Climate - measuring code complexity. We’ll look at the original paper that introduced the idea, and discuss how we discovered that understanding the role of intuition in quantifying code complexity is crucial to correctly interpreting complexity measurements.</p>

<p>While Code Climate doesn’t use this exact measurement, the history of quantifying the complexity of a computer program can be traced to an algorithm known as “cyclomatic complexity.” This concept was introduced in “A Complexity Measure,” a 1976 paper by Thomas J. McCabe, a United States Department of Defense employee who was involved in many large scale programming and programming management efforts during his career. As is the case with most enduring concepts in computer science and software engineering, the problems that motivated McCabe’s original work are still relevant today. The text of the paper begins:</p>

<blockquote>
<p>“There is a critical question facing software engineering today: How to modularize a software system so the resulting modules are both testable and maintainable?”</p>
</blockquote>

<p>While we have more ideas about modularity, testability, and maintainability than we did in 1976, this is still at the heart of what makes programming complex and challenging for modern programmers, product managers, stakeholders, and more. In order to answer this critical question, McCable makes the claim that:</p>

<blockquote>
<p>“What is needed is a mathematical technique that will provide a quantitative basis for modularization and allow us to identify software modules that will be difficult to test or maintain.”</p>
</blockquote>

<p>Charged with the task of how to identify complex programs in order to reduce testing time and maintenance costs, McCabe takes a page from his experience with <a href="http://en.wikipedia.org/wiki/Graph_theory">graph theory</a> and provides a framework for determining the complexity of a computer program based on the idea of <em>graph theoretic complexity.</em></p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/mccabe-2369ce3b.png" alt="An Image From McCabe's Paper, The Structure of a Program" /></p>

<p>The details of the algorithm aren’t terribly important, but the basic idea is that the connectedness of a graph relates to its complexity, and that the notion of complexity is independent of size. Here’s the author’s description of the strategy:</p>

<blockquote>
<p>“The overall strategy will be to measure the complexity of a program by computing the number of linearly independent paths, control the &ldquo;size&rdquo; of programs by setting an upper limit to these paths (instead of using just physical size), and use the cyclomatic complexity as the basis for a testing methodology.”</p>
</blockquote>

<p>When McCabe speaks of “linearly independent paths,” he is essentially referring to possible paths of execution that running a given piece of code can generate. In modern terms, this means that conditional statements and assignments will lead to higher cyclomatic complexity scores, and that limiting possible paths within methods will leader to lower scores. Let’s take a look at some JavaScript code that will illustrate this principle:</p>
<div class="highlight"><pre class="highlight javascript"><code><span style="color: #999988;font-style: italic">// Example 1</span>
<span style="color: #000000;font-weight: bold">function</span> <span style="background-color: #f8f8f8">myFunction</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">param</span><span style="background-color: #f8f8f8">){</span>
  <span style="color: #000000;font-weight: bold">var</span> <span style="background-color: #f8f8f8">flags</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">[];</span>
  <span style="color: #000000;font-weight: bold">if</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">param</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #009999">0</span><span style="background-color: #f8f8f8">){</span>
    <span style="background-color: #f8f8f8">flags</span><span style="background-color: #f8f8f8">.</span><span style="background-color: #f8f8f8">push</span><span style="background-color: #f8f8f8">(</span><span style="color: #009999">0</span><span style="background-color: #f8f8f8">);</span>
  <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">if</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">param</span> <span style="color: #000000;font-weight: bold">&gt;</span> <span style="color: #009999">0</span><span style="background-color: #f8f8f8">){</span>
    <span style="background-color: #f8f8f8">flags</span><span style="background-color: #f8f8f8">.</span><span style="background-color: #f8f8f8">push</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">param</span><span style="background-color: #f8f8f8">);</span>
  <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">return</span> <span style="background-color: #f8f8f8">flags</span><span style="background-color: #f8f8f8">;</span>
<span style="background-color: #f8f8f8">}</span>

<span style="color: #999988;font-style: italic">// Example 2 - simplified</span>
<span style="color: #000000;font-weight: bold">function</span> <span style="background-color: #f8f8f8">myFunction</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">param</span><span style="background-color: #f8f8f8">){</span>
  <span style="color: #000000;font-weight: bold">return</span> <span style="background-color: #f8f8f8">[</span><span style="background-color: #f8f8f8">param</span><span style="background-color: #f8f8f8">];</span>
<span style="background-color: #f8f8f8">}</span>
</code></pre></div>
<p>In the first function we can see that there are unnecessary conditional statements that cloud the intent of the (admittedly trivial) function. By removing these if statements and compacting the function to its essentials, we intuitively have a less complex function. By that token, the cyclomatic complexity score would be lower.</p>

<p>While the concept of applying graph theory to the structure of computer programs is novel and would have alone made this paper a landmark, the true measure of its genius lies in the desire of the author to “illustrate the correlation between intuitive complexity and graph-theoretic complexity.” In other words, the author was aware that the intuition of a programmer with respect to their notion of complexity is a powerful one that is worth preserving, and <strong>instead of seeking an algorithm that programmers could lean on, he sought one that would confirm what they already believed.</strong></p>

<p>Modern static analysis tools deal with a larger volume of code than McCabe probably ever imagined possible, and so their goals have to be somewhat aligned with modern practice. Tools like Code Climate that analyze entire code bases are going to be more powerful in the historical view than in the moment - there is simply too much information to consume to be able to review a quality report every time new code is pushed to a repository. Instead, the onus is on modern tools to provide a glimpse into how things are changing.Essentially, for a tool to be applicable, it must be trustworthy, and to be trustworthy, it must conform to the underlying assumptions that engineers have about the material that they work with: code.</p>

<p>For Code Climate and other code quality tools to measure their success, they should look to see if they are, for the most part, conforming to the intuition of developers. Where they’re not doing so, they should be opening interesting conversations that help programmers get to the heart of the designs they are implementing. Can you think of examples when static analysis has confirmed or contradicted your intuition? Leave us some examples in the comments below and we’ll share them.</p>

<p>Stay tuned for the next post in which we’ll explore some of the visualizations McCabe used to express code complexity, and look at some real world code examples to see how lowering cyclomatic complexity can make code intuitively less complex.</p>

<p><strong>Works Cited</strong>
McCabe, T.J. <em>A Complexity Measure</em> IEEE Transactions on Software Engineering, Vol. SE-2 No.4, December 1976. Department of Defense, National Security Agency.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Refactoring Without Good Tests</title>
    <author>
      <name>Code Climate</name>
      <uri>https://twitter.com/codeclimate</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/refactoring-without-good-tests/"/>
    <id>https://codeclimate.com/blog/refactoring-without-good-tests/</id>
    <updated>2013-12-05T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>We often have to work on code that doesn&rsquo;t have good test coverage. This creates a number of problems. The first problem is that if you don&rsquo;t have good test coverage, it&rsquo;s hard to know whether your code changes will break other parts of the application, so you need to have a strategy for handling regressions.</p>

<p>The second problem is even more troublesome. Generally, code that doesn&rsquo;t have good test coverage is also badly designed. One of the big benefits of test driving your code is that it moves you towards a range of good practices. Most of the time, when you test drive code you&rsquo;ll write your code &ldquo;outside in&rdquo; - focusing on the interface that the test needs to validate before thinking about the implementation you&rsquo;ll need to deliver. It also makes it more likely that you&rsquo;ll create classes with a narrow responsibilities that are loosely coupled, as the excessive setup required for testing tightly coupled code will quickly move you towards reducing your coupling. So if you&rsquo;re working with code that doesn&rsquo;t have good test coverage, most of the time it will be harder to write tests for and more tightly coupled than test driven code.</p>

<p>Finally, because of the the first two issues, the chances are that when changes have been made to the project in the past, developers will have made the smallest possible changes consistent with getting their new feature working rather than refactoring and cleaning up the code every time they touched it. Because of this it&rsquo;s likely to have a high degree of technical debt, making it even harder to work with.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/slop_feedback_loop-2906b76e.jpg" alt="Sloppy Code &gt; Bad Design &gt; Low Test Coverage &gt; Fear of Refactoring" /></p>

<h2>Moving forward step-by-step</h2>

<p>When confronted with code that doesn&rsquo;t have good test coverage, it&rsquo;s important not to try to &ldquo;boil the ocean&rdquo; with unit tests. It never makes sense to take a couple of weeks (or months) to try to get the code coverage up across the entire app. So, what is the answer? When you need to work with a <a href="http://www.laputan.org/mud/">big ball of mud</a>, where should you start?</p>

<p>A good starting point is to take some time with the product owner/business analyst/business stakeholder to really clarify the key user journeys. Ask, “what are the most important things that your key audiences need to be able to do through the app?” Then create a handful of concrete scenarios for each user journey and write automated acceptance tests for them. For a web app you&rsquo;d probably use a tool like Cucumber, RSpec and Capybara or Selenium to create these &ldquo;smoke tests&rdquo;. They don&rsquo;t guarantee that your app is working correctly, but they should catch most of the large, systematic problems.</p>

<p>Next, test drive all of new code. That way you have confidence in the new functionality that you are adding to the system. If necessary, you might need to write a thin <a href="http://c2.com/cgi/wiki?AnticorruptionLayer">anti-corruption layer</a> to provide a clean interface to code against for integration level testing.</p>

<p>Finally, whenever you find a bug, start by writing a failing test at an appropriate level (ideally a unit test). Then confirm that once the bug is fixed, the test passes.</p>

<p>If you&rsquo;re working with a team that is not used to test driving code, take the time to make sure that they&rsquo;re able to run the test suite locally and pair with them to get them used to test driving new functionality. Also make sure to set up continuous integration to your version control system so you&rsquo;ll quickly get notified if any of the tests break.</p>

<p>Working with legacy code with limited test coverage is hard, but by following the ideas above it should be easier to get to grips with the code base. And over time, you&rsquo;ll notice that the test coverage in the areas you care about - where you make most of your changes - will start to become reasonable. Usually within 6-12 months you end up with pretty good coverage in the parts of the app that really matter.</p>

<p><em>Peter Bell is Founder and CTO of <a href="http://speakgeek.co">Speak Geek</a>, a contract member of the GitHub training team, and trains and consults regularly on everything from JavaScript and Ruby development to devOps and NoSQL data stores.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Code Climate Now Supports Pull Requests and Branch Comparisons</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-climate-for-pull-requests/"/>
    <id>https://codeclimate.com/blog/code-climate-for-pull-requests/</id>
    <updated>2013-11-06T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Today we’re proud to announce that we’re bringing Code Climate more in line with how many of you work — <strong>you can now see how each change affects the quality and security of your code before it’s merged into master</strong>. You no longer have to wait until a security vulnerability is in master before eradicating it from your code base. If you use feature branches, you can ensure the quality is up to your team’s standards before merging. When reviewing a refactoring, you can easily visualize the impact to the codebase on a single page.</p>

<p><strong>In short, you can merge with confidence.</strong> <a href="https://codeclimate.com/signup/account">Create a Code Climate account start getting analysis of your Pull Requests right now.</a></p>

<p>There are three new, key features that work together to make this possible:</p>

<ul>
<li>GitHub Pull Request integration</li>
<li>Compare view</li>
<li>Branch analysis</li>
</ul>

<p>Let’s look at each of them.</p>

<h2>GitHub Pull Request integration</h2>

<p>We’re happy to announce that <strong>Code Climate will automatically analyze your GitHub Pull Requests</strong>. Simply open a Pull Request and Code Climate will inform GitHub when our analysis is ready for you (if you’ve used or seen Travis CI’s build status on GitHub, we use the same exact mechanism):</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/pull-requests/animated_pull_requests-eb22343b.gif" alt="Pull Request Support" /></p>

<p>Branch testing and Pull Request support is included in all our <a href="https://codeclimate.com/pricing">currently offered plans</a> at the Team level and above. We’ll be rolling this feature out to incrementally over the next few days, and we will let you know when it&rsquo;s activated for your account.</p>

<p><em>Note:</em> Due to some technical considerations around analyzing cross-repo PRs, supporting Pull Requests for our free-for-OSS repos will take some extra time but is high on our list.</p>

<h2>Compare view</h2>

<p>Once we&rsquo;ve finished analyzing your pull request/branch, you&rsquo;ll be able to see the results in our new Compare view. It’s a focused representation of the important changes in your branch. You’ll see the overall change to your repo’s GPA, how your classes or files grades have changed and where code smells have been fixed, introduced or gotten worse:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/pull-requests/compare_branches-0bb33636.gif" alt="New Compare View" /></p>

<h2>Branch analysis</h2>

<p>Even if you don’t use GitHub Pull Requests, you can start getting feedback on your branches immediately. Start by clicking on the new “Branches” tab for each of your repositories:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/pull-requests/branches_list-d0946fbd.png" alt="Code Climate for Branches" /></p>

<p>Push the “Analyze” button for any branches you care about, briefly sit tight, and within a few minutes the “View Comparison” button will be available to send you to a Compare view.</p>

<p>First-class Pull Request support has been our most requested feature over the last year, and we&rsquo;re thrilled to be delivering it to you. We’ve been using these new features while we’ve been building them (I know, very meta) and we’re really enjoying the quicker feedback loop.</p>

<p>We hope you enjoy it as much as we have. We&rsquo;d love to hear what you think!</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Launched: Code Climate for&amp;nbsp;JavaScript</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-climate-for-javascript/"/>
    <id>https://codeclimate.com/blog/code-climate-for-javascript/</id>
    <updated>2013-10-24T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Today we’re thrilled to announce that Code Climate is taking a giant step forward and <strong>launching support for JavaScript</strong>. Writing maintainable, bug-free JavaScript presents all of the challenges (and then some) of writing high quality Ruby, and now you can take advantage of Code Climate’s automated code reviews for your client-side JS and Node.js projects.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/javascript/js_code_detail-2bd2f604.png" alt="Code Climate for JavaScript" /></p>

<p>Code Climate launched out of the Ruby community, with the goal of helping developers ship quality code faster, regardless of the language they are using. With advances to client-side programming (Ember.js, Backbone, etc.) and the fast growth of Node.js on the server-side, now more than ever JavaScript is used to express critical business logic. That code needs to be free from defects, and it needs to be maintainable over the long term. As a first class language in a developer’s modern toolkit, JavaScript should have the tooling to match.</p>

<p><strong><a href="https://codeclimate.com/signup/account">Create a Code Climate account and add your first JavaScript project today.</a></strong></p>

<h2>What does it do?</h2>

<p>JavaScript projects on Code Climate benefit from the extensive work we’ve done over the past few years to make a tool that provides the most actionable, timely feedback on code changes including:</p>

<ul>
<li>Simple A-F letter ratings for every JavaScript file</li>
<li>An overall project GPA to track code improvements over time</li>
<li>Email, chat integration and activity feeds for timely notifications</li>
<li>Integration with issue trackers like GitHub Issues and Pivotal Tracker</li>
</ul>

<p>In addition, because code linting is often important to ensure consistent, predictable execution of JavaScript across browsers, we’ve built in configurable <a href="http://www.jshint.com/">JSHint</a> checks. Here’s an example from Node.js:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/javascript/js_lint_warnings-cb5682fe.png" alt="Code Climate for Node.js" /></p>

<p><em>(JSHint is configured by checking in a <code>.jshintrc</code> file into your repository. If you already have one, we’ll use it automatically.)</em></p>

<h2>How do I use it?</h2>

<p>To add private projects to Code Climate, you’ll first need to <a href="https://codeclimate.com/signup/account">create an account</a>. As of today, new repositories added to your Code Climate dashboard will have a dropdown menu to choose which language you would like us to analyze:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/javascript/add_js_repo-7820b083.png" alt="Adding a JavaScript repo to Code Climate" /></p>

<p><em>Note:</em> Right now we are able to support one language per repository, but this is something that we will be improving in the future. As many Rails projects leverage JavaScript extensively, we want you to be able to see the effects of <em>all</em> of the changes to your codebase on each commit, and we are working to make that easier.</p>

<p>As always, Code Climate is free for open-source projects on GitHub. <a href="https://codeclimate.com/github/signup">Add your OSS JavaScript projects today.</a></p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Unexpected Outcomes Of Code&amp;nbsp;Review</title>
    <author>
      <name>Michael Bernstein</name>
      <uri>https://twitter.com/mrb_bk</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/unexpected-outcomes-of-code-reviews/"/>
    <id>https://codeclimate.com/blog/unexpected-outcomes-of-code-reviews/</id>
    <updated>2013-10-16T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>As modern software developers we have many tools at our disposal to help us feel confident that the code we produce is high-quality and defect free. Among the most valuable of these are tools that aid in inspecting source code written by another developer, or what we commonly call <em>code review</em>.</p>

<p>Often developers think the main reason for code review is to find bugs, but a 2013 study produced by by Alberto Bacchelli and Christian Bird of Microsoft Research concluded that other outcomes are more prevalent – and possibly more valuable!</p>

<p>Bacchelli and Bird surveyed 165 managers and 873 programmers at Microsoft, interviewed 17 developers with various degrees of experience and seniority across 16 separate product teams, and manually reviewed the content of 570 comments from Microsoft CodeFlow,  an internal interactive tool that creates a central location where the discussion of code and the subsequent fixes can be discussed either in real-time or asynchronously.</p>

<p>What they found was that while the top motivation of developers, managers, and testers in performing code review is to find bugs, the outcome of most reviews is quite different.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/code-review/motivation-c99ace5a.png" alt="Code review motivations" /></p>

<p><strong>The &lsquo;Motivations&rsquo; chart: the ranked motivation categories from the developer segment of the interviews.</strong></p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/code-review/outcomes-eea59880.png" alt="Code review outcomes" /></p>

<p><strong>The &#39;Outcomes&rsquo;: Ranked categories extracted from a sampling of code review data.</strong></p>

<p>As can be seen from these charts of Motivations and Outcomes, the top motivation for the largest number of developers was &ldquo;Finding defects,&rdquo; yet the topic most commonly discussed in code reviews ostensibly pertains to &ldquo;code improvements:” comments  or changes about code in terms of readability, commenting, consistency, dead code removal, etc.</p>

<p>So if code review isn’t giving us what we want, why do we keep doing it? The response of one senior developer in the study sums it up well:</p>

<blockquote>
<p>“[code review] also has several beneficial influences: (1) makes people less protective about their code, (2) gives another person insight into the code, so there is (3) better sharing of information across the team, (4) helps support coding conventions on the team, and&hellip;(5) helps improve the overall process and quality of code.”</p>
</blockquote>

<p>Bacchelli and Bird conclude that, while there’s a significant difference between the expectations and outcomes of code review, this isn’t a bad thing. While we don’t always get the exact value from code reviews that we expected, we often end up getting quite a bit more.</p>

<blockquote>
<p>Turns out the Stones were right: You can’t always get what you want, but you just might find you get what you need.</p>
</blockquote>

<p>In addition to a modicum of somewhat superficial bug fixes, teams get benefits such as “knowledge transfer, increased team awareness, and improved solutions to problems&rdquo; from participating in modern code reviews. Additionally, the idea that code review is good at &ldquo;educating new developers about code writing” is a compelling point.</p>

<p>Bacchelli and Bird recommend embracing these unexpected outcomes, rather than trying to re-focus code reviews on finding bugs, and let code review policies be guided with the explicit intent to improve code style, find alternative solutions, increase learning, and share ownership.</p>

<p>They also recommend automating enforcement of team style and code conventions to free reviewers to look for deeper more subtle defects - something we agree with wholeheartedly!</p>

<p><em>All quotes and figures are from Alberto Bacchelli and Christian Bird, <a href="http://research.microsoft.com/apps/pubs/default.aspx?id=180283">&quot;Expectations, Outcomes, and Challenges of Modern Code Review&rdquo;</a>, May 2013, Proceedings of the International Conference on Software Engineering.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>The Rails Testing Pyramid</title>
    <author>
      <name>Code Climate</name>
      <uri>https://twitter.com/codeclimate</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/rails-testing-pyramid/"/>
    <id>https://codeclimate.com/blog/rails-testing-pyramid/</id>
    <updated>2013-10-09T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Are your tests running slower than you&rsquo;d like? Or perhaps your tests are brittle, making it harder to refactor and make substantial changes to your application functionality? Both are common complaints for large Rails apps that have been around for years, but good testing practices shouldn’t create these problems over the long term.</p>

<p>The testing pyramid is a concept that can help you better balance your tests, speeding up your test suite and reducing the cost of changing the functionality of your applications. It centers on the composition of different types of tests in your suite.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/rails-testing-pyramid-93e6ae0d.png" alt="Rails Testing Pyramid" /></p>

<p>You&rsquo;re probably already familiar with the two most common types of Rails tests in the wild:</p>

<ul>
<li>** Unit tests** — The lowest and most important level. Unit tests use tools like RSpec, MiniTest or Jasmine that confirm the correct behavior of isolated units of functionality (typically classes, methods or functions), and run extremely fast (milliseconds).

<ul>
<li><strong>Acceptance tests</strong> — The high level (typically user-level) tests using tools like RSpec and Capybara, Cucumber or Selenium. Since they run a lot more code than unit tests and often depend on external services they are much slower (seconds or minutes).</li>
</ul></li>
</ul>

<p>A properly tested application feature requires <em>both</em> unit tests and acceptance tests. Start by making sure you have good unit test coverage. This is a natural by-product of a test-driven development (TDD) workflow. Your unit tests should catch edge cases and confirm correct object behavior.</p>

<p>Carefully supplement your unit tests with acceptance tests that exercise the application like an end-user. These will give you confidence that all of the objects are playing nicely together. Teams often end up with way too many of these tests, slowing development cycles to a crawl. If you have 20 Capybara-based tests for user registration to confirm that all validation errors are handled correctly, you&rsquo;re testing at the wrong level. This is known as the <em>Inverted Testing Pyramid</em> anti-pattern.</p>

<h2>The Throwaway Test</h2>

<p>It&rsquo;s important to realize that — just like scaffolding — a test can be useful without being permanent. Imagine that you&rsquo;re going to spend two weeks building a complex registration system, but you&rsquo;re slicing it into half day stories each of which has a couple of Cucumber tests to verify behavior. This can be a good way to develop, as you&rsquo;ve got a large number of thinly-sliced stories and are ensuring that you have clear &ldquo;confirmation&rdquo; that each story is complete in the form of passing acceptance tests. Just don’t forget the final step: When you’re done, pare your test suite down to the <em>minimum</em> set of tests to provide the confidence you need (which may vary depending on the feature).</p>

<p>Once you&rsquo;re done with such a minimum marketable feature, instead of just shipping with the 40-50 acceptance tests you used while building out the stories, you should replace those with maybe 3-5 <em>user journeys</em> covering the major flows through the registration system. It&rsquo;s OK to throw away the other tests, but make sure that you&rsquo;re still ensuring correctness of the key behaviors — often by adding more unit tests. If you don&rsquo;t do this, you&rsquo;ll quickly end up with a test suite that requires substantial parallelization just to run in 5-8 minutes and that is brittle with small UI changes breaking large numbers of tests.</p>

<h2>Service-Level Testing</h2>

<p>Eventually, you&rsquo;ll notice that there is sometimes functionality that you can&rsquo;t confidently test at a unit level but that shouldn&rsquo;t really be tested via the UI. In his 2009 book, &ldquo;Succeeding with Agile&rdquo;, Mike Cohn (who came up with the concept of &ldquo;the testing pyramid&rdquo; which was later popularized by Martin Fowler) used the phrase &ldquo;service-level testing&rdquo; to describe these tests. Various communities also use terms like functional or integration tests which also describe tests between unit and end-to-end acceptance tests.</p>

<p>The trick with service level testing is to expose an API for your application or subsystem so that you can test the API independently of the UI that will exercise it. This ties in nicely with trends in web application development where many teams are now trending towards building a single RESTful JSON API on the server side to service both web and native mobile clients.</p>

<h2>Putting It All together</h2>

<p>Most applications only have a small number of critical user paths. For an eCommerce application, they might be:</p>

<ol>
<li>Browsing the product catalog</li>
<li>Buying a product</li>
<li>Creating an account</li>
<li>Logging in (including password reset)</li>
<li>Checking order history</li>
</ol>

<p>As long as those five things are working, the developers don’t need to be woken up in the middle of the night to fix the application code. (Ops is another story.) Those functions can likely be covered with five coarse-grained, Capybara tests that run in under two minutes total.</p>

<p>Blending unit tests, service-level tests and acceptance tests yields faster test suites that still provide confidence the application is working, and are resistant to incidental breakage. As you develop, take care to prune tests that are not pulling their weight. When you fix a bug, implement your regression test at the lowest possible level. Over time, keep an eye on the ratio between the counts of each type of test, as well as the time of your acceptance test suite.</p>

<p>Using these techniques, you can achieve testing nirvana: A suite that provides you confidence the application works, gives you freedom to change the application without brittle, UI-related test failures, and runs in a few minutes without any parallelization.</p>

<p><em>Peter Bell is Founder and CTO of <a href="http://speakgeek.co">Speak Geek</a>, a contract member of the GitHub training team, and trains and consults regularly on everything from JavaScript and Ruby development to devOps and NoSQL data stores.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>High-Speed Rails Deploys With Git</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/high-speed-rails-deploys-with-git/"/>
    <id>https://codeclimate.com/blog/high-speed-rails-deploys-with-git/</id>
    <updated>2013-10-02T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>TL;DR — <strong>We reduced deploy times from ten minutes to less than five seconds by replacing the standard Capistrano deploy tasks with a simpler, Git-based workflow and avoiding slow, unnecessary work.</strong></p>

<p>At Code Climate, we try to minimize the time between when code is written and when it is live in production. When deploys slowed until they left enough time to make a pot of coffee, we invested in speeding them up.</p>

<h2>What’s in a deploy?</h2>

<p>At its core, deploying a modern Rails application consists of a few simple steps:</p>

<ol>
<li>Update the application code</li>
<li>Run <code>bundle install</code> (if the Gemfile was updated)</li>
<li>Precompile assets (if assets were updated)</li>
<li>Restart the application processes (e.g. Unicorn)</li>
</ol>

<p>If the deploy fails, the developer needs to be alerted immediately. If application processes fail to rollover to the latest code, we need to detect that.</p>

<p>For kicks, I wrote a Bash script to perform those steps, to determine our theoretical lowest deploy time (just the time for SSH and running the minimum, required commands). It took about three seconds when there were no <code>Gemfile</code> or asset changes.  So I set out to reduce our ten minute deploys to as close to that number as possible.</p>

<h2>Enter Capistrano</h2>

<p>If you take anything away from this article, make it this: Capistrano is really two tools in one. It provides both:</p>

<ol>
<li>A runtime allowing you to run arbitrary commands against sets of remote servers via SSH</li>
<li>A set of default tasks for deploying Rails applications</li>
</ol>

<p>The runtime is incredibly useful. The default tasks, which originated back  <a href="http://weblog.jamisbuck.org/2005/8/5/introducing-switchtower">in 2005</a>, come from a pre-Git era and are unnecessarily slow and complex for most Rails applications today.</p>

<p>By default, Capistrano creates a <code>releases</code> directory to store each deployed version of the code, and implicitly serve as a deployment history for rollback. The <code>current</code> symlink points to the active version of the code. For files that need to be shared across deployments (e.g. logs and PID files), Capistrano creates symlinks into the <code>shared</code> directory.</p>

<h2>Git for faster, simpler deploys</h2>

<p>We avoid the complexity of the <code>releases</code>, <code>current</code> and <code>shared</code> directories, and the slowness of copying our application code on every deploy by using Git. To begin, we clone our Git repo into what will become our <code>deploy_to</code> directory (in Capistrano speak):</p>

<p><code>git clone ssh://github.com/codeclimate/codeclimate.git /data/codeclimate/app</code></p>

<p>To update the code, a simple<code>git fetch</code> followed by <code>git reset —hard</code> will suffice. Local Git tags (on the app servers) work beautifully for tracking the deployment history that the <code>releases</code> directory did. Because the same checkout is used across deployments, there’s no need for <code>shared</code> symlinks. As a bonus, we use Git history to detect whether post-update work like bundling Gems needs to be done (more on that later).</p>

<h2>The Results</h2>

<p>Our new deploy process is heavily inspired by (read: stolen from) <a href="https://github.com/freerange/recap">Recap</a>, a fantastic set of modern Capistrano tasks intended to replace the defaults. We would have used Recap directly, but it only works on Ubuntu right now.</p>

<p>In the end we extracted a small set of Capistrano tasks that work together to give us the simple, extremely fast deploys:</p>

<ul>
<li><code>deploy:update_code</code> — Resets the Git working directory to the latest code we want to deploy.</li>
<li><code>bundle:install:if_changed</code> — Checks if either the <code>Gemfile</code> or <code>Gemfile.lock</code> were changed, and if so invokes the <code>bundle:install</code> task. Most deploys don’t include <code>Gemfile</code> changes so this saves some time.</li>
<li><code>assets:precompile:if_changed</code> — Similar to the above, this invokes the <code>assets:precompile</code> task if and only if there were changes that may necessitate asset updates. We look for changes to three paths: <code>app/assets</code>, <code>Gemfile.lock</code>, and <code>config</code>. Asset pre-compilation is notoriously slow, and this saves us a lot of time when pushing out changes that only touch Ruby code or configuration.</li>
<li><code>deploy:tag</code> — Creates a Git tag on the app server for the release. We never push these tags upstream to GitHub.</li>
<li><code>deploy:restart</code> — This part varies depending on your application server of choice. For us, we use God to send a <code>USR2</code> signal to our Unicorn master process.</li>
<li><code>deploy:verify</code> — This is the most complex part. The simplest approach would have Capistrano wait until the Unicorn processes reboot (with a timeout). However, since Unicorn reboots take 30 seconds, I didn’t want to wait all that extra time just to confirm something that works 99% of the time. Using every ounce of Unix-fu I could muster, I cobbled together a solution using the <code>at</code> utility:</li>
</ul>

<p><code>echo &#39;curl -sS http://127.0.0.1:3000/system/revision | grep &quot;c7fe01a813&quot; &gt; /dev/null || echo &quot;Expected SHA: c7fe01a813&quot; | mail -s &quot;Unicorn restart failed&quot; ops@example.com&#39; | at now + 2 minutes</code></p>

<p>Here’s where we ended up: (<em>Note:</em> I edited the output a bit for clarity.)</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ time cap deploy
  * executing `deploy'
 ** transaction: start
  * executing `deploy:update_code'
  * executing "cd /data/codeclimate/app &amp;&amp; git fetch origin &amp;&amp; git reset --hard origin/master"
    command finished in 714ms
  * executing `bundle:install:if_changed'
  * executing `assets:precompile:if_changed'
  * executing `deploy:tag'
  * executing "cd /data/codeclimate/app &amp;&amp; git tag 20130930041400 -m 'Deployed at 2013-09-30 00:13:58 -0400'"
    command finished in 199ms
 ** transaction: commit
  * executing `deploy:restart'
  * executing "rvmsudo god restart unicorn"
    command finished in 1867ms
  * executing `deploy:verify'
    command finished in 216ms

real  0m5.314s
user  0m1.022s
sys 0m0.366s
</code></pre></div>
<p>If your deploys are not as zippy as you&rsquo;d like, consider if a similar approach would work for you. The entire project took me about a day of upfront work, but it pays dividends each and every time we deploy.</p>

<h2>Further Reading</h2>

<ul>
<li><a href="https://github.com/freerange/recap">Recap</a> — Discussed above. Highly recommend taking a look at the source, even if you don’t use it.</li>
<li><a href="https://github.com/blog/470-deployment-script-spring-cleaning">Deployment Script Spring Cleaning</a> from the GitHub blog — The first time I encountered the idea of deploying directly from a single Git working copy. I thought it was crazy at the time but have come around.</li>
</ul>
]]>
    </content>
  </entry>
  <entry>
    <title>Test Coverage and Code Quality, Better&amp;nbsp;Together</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/test-coverage-and-code-quality-better-together/"/>
    <id>https://codeclimate.com/blog/test-coverage-and-code-quality-better-together/</id>
    <updated>2013-09-11T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Code quality and test coverage information often live in separate silos. Code Climate has always been able to help you understand the complexity of your code, but to look at your test coverage required a different set of tools (like SimpleCov). This made it harder than necessary to answer key questions like:</p>

<ul>
<li>&ldquo;Which areas of my app are both low quality and untested?&rdquo;</li>
<li>&ldquo;How well covered is this method I&rsquo;m about to refactor?&rdquo;</li>
<li>&ldquo;Should I beef up integration testing coverage before this large-scale change?&rdquo;</li>
</ul>

<p><strong>Today, we&rsquo;re proud to announce the full integration of test coverage metrics into Code Climate.</strong> To make it dead simple to get started, we&rsquo;re also partnering with three awesome companies that are experts at running your tests – Semaphore, Solano Labs, and Travis CI. (More on this below.)</p>

<p>Having test coverage side-by-side with code quality enables your team to make better decisions earlier in your development process, leading to more maintainable code that is easier to work in. Here&rsquo;s a quick look:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/testing-6e0edf15.gif" alt="Code Climate Test Coverage" /></p>

<p>Just like with code quality, we surface test coverage information at the repository, class, and source listing level (down to an individual line of code) and provide feedback as metrics change over time in the form of email alerts, activity feeds, chat notifications and RSS.</p>

<p>With just a few minutes of setup you can:</p>

<ul>
<li>View test coverage reports for each class alongside other metrics like complexity, duplication, and churn.</li>
<li>Toggle between viewing code smells and test coverage line-by-line on the same source listings (see above).</li>
<li>Track your team&rsquo;s test coverage in your weekly summary emails and Code Climate feed.</li>
</ul>

<p>Here&rsquo;s a couple examples of Code Climate&rsquo;s test coverage integration &hellip;</p>

<p>&hellip; in your chatroom:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/coverage_notifications-5ea16695.jpg" alt="Code Climate Test Coverage Notification" /></p>

<p>&hellip; and in your weekly summary email:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/weekly_summary_coverage-57d1dd83.png" alt="Code Climate Test Coverage Weekly Summary" /></p>

<p>We think the addition of test coverage to our code quality offering is a powerful upgrade in our mission of helping free teams from the burden of technical debt and unmaintainable code. <strong><a href="https://codeclimate.com/signup/account">Give it a try today, and let us know what you think.</a></strong></p>

<h2>How does test coverage work?</h2>

<p>Code Climate does not run your code, and that’s not changing. Instead, <strong>our new test coverage feature works by accepting coverage data sent from your wherever you are already runing your tests.</strong> This means you can use Code Climate’s new test coverage feature with your existing continuous integration (CI) server. (In a pinch, you could even send up test coverage data from your laptop, or anywhere else.)</p>

<p>We&rsquo;ve released the codeclimate-test-reporter RubyGem that you install into your Gemfile. When your tests finish, it sends an HTTPS post to us with a report on which lines of code were executed (and how many times).</p>

<p>Test Coverage is included in all our <a href="https://codeclimate.com/pricing">currently offered plans</a>.  To turn it on for a specific repo, just go to your repository&rsquo;s feed page, click &ldquo;Set up Test Coverage&rdquo; and follow the instructions.</p>

<h2>Our Partners</h2>

<p>Some of you might not have a CI server in place for your project, or perhaps you’ve been frustrated maintaining your own CI server and are looking for something better. We believe cloud-based CI is the future and are excited to partner with three fantastic CI providers &ndash; Semaphore, Solano Labs, and Travis CI &ndash; to ensure you can integrate their services with just a few clicks.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/cc-partners-bcde5c7c.png" alt="Code Climate CI Partners" /></p>

<p>All three of our partners save you from the headaches of administering a CI server (like Jenkins) on your own &ndash; time and money that adds up quickly. If you’re looking to make a move to a cloud CI vendor, now is a great time. <a href="https://semaphoreapp.com/partners/code_climate">Semaphore</a>, <a href="https://api.tddium.com/signups/new?promo_code=codeclimate20for3">Solano Labs</a>, and <a href="https://travis-ci.com/c/travis-cis-got-you-covered">Travis CI</a> have generously agreed to provide Code Climate customers 20% off their first three months.</p>

<p>Joining forces with three companies that are experts at running your tests &ndash; safely, quickly and with little effort &ndash; means we can stay focused on what we do best. To get started with one of these great partner offers, <a href="http://codeclimate.com/login">login</a> to your Code Climate account and head to the Test Coverage setup tab for one of your repos.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Deciphering Ruby Code Metrics</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/deciphering-ruby-code-metrics/"/>
    <id>https://codeclimate.com/blog/deciphering-ruby-code-metrics/</id>
    <updated>2013-08-07T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Ruby has a rich ecosystem of code metrics tools, readily available and easy to run on your codebase. Though generating the metrics is simple, interpreting them is complex.  This article looks at some Ruby metrics, how they are calculated, what they mean and (most importantly) what to do about them, if anything.</p>

<p>Code metrics fall into two tags: static analysis and dynamic analysis. Static analysis is performed without executing the code (or tests). Dynamic analysis, on the other hand, requires executing the code being measured. Test coverage is a form of dynamic analysis because it requires running the test suite. We&rsquo;ll look at both types of metrics.</p>

<p><em>By the way, if you&rsquo;d rather not worry about the nitty-gritty details of the individual code metrics below, <strong><a href="https://codeclimate.com/signup/account">give Code Climate a try</a></strong>. We&rsquo;ve selected the most important metrics to care about and did all the hard work to get you actionable data about your project within minutes.</em></p>

<p><a id="loc"></a></p>

<h2>Lines of Code</h2>

<p>One of the oldest and most rudimentary forms of static analysis is lines of code (LOC). This is most commonly defined as the count of non-blank, non-comment lines of source code. LOC can be looked at on a file-by-file basis or aggregated by module, architecture layer (e.g. the models in an MVC app) or by production code vs. test code.</p>

<p>Rails provides LOC metrics broken down my MVC layer and production code vs. tests via the <code>rake stats</code> command. The output looks something like this:</p>
<div class="highlight"><pre class="highlight plaintext"><code>+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |   612 |   513 |      24 |      57 |   2 |     7 |
| Helpers              |   207 |   179 |       0 |      26 |   0 |     4 |
| Models               |  1321 |  1055 |      13 |     188 |  14 |     3 |
| Libraries            |   115 |    98 |       1 |       6 |   6 |    14 |
| Integration tests    |     0 |     0 |       0 |       0 |   0 |     0 |
| Functional tests     |  2693 |  2282 |      19 |      24 |   1 |    93 |
| Unit tests           |  2738 |  2225 |      16 |       4 |   0 |   554 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |  8749 |  7133 |      78 |     326 |   4 |    19 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 1845     Test LOC: 5288     Code to Test Ratio: 1:2.9
</code></pre></div>
<p>Lines of code alone can&rsquo;t tell you much, but it&rsquo;s usually considered in two ways: overall codebase size and test-to-code ratio. Large, monolithic apps will naturally have higher LOC. Test-to-code ratio can give a programmer a crude sense of the testing practices that have been applied.</p>

<p>Because they are so high level and abstract, don&rsquo;t work on &ldquo;addressing&rdquo; LOC-based metrics directly. Instead, just focus on improvements to maintainability (e.g. decomposing an app into services when appropriate, applying TDD) and it will eventually show up in the metrics.</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/deciphering-metrics/loc-b73d6f96.jpg" alt="LoC Output on Code Climate" /></p>

<p><a id="complexity"></a></p>

<h2>Complexity</h2>

<p>Broadly defined, &ldquo;complexity&rdquo; metrics take many forms:</p>

<ul>
<li><a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">Cyclomatic complexity</a> — Also known as McCabe&rsquo;s complexity, after its inventor Thomas McCabe, cyclomatic complexity is a count of the linearly independent paths through source code. While his <a href="http://www.literateprogramming.com/mccabe.pdf">original paper</a> contains a lot of graph-theory analysis, McCabe noted that cyclomatic complexity &ldquo;is designed to conform to our intuitive notion of complexity&rdquo;.</li>
<li><a href="http://c2.com/cgi/wiki?AbcMetric">The ABC metric</a> — Aggregates the number of assignments, branches and conditionals in a unit of code. The branches portion of an ABC score is very similar to cyclomatic complexity. The metric was designed to be language and style agnostic, which means you could theoretically compare the ABC scores of very different codebases (one in Java and one in Ruby for example).</li>
<li>Ruby&rsquo;s <a href="http://ruby.sadi.st/Flog.html">Flog</a> scores — Perhaps the most popular way to describe the complexity of Ruby code. While Flog incorporates ABC analysis, it is, unlike the ABC metric, opinionated and language-specific. For example, Flog penalizes hard-to-understand Ruby constructs like meta-programming.</li>
</ul>

<p>For my money, Flog scores seem to do the best job of being a proxy for how easy or difficult a block of Ruby code is to understand. Let&rsquo;s take a look at how it&rsquo;s computed for a simple method, based on an example from the Flog website:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">blah</span>         <span style="color: #999988;font-style: italic"># 11.2 total =</span>
  <span style="background-color: #f8f8f8">a</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #0086B3">eval</span> <span style="color: #d14">"1+1"</span> <span style="color: #999988;font-style: italic"># 1.2 (a=) + 6.0 (eval) +</span>

  <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">a</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #009999">2</span>      <span style="color: #999988;font-style: italic"># 1.2 (if) + 1.2 (==) + 0.4 (fixnum) +</span>
    <span style="color: #0086B3">puts</span> <span style="color: #d14">"yay"</span>   <span style="color: #999988;font-style: italic"># 1.2 (puts)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>To use Flog on your own code, first install it:</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ gem install flog
</code></pre></div>
<p>Then you can Flog individual files or whole directories. By default, Flog scores are broken out by method, but you can get per-class total by running it with the <code>-g</code> option (<em>group</em> by class):</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ flog app/models/user.rb
$ flog -g app/controllers
</code></pre></div>
<p>All of this raises a question: What&rsquo;s a good Flog score? It&rsquo;s subjective, of course, but Jake Scruggs, one of the original authors of Metric-Fu, suggested that scores above 20 indicate the method <em>may</em> need refactoring, and above 60 is dangerous. Similarly, <a href="https://codeclimate.com">Code Climate</a> will flag methods with scores above 25, and considers anything above 60 &ldquo;very complex&rdquo;. <em>Fun fact:</em> The highest Flog score ever seen on Code Climate for a single method is 11,354.</p>

<p>If you&rsquo;d like to get a better sense for Flog scores, take a look at complex classes in some <a href="https://codeclimate.com/explore">open source projects</a> on Code Climate. Here, <a href="https://codeclimate.com/github/redmine/redmine/Query#method-complexity">for example</a>, is a pretty complex method inside an open source project:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/deciphering-metrics/complex_method-b343d521.jpg" alt="Complex Method Flog Score" /></p>

<p>Like most code smells, high complexity is a pointer to a deeper problem rather than a problem in-and-of itself. Tread carefully in your refactorings. Often the simplest solutions (e.g. applying <a href="http://www.refactoring.com/catalog/extractMethod.html">Extract Method</a>) are not the best and rethinking your domain model is required, and sometimes may actually make things worse.</p>

<p><a id="duplication"></a></p>

<h2>Duplication</h2>

<p>Static analysis can also identify identical and similar code, which usually results from copying and pasting. In Ruby, <a href="http://ruby.sadi.st/Flay.html">Flay</a> is the most popular tool for duplication detection. It hunts for large, identical syntax trees and also uses fuzzy matching to detect code which differs only by the specific identifiers and constants used.</p>

<p>Let&rsquo;s take a look at an example of two similar, but not-quite-identical Ruby snippets:</p>
<div class="highlight"><pre class="highlight plaintext"><code>###### From app/models/tickets/lighthouse.rb:
def build_request(path, body)
  Post.new(path).tap do |req|
    req["X-LighthouseToken"] = @token
    req.body = body
  end
end

####### From app/models/tickets/pivotal_tracker.rb:
def build_request(path, body)
  Post.new(path).tap do |req|
    req["X-TrackerToken"] = @token
    req.body = body
  end
end
</code></pre></div>
<p>The <a href="http://en.wikipedia.org/wiki/S-expression">s-expressions</a> produced by <a href="https://github.com/seattlerb/ruby_parser">RubyParser</a> for these methods are nearly identical, sans the string literal for the token header name, so Flay reports these as:</p>
<div class="highlight"><pre class="highlight plaintext"><code>1) Similar code found in :defn (mass = 78)
  ./app/models/tickets/lighthouse.rb:25
  ./app/models/tickets/pivotal_tracker.rb:25
</code></pre></div>
<p>Running Flay against your project is simple:</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ gem install flay
$ flay path/to/rails_app
</code></pre></div>
<p>Some duplications reported by Flay should not be addressed. Identical code is generally worse than similar code, of course, but you also have to consider the context. Remember, the real definition of the <a href="http://c2.com/cgi/wiki?DontRepeatYourself">Don&rsquo;t Repeat Yourself</a> (DRY) principle is:</p>

<blockquote>
<p>Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.</p>
</blockquote>

<p>And <em>not</em>:</p>

<blockquote>
<p>Don&rsquo;t type the same characters into the keyboard multiple times.</p>
</blockquote>

<p>Simple Rails controllers that follow the REST convention will be similar and show up in Flay reports, but they&rsquo;re better left <em>damp</em> than introducing a harder-to-understand meta-programmed base class to remove duplication. Remember, code that is too DRY can become <em>chafe</em>, and that&rsquo;s uncomfortable for everyone.</p>

<p><a id="test-coverage"></a></p>

<h2>Test Coverage</h2>

<p>One of the most popular code metrics is test coverage. Because it requires running the test suite, it&rsquo;s actually dynamic analysis rather than static analysis. Coverage is often expressed as a percentage, as in: &ldquo;The test coverage for our Rails app is 83%.&rdquo;</p>

<p>Test coverage metrics come in three flavors:</p>

<ul>
<li>C0 coverage — The percentage of lines of code that have been executed.</li>
<li>C1 coverage — The percentage of branches that have been followed at least once.</li>
<li>C2 coverage — The percentage of unique paths through the source code that have been followed.</li>
</ul>

<p>C0 coverage is by far the most commonly used metric in Ruby. Low test coverage can tell you that your code in untested, but a high test coverage metric doesn&rsquo;t guarantee that your tests are thorough. For example, you could theoretically achieve 100% C0 coverage with a single test with no assertions.</p>

<p>To calculate the test coverage for your Ruby 1.9 app, use <a href="https://github.com/colszowka/simplecov">SimpleCov</a>. It takes a couple steps to setup, but they have <a href="https://github.com/colszowka/simplecov#getting-started">solid documentation</a> so I won&rsquo;t repeat them here.</p>

<p>So what&rsquo;s a good test coverage percentage? It&rsquo;s been hotly debated. Some, like Robert Martin, argue that <a href="http://cleancoder.posterous.com/100-test-coverage">100% test coverage</a> is a natural side effect of proper development practices, and therefore a bare minimum indicator of quality. DHH put forth an <a href="http://37signals.com/svn/posts/3159-testing-like-the-tsa">opposing view</a> likening code coverage to security theater and expressly discouraged aiming for 100% code coverage.</p>

<p>Ultimately you need to use your judgement to make a decision that&rsquo;s right for your team. Different projects with different developers might have different optimal test coverage levels throughout their evolution (even if they are not looking at the metric at all). Tune your sensors to detect pain from under-testing or over-testing and adjust your practices based on pain you&rsquo;re experiencing.</p>

<p>Suppose that you find yourself with low coverage and are feeling pain as a result. Maybe deploys are breaking the production website every so often. What should you do then? <a href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052">Whole books</a> have been written on this subject, but there are a few tips I&rsquo;d suggest as a starting point:</p>

<ol>
<li>Test drive new code.</li>
<li><em>Don&rsquo;t</em> backfill unit tests onto non-TDD&#39;ed code. You lose out on the primary benefits of TDD: design assistance. Worse, you can easily end up cementing a poor object design in place.</li>
<li>Start with high level tests (e.g. acceptance tests) to provide confidence the system as a whole doesn&rsquo;t break as you refactor its guts.</li>
<li>Write failing tests for bugs before fixing them to protect agains regressions. Never fix the same bug twice.</li>
</ol>

<p><a id="churn"></a></p>

<h2>Churn</h2>

<p>Churn looks at your source code from a different dimension: the change of your source files over time. I like to express it as a count of the number of times a class has been modified in your version control history. For example: &ldquo;The <code>User</code> class has a churn of 173.&rdquo;</p>

<p>By itself, Churn can&rsquo;t tell you much, but it&rsquo;s powerful if you mix it with another metric like complexity. <a href="https://github.com/chad/turbulence">Turbulence</a> is a Gem that does just that for Ruby projects. It&rsquo;s quite easy to use:</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ gem install turbulence
$ cd path/to/rails_app &amp;&amp; bule
</code></pre></div>
<p>This will spit out a nice report in <code>turbulence/turbulence.html</code>. Here&rsquo;s an example:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/deciphering-metrics/turbulence-d401c085.jpg" alt="Turbulence Output" /></p>

<p>Depending on its complexity and churn, classes fall into one of four quadrants:</p>

<ol>
<li>Upper-right — Classes with high complexity and high churn. These are good top priorities for refactoring because their maintainability issues are impacting the developers on a regular basis.</li>
<li>Upper-left — Classes with high complexity and low churn. An adapter to hook into a complex third-party system may end up here. It&rsquo;s complicated, but if no one has to work on (or debug) that code, it&rsquo;s probably worth leaving as-is for now.</li>
<li>Lower-left — Classes with low churn and low complexity. The best type of classes to have. Most of your code should be in this quadrant.</li>
<li>Lower-right — Classes with low complexity and high churn. Configuration definitions are a prototypical example. Done right, there&rsquo;s not much to refactor here at all.</li>
</ol>

<h2>Wrapping Up</h2>

<p>Ruby is blessed with a rich ecosystem of code metrics tools, and the gems we looked at today just scratch the surface. Generally, the tools are easy to get started with, so it&rsquo;s worth trying them out and getting a feel for how they match up (or don&rsquo;t) with your sense of code quality. Use the metrics that prove meaningful to you.</p>

<p>Keep in mind that while these metrics contains a treasure trove of information, they represent only a moment in time. They can tell you where you stand, but less about how you got there and where you&rsquo;re going. Part of the reason why I built <a href="https://codeclimate.com/">Code Climate</a> is to address this shortcoming. Code Climate allows you to track progress in a meaningful way, raising visibility within your team:</p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/deciphering-metrics/trends-6c21a860.jpg" alt="GPA Over Time" /></p>

<p><em>If you&rsquo;d like to try out code quality metrics on your project quickly and easily, <strong><a href="https://codeclimate.com/signup/account">give Code Climate a try</a></strong>. There&rsquo;s a free two week trial, and I&rsquo;d love to hear your feedback on how it affects your development process.</em></p>

<p>There&rsquo;s a lot our code can tell us about the software development work we are doing. There will always be the need for our own judgement as to how our systems should be constructed, and where risky areas reside, but I hope I&rsquo;ve shown you how metrics can be a great start to the conversation.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Testing Code in a Rails Initializer</title>
    <author>
      <name>Noah Davis</name>
      <uri>https://twitter.com/noahd1</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/testing-code-in-a-rails-initializer/"/>
    <id>https://codeclimate.com/blog/testing-code-in-a-rails-initializer/</id>
    <updated>2013-07-23T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Rails prides itself on sane defaults, but also provides hooks for customizing the framework by providing Ruby blocks in your configuration files. Most of this code begins and ends its life simply and innocuously. Sometimes, however, it grows. Maybe it&rsquo;s only 3 or 4 lines, but chances are they define important behavior.</p>

<p>Pretty soon, you&rsquo;re going to want some tests. But while testing models and controllers is a well-established practice, how do you test code that&rsquo;s tucked away in an initializer? Is there such thing as an <em>initializer test</em>?</p>

<p>No, not really. But that&rsquo;s ok. Configuration or DSL-style code can trick us into forgetting that we have the full arsenal of Ruby and OO practices at our disposal. Let&rsquo;s take a look at a common idiom found in initialization code and how we might write a test for it.</p>

<h2>Configuring Asset Hosts</h2>

<p>Asset host configuration often start as a simple String:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">config</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">action_controller</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">asset_host</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"assets.example.com"</span>
</code></pre></div>
<p>Eventually, as the security and performance needs of your site change, it may grow to:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">config</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">action_controller</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">asset_host</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Proc</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|*</span><span style="background-color: #f8f8f8">args</span><span style="color: #000000;font-weight: bold">|</span>
  <span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">request</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">args</span>

  <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">try</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:ssl?</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #d14">'ssl.cdn.example.com'</span>
  <span style="color: #000000;font-weight: bold">else</span>
    <span style="color: #d14">'cdn%d.example.com'</span> <span style="color: #000000;font-weight: bold">%</span> <span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">hash</span> <span style="color: #000000;font-weight: bold">%</span> <span style="color: #009999">4</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Rails accepts an asset host <code>Proc</code> which takes two arguments &ndash; the path to the source file and, when available, the request object &ndash; and returns a computed asset host. What we really want to test here is not the assignment of our <code>Proc</code> to a variable, but the logic inside the <code>Proc</code>. If we isolate it, it&rsquo;s going to make our lives a bit easier.</p>

<p>Since Rails seems to want a <code>Proc</code> for the asset host, we can provide one. Instead of embedding it in an environment file, we can return one from a method inside an object:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">AssetHosts</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">configuration</span>
    <span style="color: #008080">Proc</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|*</span><span style="background-color: #f8f8f8">args</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">request</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">args</span>

      <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">try</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:ssl?</span><span style="background-color: #f8f8f8">)</span>
        <span style="color: #d14">'ssl.cdn.example.com'</span>
      <span style="color: #000000;font-weight: bold">else</span>
        <span style="color: #d14">'cdn%d.example.com'</span> <span style="color: #000000;font-weight: bold">%</span> <span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">hash</span> <span style="color: #000000;font-weight: bold">%</span> <span style="color: #009999">4</span><span style="background-color: #f8f8f8">)</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>It&rsquo;s the exact same code inside the <code>#configuration</code> method, but now we have an object we can test and refactor. To use it, simply assign it to the <code>asset_host</code> config variable as before:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">config</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">action_controller</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">asset_host</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">AssetHosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">configuration</span>
</code></pre></div>
<p>At this point you may see an opportunity to leverage Ruby&rsquo;s duck typing, and eliminate the explicit <code>Proc</code> entirely, instead providing an <code>AssetHosts#call</code> method directly. Let&rsquo;s see how that would work:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">AssetHosts</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">request</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">nil</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">try</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:ssl?</span><span style="background-color: #f8f8f8">)</span>
      <span style="color: #d14">'ssl.cdn.example.com'</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="color: #d14">'cdn%d.example.com'</span> <span style="color: #000000;font-weight: bold">%</span> <span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">hash</span> <span style="color: #000000;font-weight: bold">%</span> <span style="color: #009999">4</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Since Rails just expects that the object you provide for the <code>asset_hosts</code> variable respond to the <code>#call</code> interface (like <code>Proc</code> itself does), you can simplify the configuration:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">config</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">action_controller</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">asset_host</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">AssetHosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span>
</code></pre></div>
<p>Now lets wrap some tests around <code>AssetHosts</code>. Here&rsquo;s a first cut:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">describe</span> <span style="color: #008080">AssetHosts</span> <span style="color: #000000;font-weight: bold">do</span>
  <span style="background-color: #f8f8f8">describe</span> <span style="color: #d14">"#call"</span> <span style="color: #000000;font-weight: bold">do</span>
    <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:https_request</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">double</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">ssl?: </span><span style="color: #000000;font-weight: bold">true</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>
    <span style="background-color: #f8f8f8">let</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:http_request</span><span style="background-color: #f8f8f8">)</span>  <span style="background-color: #f8f8f8">{</span> <span style="background-color: #f8f8f8">double</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">ssl?: </span><span style="color: #000000;font-weight: bold">false</span><span style="background-color: #f8f8f8">)</span> <span style="background-color: #f8f8f8">}</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"HTTPS"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"returns the SSL CDN asset host"</span> <span style="color: #000000;font-weight: bold">do</span>
        <span style="color: #008080">AssetHosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"image.png"</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">https_request</span><span style="background-color: #f8f8f8">).</span>
          <span style="color: #990000;font-weight: bold">should</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #d14">"ssl.cdn.example.com"</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"HTTP"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"balances asset hosts between 0 - 3"</span> <span style="color: #000000;font-weight: bold">do</span>
        <span style="background-color: #f8f8f8">asset_hosts</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">AssetHosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span>
        <span style="background-color: #f8f8f8">asset_hosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"foo.png"</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">http_request</span><span style="background-color: #f8f8f8">).</span>
          <span style="color: #990000;font-weight: bold">should</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #d14">"cdn1.example.com"</span>

        <span style="background-color: #f8f8f8">asset_hosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"bar.png"</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">http_request</span><span style="background-color: #f8f8f8">).</span>
          <span style="color: #990000;font-weight: bold">should</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #d14">"cdn2.example.com"</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>

    <span style="background-color: #f8f8f8">context</span> <span style="color: #d14">"no request"</span> <span style="color: #000000;font-weight: bold">do</span>
      <span style="background-color: #f8f8f8">it</span> <span style="color: #d14">"returns the non-ssl asset host"</span> <span style="color: #000000;font-weight: bold">do</span>
        <span style="color: #008080">AssetHosts</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"image.png"</span><span style="background-color: #f8f8f8">).</span>
          <span style="color: #990000;font-weight: bold">should</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #d14">"cdn0.example.com"</span>
      <span style="color: #000000;font-weight: bold">end</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>It&rsquo;s not magic, but the beauty of first-class objects is they have room to breathe and help present refactorings. In this case, you can apply the <em>Composed Method</em> pattern to <code>AssetHosts#call</code>.</p>

<p>Guided by tests, you might end up with an object that looks like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">AssetHosts</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">call</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">request</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">nil</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">try</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:ssl?</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">https_asset_host</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">http_asset_host</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

<span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">http_asset_host</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #d14">'cdn%d.example.com'</span> <span style="color: #000000;font-weight: bold">%</span> <span style="background-color: #f8f8f8">cdn_number</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">https_asset_host</span>
    <span style="color: #d14">'ssl.cdn.example.com'</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">cdn_number</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">source</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">hash</span> <span style="color: #000000;font-weight: bold">%</span> <span style="color: #009999">4</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Since the external behavior of <code>AssetHosts</code> hasn&rsquo;t changed, no changes to the tests are required.</p>

<p>By making a small leap &ndash; isolating configuration code into an object &ndash; we now have logic that is easier to test, read, and change. If you find yourself stuck in a similar situation, with important logic stuck in a place that resists testing, see where a similar leap can lead you.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Rails' Insecure Defaults</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/rails-insecure-defaults/"/>
    <id>https://codeclimate.com/blog/rails-insecure-defaults/</id>
    <updated>2013-03-27T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><strong>Update:</strong> If you&rsquo;re interested in this, you may want to check out our new <a href="http://railssecurity.com/">free, 1-month email course about Rails security</a>.</p>

<p>Secure defaults are critical to building secure systems. If a developer must take explicit action to enforce secure behavior, eventually even an experienced developer will forget to do so. For this reason, security experts say:</p>

<blockquote>
<p>&ldquo;Insecure by default is insecure.&rdquo;</p>
</blockquote>

<p>Rails&rsquo; reputation as a relatively secure Web framework is well deserved. Out-of-the-box, there is protection against many common attacks: cross site scripting (XSS), cross site request forgery (CSRF) and SQL injection. Core members are knowledgeable and genuinely concerned with security.</p>

<p>However, there are places where the default behavior could be more secure. This post explores potential security issues in Rails 3 that are fixed in Rails 4, as well as some that are still risky. I hope this post will help you secure your own apps, as well as inspire changes to Rails itself.</p>

<h2>Rails 3 Issues</h2>

<p>Let&rsquo;s begin by looking at some Rails 3 issues that are resolved in master. The Rails team deserves credit for addressing these, but they are worth noting since many applications will be running on Rails 2 and 3 for years to come.</p>

<p><a id="match-routes"></a></p>

<h3>1. CSRF via Leaky #match Routes</h3>

<p>Here is an example taken directly from the Rails 3 generated <code>config/routes.rb</code> file:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">WebStore</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Application</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">routes</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">draw</span> <span style="color: #000000;font-weight: bold">do</span>
  <span style="color: #999988;font-style: italic"># Sample of named route:</span>
  <span style="background-color: #f8f8f8">match</span> <span style="color: #d14">'products/:id/purchase'</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #d14">'catalog#purchase'</span><span style="background-color: #f8f8f8">,</span>
    <span style="color: #990073">:as</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #990073">:purchase</span>
  <span style="color: #999988;font-style: italic"># This route can be invoked with</span>
  <span style="color: #999988;font-style: italic"># purchase_url(:id =&gt; product.id)</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This has the effect of routing the <code>/products/:id/purchase</code> path to the <code>CatalogController#purchase</code> method <em>for all HTTP verbs</em> (<code>GET</code>, <code>POST</code>, etc). The problem is that Rails&rsquo; cross site request forgery (CSRF) protection does not apply to <code>GET</code> requests. You can see this in the method to enforce CSRF protection:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">verified_request?</span>
  <span style="color: #000000;font-weight: bold">!</span><span style="background-color: #f8f8f8">protect_against_forgery?</span> <span style="color: #000000;font-weight: bold">||</span>
  <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">get?</span> <span style="color: #000000;font-weight: bold">||</span>
  <span style="background-color: #f8f8f8">form_authenticity_token</span> <span style="color: #000000;font-weight: bold">==</span>
    <span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="background-color: #f8f8f8">request_forgery_protection_token</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">||</span>
  <span style="background-color: #f8f8f8">form_authenticity_token</span> <span style="color: #000000;font-weight: bold">==</span>
    <span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">headers</span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">'X-CSRF-Token'</span><span style="background-color: #f8f8f8">]</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>The second line short-circuits the CSRF check: it means that if <code>request.get?</code> is <code>true</code>, the request is considered &ldquo;verified&rdquo; and the CSRF check is skipped. In fact, in the Rails source there is a comment above this method that says:</p>

<blockquote>
<p>Gets should be safe and idempotent.</p>
</blockquote>

<p>In your application, you may always use <code>POST</code> to make requests to <code>/products/:id/purchase</code>. But because the router allows <code>GET</code> requests as well, <em>an attacker can trivially bypass the CSRF protection for any method routed via the <code>#match</code> helper.</em>  If your application uses the old wildcard route (not recommended), the CSRF protection is completely ineffective.</p>

<p><strong>Best Practice:</strong> Don&rsquo;t use <code>GET</code> for unsafe actions. Don&rsquo;t use <code>#match</code> to add routes (instead use <code>#post</code>, <code>#put</code>, etc.). Ensure you don&rsquo;t have wildcard routes.</p>

<p><strong>The Fix:</strong> Rails now requires you to specify either specific HTTP verbs or <code>via: :all</code> when adding routes with <code>#match</code>. The generated <code>config/routes.rb</code> no longer contains commented out <code>#match</code> routes. (The wildcard route is also removed.)</p>

<p><a id="format-anchors"></a></p>

<h3>2. Regular Expression Anchors in Format Validations</h3>

<p>Consider the following validation:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">validates_format_of</span> <span style="color: #990073">:name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">with: </span><span style="color: #009926">/^[a-z ]+$/i</span>
</code></pre></div>
<p>This code is usually a subtle bug. The developer probably meant to enforce that the entire name attribute is composed of only letters and spaces. Instead, this will only enforce that <em>at least one line</em> in the name is composed of letters and spaces. Some examples of regular expression matching make it more clear:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">&gt;&gt;</span> <span style="color: #009926">/^[a-z ]+$/i</span> <span style="color: #000000;font-weight: bold">=~</span> <span style="color: #d14">"Joe User"</span>
<span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">0</span> <span style="color: #999988;font-style: italic"># Match</span>

<span style="color: #000000;font-weight: bold">&gt;&gt;</span> <span style="color: #009926">/^[a-z ]+$/i</span> <span style="color: #000000;font-weight: bold">=~</span> <span style="color: #d14">" '); -- foo"</span>
<span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #000000;font-weight: bold">nil</span> <span style="color: #999988;font-style: italic"># No match</span>

<span style="color: #000000;font-weight: bold">&gt;&gt;</span> <span style="color: #009926">/^[a-z ]+$/i</span> <span style="color: #000000;font-weight: bold">=~</span> <span style="color: #d14">"a</span><span style="color: #d14">\n</span><span style="color: #d14"> '); -- foo"</span>
<span style="color: #000000;font-weight: bold">=&gt;</span> <span style="color: #009999">0</span> <span style="color: #999988;font-style: italic"># Match</span>
</code></pre></div>
<p>The developer should have used the <code>\A</code> (beginning of string) and <code>\z</code> (end of string) anchors instead of <code>^</code> (beginning of line) and <code>$</code> (end of line). The correct code would be:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">validates_format_of</span> <span style="color: #990073">:name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">with: </span><span style="color: #009926">/\A[a-z ]+\z/i</span>
</code></pre></div>
<p>You could argue that the developer is at fault, and you&rsquo;d be right. However, the behavior of regular expression anchors is not necessarily obvious, especially to developers who are not considering multiline values. (Perhaps the attribute is only exposed in a text input field, never a <code>textarea</code>.)</p>

<p>Rails is at the right place in the stack to save developers from themselves and that&rsquo;s exactly what has been done in Rails 4.</p>

<p><strong>Best Practice:</strong> Whenver possible, use <code>\A</code> and <code>\z</code> to anchor regular expressions instead of <code>^</code> and <code>$</code>.</p>

<p><strong>The Fix:</strong> Rails 4 introduces a <code>multiline</code> option for <code>validates_format_of</code>. If your regular expression is anchored using <code>^</code> and <code>$</code>rather than <code>\A</code> and <code>\z</code> and you do not pass <code>multiline: true</code>, Rails will raise an exception. This is a great example of creating safer default behavior, while still providing control to override it where necessary.</p>

<p><a id="clickjacking"></a></p>

<h3>3. Clickjacking</h3>

<p>Clickjacking or &ldquo;UI redress attacks&rdquo; involve rendering the target site in an invisible frame, and tricking a victim to take an unexpected action when they click. If a site is vulnerable to clickjacking, an attacker may trick users into taking undesired actions like making a one-click purchase, following someone on Twitter, or changing their privacy settings.</p>

<p>To defend against clickjacking attacks, a site must prevent itself from being rendered in a <code>frame</code> or <code>iframe</code> on sites that it does not control. Older browsers required ugly &ldquo;frame busting&rdquo; JavaScripts, but modern browsers support the <a href="https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options"><code>X-Frame-Options</code> HTTP header</a> which instructs the browser about whether or not it should allow the site to be framed. This header is easy to include, and not likely to break most websites, so Rails should include it by default.</p>

<p><strong>Best Practice:</strong> Use the <a href="https://github.com/twitter/secureheaders">secure_headers</a> RubyGem by Twitter to add an <code>X-Frame-Options</code> header with the value of <code>SAMEORIGIN</code> or <code>DENY</code>.</p>

<p><strong>The Fix:</strong> By default, Rails 4 now sends the <code>X-Frame-Options</code> header with the value of <code>SAMEORIGIN</code>:</p>
<div class="highlight"><pre class="highlight plaintext"><code>X-Frame-Options: SAMEORIGIN
</code></pre></div>
<p>This tells the browser that your application can only be framed by pages originating from the same domain.</p>

<p><a id="readable-sessions"></a></p>

<h3>4. User-Readable Sessions</h3>

<p>The default Rails 3 session store uses signed, unencrypted cookies. While this protects the session from tampering, it is trivial for an attacker to decode the contents of a session cookie:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">session_cookie</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">&lt;&lt;-</span><span style="color: #008080">STR</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">strip</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">gsub</span><span style="background-color: #f8f8f8">(</span><span style="color: #009926">/\n/</span><span style="background-color: #f8f8f8">,</span> <span style="color: #d14">''</span><span style="background-color: #f8f8f8">)</span><span style="color: #d14">
BAh7CEkiD3Nlc3Npb25faWQGOgZFRkkiJTkwYThmZmQ3Zm
dAY7AEZJIgtzZWtyaXQGO…--4c50026d340abf222…
</span><span style="color: #008080">STR</span>

<span style="color: #008080">Marshal</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">load</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Base64</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">decode64</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">session_cookie</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">split</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"--"</span><span style="background-color: #f8f8f8">)[</span><span style="color: #009999">0</span><span style="background-color: #f8f8f8">]))</span>
<span style="color: #999988;font-style: italic"># =&gt; {</span>
<span style="color: #999988;font-style: italic">#   "session_id"  =&gt; "90a8f...",</span>
<span style="color: #999988;font-style: italic">#   "_csrf_token" =&gt; "iUoXA...",</span>
<span style="color: #999988;font-style: italic">#   "secret"      =&gt; "sekrit"</span>
<span style="color: #999988;font-style: italic"># }</span>
</code></pre></div>
<p>It&rsquo;s unsafe to store any sensitive information in the session. Hopefully this is a well known, but even if a user&rsquo;s session does not contain sensitive data, it can still create risk. By decoding the session data, an attacker can gain useful information about the internals of the application that can be leveraged in an attack. For example, it may be possible to understand which authentication system is in use (Authlogic, Devise, etc.).</p>

<p>While this does not create a vulnerability on its own, it can aid attackers. Any information about how the application works can be used to hone exploits, and in some cases to avoid triggering exceptions or tripwires that could give the developer an early warning an attack is underway.</p>

<p>User-readable sessions violate the Principle of Least Privilege, because even though the session data must be passed to the visitor&rsquo;s browser, the visitor does not need to be able to read the data.</p>

<p><strong>Best Practice:</strong> Don&rsquo;t put any information into the session that you wouldn&rsquo;t want an attacker to have access to.</p>

<p><strong>The Fix:</strong> Rails 4 changed the default session store to be encrypted. Users can no longer decode the contents of the session without the decryption key, which is not available on the client side.</p>

<h2>Unresolved Issues</h2>

<p>The remainder of this post covers security risks that are still present in Rails&rsquo; at the time of publication. Hopefully, at least some of these will be fixed, and I will update this post if that is the case.</p>

<p><a id="server-header"></a></p>

<h3>1. Verbose <code>Server</code> Headers</h3>

<p>The default Rails server is WEBrick (part of the Ruby standard library), even though it is rare to run WEBrick in production. By default, WEBrick returns a verbose <code>Server</code> header with every HTTP response:</p>
<div class="highlight"><pre class="highlight plaintext"><code>HTTP/1.1 200 OK
# …
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
</code></pre></div>
<p>Looking at the WEBrick source, you can see the header is composed with a few key pieces of information:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #d14">"WEBrick/</span><span style="color: #d14">#{</span><span style="color: #008080">WEBrick</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">VERSION</span><span style="color: #d14">}</span><span style="color: #d14"> "</span> <span style="color: #000000;font-weight: bold">+</span>
<span style="color: #d14">"(Ruby/</span><span style="color: #d14">#{</span><span style="color: #008080">RUBY_VERSION</span><span style="color: #d14">}</span><span style="color: #d14">/</span><span style="color: #d14">#{</span><span style="color: #008080">RUBY_RELEASE_DATE</span><span style="color: #d14">}</span><span style="color: #d14">)"</span><span style="background-color: #f8f8f8">,</span>
</code></pre></div>
<p>This exposes the WEBrick version, and also the specific Ruby patchlevel being run (since release dates map to patchlevels). With this information, spray and prey scanners can target your server more effectively, and attackers can tailor their attack payloads.</p>

<p><strong>Best Practice:</strong> Avoid running WEBrick in production. There are better servers out there like Passenger, Unicorn, Thin and Puma.</p>

<p><strong>The Fix:</strong> While this issue originates in the WEBrick source, Rails should configure WEBrick to use a less verbose <code>Server</code> header. Simply &ldquo;Ruby&rdquo; seems like a good choice.</p>

<p><a id="server-binding"></a></p>

<h3>2. Binding to 0.0.0.0</h3>

<p>If you boot a Rails server, you&rsquo;ll see something like this:</p>
<div class="highlight"><pre class="highlight plaintext"><code>$ ./script/rails server -e production
=&gt; Booting WEBrick
=&gt; Rails 3.2.12 application starting in production on http://0.0.0.0:3000
</code></pre></div>
<p>Rails is binding on 0.0.0.0 (all network interfaces) instead of 127.0.0.1 (local interface only). This can create security risk in both development and production contexts.</p>

<p>In development mode, Rails is not as secure (for example, it renders diagnostic 500 pages). Additionally, developers may load a mix of production data and testing data (e.g. username: admin / password: admin). Scanning for web servers on port 3000 in a San Francisco coffee shop would probably yield good targets.</p>

<p>In production, Rails should be run behind a proxy. Without a proxy, IP spoofing attacks are trivial. But if Rails binds on 0.0.0.0, it may be possible to easily circumvent a proxy by hitting Rails directly depending on the deployment configuration.</p>

<p>Therefore, binding to 127.0.0.1 is a safer default than 0.0.0.0 in all Rails environments.</p>

<p><strong>Best Practice:</strong> Ensure your Web server process is binding on the minimal set of interfaces in production. Avoid loading production data on your laptop for debugging purposes. If you must do so, load a minimal dataset and remove it as soon as it&rsquo;s no longer necessary.</p>

<p><strong>The Fix:</strong> Rails already provides a <code>--binding</code> option to change the IP address that the server listens on. The default should be changed from 0.0.0.0 to 127.0.0.1. Developers who need to bind to other interfaces in production can make that change in their deployment configurations.</p>

<p><a id="versioned-secrets"></a></p>

<h3>3. Versioned Secret Tokens</h3>

<p>Every Rails app gets a long, randomly-generated secret token in <code>config/initializers/secret_token.rb</code> when it is created with <code>rails new</code>. It looks something like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">WebStore</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Application</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">config</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">secret_token</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">'4f06a7a…72489780f'</span>
</code></pre></div>
<p>Since Rails creates this automatically, most developers do not think about it much. But this secret token is like a root key for your application. If you have the secret token, it is trivial to forge sessions and escalate privileges. It is one of the most critical pieces of sensitive data to protect. Encryption is only as good as your key management practices.</p>

<p>Unfortunately, Rails falls flat in dealing with these secret token. The <code>secret_token.rb</code> file ends up checked into version control, and copied to GitHub, CI servers and every developer&rsquo;s laptop.</p>

<p><strong>Best Practice:</strong> Use a different secret token in each environment. Inject it via an ENV var into the application. As an alternative, symlink the production secret token in during deployment.</p>

<p><strong>This Fix:</strong> At a minimum, Rails should <code>.gitignore</code> the <code>config/initializers/secret_token.rb</code> file by default. Developers can symlink a production token in place when they deploy or change the initializer to use an ENV var (on e.g. Heroku).</p>

<p>I would go further and propose that Rails create a storage mechanism for secrets. There are many libraries that provide installation instructions involving checking secrets into initializers, which is a bad practice. At the same time, there are at least two popular strategies for dealing with this issue: ENV vars and symlinked initializers.</p>

<p>Rails is in the right place to provide a simple API that developers can depend on for managing secrets, with a swappable backend (like the cache store and session store).</p>

<p><a id="logging-sql"></a></p>

<h3>4. Logging Values in SQL Statements</h3>

<p>The <code>config.filter_parameters</code> Rails provides is a useful way to prevent sensitive information like passwords from accumulating in production log files. But it does not affect logging of values in SQL statements:</p>
<div class="highlight"><pre class="highlight plaintext"><code>Started POST "/users" for 127.0.0.1 at 2013-03-12 14:26:28 -0400
Processing by UsersController#create as HTML
  Parameters: {"utf8"=&gt;"✓œ“", "authenticity_token"=&gt;"...",
  "user"=&gt;{"name"=&gt;"Name", "password"=&gt;"[FILTERED]"}, "commit"=&gt;"Create User"}
  SQL (7.2ms)  INSERT INTO "users" ("created_at", "name", "password_digest",
  "updated_at") VALUES (?, ?, ?, ?)  [["created_at",
  Tue, 12 Mar 2013 18:26:28 UTC +00:00], ["name", "Name"], ["password_digest",
  "$2a$10$r/XGSY9zJr62IpedC1m4Jes8slRRNn8tkikn5.0kE2izKNMlPsqvC"], ["updated_at",
  Tue, 12 Mar 2013 18:26:28 UTC +00:00]]
Completed 302 Found in 91ms (ActiveRecord: 8.8ms)
</code></pre></div>
<p>The default Rails logging level in production mode (info) will not log SQL statements. The risk here is that sometimes developers will temporarily increase the logging level in production when debugging.
During those periods, the application may write sensitive data to log files, which then persist on the server for a long time. An attacker who gains access to read files on the server could find the data with a simple <code>grep</code>.</p>

<p><strong>Best Practice:</strong> Be aware of what is being logged at your production log level. If you increase the log level temporarily, causing sensitive data to be logged, remove that data as soon as it&rsquo;s no longer needed.</p>

<p><strong>The Fix:</strong> Rails could change the <code>config.filter_parameters</code> option into something like <code>config.filter_logs</code>, and apply it to both parameters and SQL statements. It may not be possible to properly filter SQL statements in all cases (as it would require a SQL parser) but there may be an 80/20 solution that could work for standard inserts and updates.</p>

<p>As an alternative, Rails could redact the entire SQL statement if it contains references to the filtered values (for example, redact all statements containing &ldquo;password&rdquo;), at least in production mode.</p>

<p><a id="offsite-redirects"></a></p>

<h3>5. Offsite Redirects</h3>

<p>Many applications contain a controller action that needs to send users to a different location depending on the context. The most common example is a <code>SessionsController</code> that directs the newly authenticated user to their intended destination or a default destination:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SignupsController</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ApplicationController</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create</span>
    <span style="color: #999988;font-style: italic"># ...</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:destination</span><span style="background-color: #f8f8f8">].</span><span style="color: #990000;font-weight: bold">present?</span>
      <span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:destination</span><span style="background-color: #f8f8f8">]</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">dashboard_path</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This creates the risk that an attacker can construct a URL that will cause an unsuspecting user to be sent to a malicious site after they login:</p>
<div class="highlight"><pre class="highlight plaintext"><code>https://example.com/sessions/new?destination=http://evil.com/
</code></pre></div>
<p>Unvalidated redirects can be used for phishing or may damage the users trust in you because it appears that <em>you</em> sent them to a malicious website. Even a vigilant user may not check the URL bar to ensure they are not being phished after their first page load. The issue is serious enough that it has made it into the latest edition of the OWASP Top Ten Application Security Threats.</p>

<p><strong>Best Practice:</strong> When passing a hash to <code>#redirect_to</code>, use the <code>only_path: true</code> option to limit the redirect to the current host:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">merge</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">only_path: </span><span style="color: #000000;font-weight: bold">true</span><span style="background-color: #f8f8f8">)</span>
</code></pre></div>
<p>When passing a string, you can parse it an extract the path:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">redirect_to</span> <span style="color: #008080">URI</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:destination</span><span style="background-color: #f8f8f8">]).</span><span style="color: #990000;font-weight: bold">path</span>
</code></pre></div>
<p><strong>The Fix:</strong> By default, Rails should only allow redirects within the same domain (or a whitelist). For the rare cases where external redirects are intended, the developer should be required to pass an <code>external: true</code> option to <code>redirect_to</code> in order to opt-in to the more risky behavior.</p>

<p><a id="linkto-xss"></a></p>

<h3>6. Cross Site Scripting (XSS) Via <code>link_to</code></h3>

<p>Many developers don&rsquo;t realize that the HREF attribute of the <code>link_to</code> helper can be used to inject JavaScript. Here is an example of unsafe code:</p>
<div class="highlight"><pre class="highlight erb"><code><span style="color: #999999;font-weight: bold">&lt;%=</span> <span style="background-color: #f8f8f8">link_to</span> <span style="color: #d14">"Homepage"</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">homepage_url</span> <span style="color: #999999;font-weight: bold">%&gt;</span>
</code></pre></div>
<p>Assuming the user can set the value of their <code>homepage_url</code> by updating their profile, it creates the risk of XSS. This value:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">homepage_url</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"javascript:alert('hello')"</span>
</code></pre></div>
<p>Will generate this HTML:</p>
<div class="highlight"><pre class="highlight html"><code><span style="color: #000080">&lt;a</span> <span style="color: #008080">href=</span><span style="color: #d14">"javascript:alert('hello')"</span><span style="color: #000080">&gt;</span>Homepage<span style="color: #000080">&lt;/a&gt;</span>
</code></pre></div>
<p>Clicking the link will execute the script provided by the attacker. Rails&rsquo; XSS protection will not prevent this. This used to be necessary and common before the community migrated to more unobtrusive JavaScript techniques, but is now a vestigial weakness.</p>

<p><strong>Best Practice:</strong> Avoid using untrusted input in HREFs. When you must allow the user to control the HREF, run the input through <code>URI.parse</code> first and sanity check the protocol and host.</p>

<p><strong>The Fix:</strong> Rails should only allow paths, HTTP, HTTPS and <code>mailto:</code> href values in the <code>link_to</code> helper by default. Developers should have to opt-in to unsafe behavior by passing in an option to the <code>link_to</code> helper, or <code>link_to</code> could simply not support this and developers can craft their links by hand.</p>

<p><a id="sqli"></a></p>

<h3>7. SQL Injection</h3>

<p>Rails does a relatively good job of preventing common SQL injection (SQLi) attacks, so developers may think that Rails is immune to SQLi. Of course, that is not the case. Suppose a developer needs to pull either subtotals or totals off the <code>orders</code> table, based on a parameter. They might write:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Order</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pluck</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:column</span><span style="background-color: #f8f8f8">])</span>
</code></pre></div>
<p>This is not a safe thing to do. Clearly, the user can now manipulate the application to retrieve any column of data from the <code>orders</code> table that they wish. What is less obvious, however, is that the attacker can also pull values from other tables. For example:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:column</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"password FROM users--"</span>
<span style="color: #008080">Order</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">pluck</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:column</span><span style="background-color: #f8f8f8">])</span>
</code></pre></div>
<p>Will become:</p>
<div class="highlight"><pre class="highlight sql"><code><span style="color: #000000;font-weight: bold">SELECT</span> <span style="background-color: #f8f8f8">password</span> <span style="color: #000000;font-weight: bold">FROM</span> <span style="background-color: #f8f8f8">users</span><span style="color: #999988;font-style: italic">-- FROM "orders"</span>
</code></pre></div>
<p>Similarly, the <code>column_name</code> attribute to <code>#calculate</code> actually accepts arbitrary SQL:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:column</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"age) FROM users WHERE name = 'Bob'; --"</span>
<span style="color: #008080">Order</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">calculate</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:sum</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:column</span><span style="background-color: #f8f8f8">])</span>
</code></pre></div>
<p>Will become:</p>
<div class="highlight"><pre class="highlight sql"><code><span style="color: #000000;font-weight: bold">SELECT</span> <span style="color: #000000;font-weight: bold">SUM</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">age</span><span style="background-color: #f8f8f8">)</span> <span style="color: #000000;font-weight: bold">FROM</span> <span style="background-color: #f8f8f8">users</span> <span style="color: #000000;font-weight: bold">WHERE</span> <span style="background-color: #f8f8f8">name</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">'Bob'</span><span style="background-color: #f8f8f8">;</span> <span style="color: #999988;font-style: italic">--) AS sum_id FROM "orders"</span>
</code></pre></div>
<p>Controlling the <code>column_name</code> attribute of the <code>#calculate</code> method allows the attacker to pull specific values from arbitrary columns on arbitrary tables.</p>

<p><a href="http://rails-sqli.org">Rails-SQLi.org</a> details which ActiveRecord methods and options permit SQL, with examples of how they might be attacked.</p>

<p><strong>Best Practice:</strong> Understand the APIs you use and where they might permit more dangerous operations than you&rsquo;d expect. Use the safest APIs possible, and whitelist expected inputs.</p>

<p><strong>The Fix:</strong> This one is difficult to solve en masse, as the proper solution varies by context. In general, ActiveRecord APIs should only permit SQL fragments where they are commonly used. Method parameters named <code>column_name</code> should only accept column names. Alternative APIs can be provided for developers who need more control.</p>

<p><em>Hat tip to Justin Collins of Twitter for writing <a href="http://rails-sqli.org">rails-sqli.org</a> which made me aware of this issue.</em></p>

<p><a id="yaml"></a></p>

<h3>8. YAML Deserialization</h3>

<p>As many Ruby developers learned in January, deserializing untrusted data with YAML is as unsafe as <code>eval</code>. There&rsquo;s been a lot written about YAML-based attacks, so I won&rsquo;t rehash it here, but in summary if the attacker can inject a YAML payload, they can execute arbitrary code on the server. The application does not need to do anything other than load the YAML in order to be vulnerable.</p>

<p>Although Rails was patched to avoid parsing YAML sent to the server in HTTP requests, it still uses YAML as the default serialization format for the <code>#serialize</code> feature, as well as the new <code>#store</code> feature (which is itself a thin wrapper around <code>#serialize</code>). Risky code looks like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">User</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ActiveRecord</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Base</span>
  <span style="color: #999988;font-style: italic"># ...</span>
  <span style="background-color: #f8f8f8">serialize</span> <span style="color: #990073">:preferences</span>

  <span style="background-color: #f8f8f8">store</span> <span style="color: #990073">:theme</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">accessors: </span><span style="background-color: #f8f8f8">[</span> <span style="color: #990073">:color</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:bgcolor</span> <span style="background-color: #f8f8f8">]</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Most Rails developers would not feel comfortable with storing arbitrary Ruby code in their database, and <code>eval</code>ing it when the records are loaded, but that&rsquo;s the functional equivalent of using YAML deserialization in this way. It violates the Principle of Least Privilege when the stored data does not include arbitrary Ruby objects. Suddenly a vulnerability allowing the writing of a value in a database can be springboarded into taking control of the entire server.</p>

<p>The use of YAML is especially concerning to me as it looks safe but is dangerous. The YAML format was looked at for years by hundreds of skilled developers before the remote code execution (RCE) vulnerability was exposed. While this is top of mind in the Ruby community now, new developers who pick up Rails next year will not have experienced the YAML RCE fiasco.</p>

<p><strong>Best Practice:</strong> Use the JSON serialization format instead of YAML for <code>#serialize</code> and <code>#store</code>:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">User</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ActiveRecord</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Base</span>
  <span style="background-color: #f8f8f8">serialize</span> <span style="color: #990073">:preferences</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">JSON</span>
  <span style="background-color: #f8f8f8">store</span> <span style="color: #990073">:theme</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">accessors: </span><span style="background-color: #f8f8f8">[</span> <span style="color: #990073">:color</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:bgcolor</span> <span style="background-color: #f8f8f8">],</span> <span style="color: #990073">coder: </span><span style="color: #008080">JSON</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p><strong>The Fix:</strong> Rails should switch its default serialization format for ActiveRecord from YAML to JSON. The YAML behavior should be either available by opt-in or extracted into an optional Gem.</p>

<p><a id="mass-assignment"></a></p>

<h3>9. Mass Assignment</h3>

<p>Rails 4 switched from using <code>attr_accessible</code> to deal with mass assignment vulnerabilities to the strong<em>parameters approach. The <code>params</code> object is now an instance of <code>ActionController::Parameters</code>. strong</em>parameters works by checking that instances of <code>Parameters</code> used in mass assignment are &ldquo;permitted&rdquo; &ndash; that a developer has specifically indicated which keys (and value types) are expected.</p>

<p>In general, this is a positive change, but it does introduce a new attack vector that was not present in the <code>attr_accessible</code> world. Consider this example:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">params</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">{</span> <span style="color: #990073">user: </span><span style="background-color: #f8f8f8">{</span> <span style="color: #990073">admin: </span><span style="color: #000000;font-weight: bold">true</span> <span style="background-color: #f8f8f8">}.</span><span style="color: #990000;font-weight: bold">to_json</span> <span style="background-color: #f8f8f8">}</span>
<span style="color: #999988;font-style: italic"># =&gt; {:user=&gt;"{\"admin\":true}"}</span>

<span style="color: #008080">@user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">User</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">JSON</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:user</span><span style="background-color: #f8f8f8">]))</span>
</code></pre></div>
<p><code>JSON.parse</code> returns an ordinary Ruby <code>Hash</code> rather than an instance of <code>ActionController::Parameters</code>. With strong_parameters, the default behavior is to allow instances of <code>Hash</code> to set any model attribute via mass assignment. The same issue occurs if you use <code>params</code> from a Sinatra app when accessing an ActiveRecord model &ndash; Sinatra will not wrap the Hash in an instance of <code>ActionController::Parameters</code>.</p>

<p><strong>Best Practice:</strong> Rely on Rails&rsquo; out-of-the-box parsing whenever possible When combining ActiveRecord models with other web frameworks (or deserializing data from caches, queues, etc.) wrap input in <code>ActionController::Parameters</code> so that strong_parameters works.</p>

<p><strong>The Fix:</strong> It&rsquo;s unclear what the best way for Rails to deal with this is. Rails could override deserialization methods like <code>JSON.parse</code> to return instances of <code>ActionController::Parameters</code> but that is relatively invasive and could cause compatibility issues.</p>

<p>A concerned developer could combine strong<em>parameters with `attr</em>accessible<code>for highly sensitive fields (like</code>User#admin`) for extra protection, but that is likely overkill for most situations. In the end, this may just be a behavior we need to be aware of and look out for.</p>

<p><strong>Update:</strong> If you&rsquo;ve made it all the way here and want to learn more about Rails security, check out our <a href="http://railssecurity.com/">free, 1-month Rails security email course</a>.</p>

<p><em>Hat tip to Brendon Murphy for making me aware of this issue.</em></p>

<p><em>Thanks to Adam Baldwin, Justin Collins, Neil Matatell, Noah Davis and Aaron Patterson for reviewing this article.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Launching Today: Security Monitor by Code Climate</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/launching-today-security-monitor-by-code-climate/"/>
    <id>https://codeclimate.com/blog/launching-today-security-monitor-by-code-climate/</id>
    <updated>2013-03-19T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><strong>Today we&rsquo;re very excited to publicly launch our new <a href="https://codeclimate.com/security-monitor">Security Monitor</a> feature!</strong> It&rsquo;s our next step in bringing you clear, timely and actionable information from your codebase.</p>

<p><a href="https://codeclimate.com/security-monitor"><img src="https://d341kum51qu34d.cloudfront.net/images/posts/sec-dash-419087c0.jpg" alt="Security Monitor dashboard" /></a></p>

<p>Security Monitor regularly scans your Rails apps and lets your team know as soon as new potential vulnerabilities are found. <strong>It keeps your app and data safe by catching common security issues code before they reach production.</strong></p>

<p>Some large organizations employ security specialists to review every commit before they go live, but many teams can&rsquo;t afford that cost and the slowdown on their release cycles. Security Monitor gives you a second set of eyes on every commit &ndash; eyes that are well trained to spot common Rails security issues &ndash; but much faster and at a fraction of the cost.</p>

<p><em>(We love security experts, we just think their time is better spent on the hard security problems rather than common, easily detectible issues.)</em></p>

<h2>Code Climate keeps getting better</h2>

<p>We&rsquo;ve been astonished and humbled by the growth of Code Climate over the past year. What began as a simple project to make static analysis easy for Ruby projects has grown into much more than that. The praise has been overwhelming:</p>

<blockquote>
<p>&ldquo;I&rsquo;ve only been using Code Climate for about 10 minutes and it&rsquo;s already become one of the most useful tools we have access to.&rdquo; —Ryan Kee</p>
</blockquote>

<p>Every day we work to make the product even better for our customers. Since we&rsquo;ve launched, we&rsquo;ve added things like:</p>

<ul>
<li>Easy-to-understand A-F ratings for each class and Quality GPAs</li>
<li>Class Compare view for identifying exactly what changed</li>
<li>Quality alerts and totally new weekly summary emails</li>
<li>Trends charts and churn metrics</li>
<li>GitHub, Pivotal Tracker, and Lighthouse integration</li>
</ul>

<p><strong>Now that Security Monitor is out the door, the next big feature we are working on is Branch Testing.</strong>  Soon, you&rsquo;ll be able to easily see the quality changes and new security risks of every feature branch and pull request <em>before</em> they get merged into master.</p>

<h2>Changes to our pricing</h2>

<p>Our current plans have been in place for over a year, and the product has changed tremendously in that time. We believe (and we&rsquo;ve been told many times) that Code Climate is much more valuable today than it was when started.</p>

<p>Additionally, Security Monitor has proven to be incredibly valuable to teams looking for help trying to catch risky code before it makes its way into production. We wouldn&rsquo;t be able to offer it on all plans, so we&rsquo;re making some changes.</p>

<p>Today we&rsquo;re rolling out new plans for private accounts:</p>

<p><a href="https://codeclimate.com/pricing"><img src="https://d341kum51qu34d.cloudfront.net/images/posts/new_pricing-905ac4f8.png" alt="New Plans and Pricing" /></a></p>

<p>I&rsquo;d like to address some common questions&hellip;</p>

<h3>I&rsquo;m a current customer. How does this affect me?</h3>

<p>We love you.  Your support was key to getting Code Climate to this point.  The plan you&rsquo;re currently on isn&rsquo;t changing at all, and won&rsquo;t for at least two years.</p>

<p>Also, we think if you&rsquo;re running Rails in a commercial capacity you&rsquo;d strongly benefit from upgrading to our Team plan, which has the Security Monitor feature we talked about above.</p>

<p><strong>To make that a no-brainer decision for you, we&rsquo;ll comp you $25 a month for the next two years if you upgrade to a Team, Company or Enterprise plan before April 2nd.</strong> Look for an email with a link to upgrade arriving today (Tuesday, March 19th).</p>

<p>Also, <strong>big new features like Branch/Pull Request Testing will only be available on the new plans, upgrade now to avoid missing out on this big, one-time discount.</strong></p>

<h3>I&rsquo;m on the fence about Code Climate. What should I do?</h3>

<p>To make it easy for you to get off the fence, we&rsquo;re extending a discount of $25/month for the next two years ($600 value) if you start a free trial before April 2nd. <strong>Now is the best time to <a href="https://codeclimate.com/pricing">start a free trial</a> and lock in that discount.</strong></p>

<h3>Why charge per user?</h3>

<p>Ultimately, it is best for you guys, our customers, if our pricing creates a vibrant, sustainable company that can be here for the long haul and improving Code Climate so that it continues to create massive value for your businesses.</p>

<p>Within that overarching goal, we&rsquo;d like our pricing to scale with customer success: we&rsquo;d like entry-level users to be able to get started without sacrificing too much ramen and for extraordinarily successful software companies to pay appropriately given the value Code Climate creates for them.</p>

<p>It turns out that per-repository pricing doesn&rsquo;t necessarily proxy customer success all that well: Google, for example, is rumored to have a grand total of <em>one</em> Perforce repository.  Many smaller teams (like the good folks at Travis CI) have dozens, given that Git encourages a one-repo-per-project workflow.  To more appropriately balance prices between small teams and the Google&rsquo;s of the world (not technically a customer yet but hey, Larry, call me), we&rsquo;re adding a per-user component to pricing.</p>

<p>This largely affects larger commercial enterprises which are used to per-seat licensing, have defined budgets for per-employee expenses (like healthcare, training, and equipment, next to which Code Climate is very reasonably priced), and can easily see the substantial business value created by lowering software maintenance costs, keeping projects on track, and reducing security risk.</p>

<p>It also lets us invest substantially in development operations to support new features like Security Monitor which are most critically needed by larger teams, while keeping the basic Code Climate offering available and reasonably priced for all teams and 100% free for open source projects.</p>

<h3>I&rsquo;m a student or non-profit. Can you help?</h3>

<p>Yes. We now offer <a href="https://codeclimate.com/edu">educational</a> and <a href="https://codeclimate.com/nonprofit">non-profit</a> discounts to qualifying people and organizations. We&rsquo;re interested in supporting you.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Code Climate now hosts over 5,000 Open Source, Ruby projects</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-climate-now-hosts-over-5000-open-source-ruby-projects/"/>
    <id>https://codeclimate.com/blog/code-climate-now-hosts-over-5000-open-source-ruby-projects/</id>
    <updated>2013-02-18T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Code Climate hit an exciting milestone last week: <strong>in the seven months since we launched our free OSS service we’ve added <a href="https://codeclimate.com/explore">5,000 Ruby projects</a></strong>. Code Climate is built on open source software, so we’re especially thrilled for the service to be adopted by the community.</p>

<p>We’re also incredibly grateful to our hosting partners Blue Box whose support makes it possible to provide this service free for OSS! <a href="https://bluebox.net">Blue Box</a> has provided us great uptime, dependable monitoring and support, and help planning for our continued growth. I definitely encourage everyone to check them  out. Thanks guys!</p>

<p>Code quality can be especially important for OSS because there are many contributors involved. We try to make it easy to monitor overall quality by providing projects with a “Quality GPA” calculated by aggregating the ratings for each class, weighted by lines of code, into an average from 0 to 4.0.</p>

<p><strong>Fun fact: The average open source project on Code Climate has a GPA of 3.6</strong> – which we thinks speaks volumes about the culture of quality in the Ruby open source community.  Andy Lindeman, project lead for <a href="https://github.com/rspec/rspec-rails">rspec-rails</a>, explained:</p>

<blockquote>
<p>Code Climate helps keep both the core team and contributors accountable since we display the GPA
badge at the top of the READMEs. The GPA is useful in finding pieces of code that would benefit from a refactor or redesign, and the feed of changes (especially when things &ldquo;have gotten worse&rdquo;) is useful to nip small problems before they become big problems.</p>
</blockquote>

<p>Erik Michaels-Ober also uses Code Climate for his many RubyGems and noted, &ldquo;I spent one day refactoring the <a href="https://github.com/sferik/twitter">Twitter gem</a> with Code Climate and it dramatically reduced the complexity and duplication in the codebase. If you maintain an open source project, there&rsquo;s no excuse not to use it.&rdquo;</p>

<p><strong>Curious about your project’s GPA?</strong> Just provide the name of the repo on the <a href="https://codeclimate.com/github/signup">Add GitHub Repository page</a>. Code Climate will clone the project, analyze it, and shoot you an email when the metrics are ready - all in a couple of minutes. Once you&rsquo;ve added your project, you can show off your code&rsquo;s GPA by adding a dynamic badge (designed by Oliver Lacan and part of his open source <a href="https://github.com/olivierlacan/shields">shields project</a>) to your project&rsquo;s README or site.</p>

<p>Here’s to the next 5,000 projects!</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Rails' Remote Code Execution Vulnerability Explained</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/"/>
    <id>https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/</id>
    <updated>2013-01-10T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>We interrupt our regularly scheduled code quality content to raise awareness about a recently-disclosed, critical security vulnerability in Rails.</em></p>

<p>On Tuesday, a <a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ">vulnerability</a> was patched in Rails&rsquo; Action Pack layer that allows for remote code execution. Since then, a number of proof of concepts have been publicly posted showing exactly how to exploit this issue to trick a remote server into running an attacker&rsquo;s arbitrary Ruby code.</p>

<p>This post is an attempt to document the facts, raise awareness, and drive organizations to protect their applications and data immediately. Given the presence of automated attack tools, mass scanning for vulnerable applications is likely already in progress.</p>

<h3>Vulnerability Summary</h3>

<p>An attacker sends a specially crafted XML request to the application containing an embedded YAML-encoded object. Rails&rsquo; parses the XML and loads the objects from YAML. In the process, arbitrary Ruby code sent by the attacker may be executed (depending on the type and structure of the injected objects).</p>

<ul>
<li><strong>Threat Agents:</strong> Anyone who is able to make HTTPs request to your Rails application.</li>
<li><strong>Exploitability:</strong> Easy — Proof of concepts in the wild require only the URL of the application to attack a Ruby code payload.</li>
<li><strong>Prevalence:</strong> Widespread — All Rails versions prior to those released on Tuesday are vulnerable.</li>
<li><strong>Detectability:</strong> Easy — No special knowledge of the application is required to test it for the vulnerability, making it simple to perform automated spray-and-pray scans.</li>
<li><strong>Technical Impacts:</strong> Severe — Attackers can execute Ruby (and therefore shell) code at the privilege level of the application process, potentially leading to host takeover.</li>
<li><strong>Business Impacts:</strong> Severe — All of your data could be stolen and your server resources could be used for malicious purposes. Consider the reputation damage from these impacts.</li>
</ul>

<p>Step by step:</p>

<ol>
<li>Rails parses parameters based on the <code>Content-Type</code> of the request. You do not have to be generating XML based responses, calling <code>respond_to</code> or taking any specific action at all for the XML params parser to be used.</li>
<li>The XML params parser (prior to the patched versions) activates the YAML parser for elements with <code>type=&quot;yaml&quot;</code>. Here&rsquo;s a simple example of XML embedding YAML:
    <foo type="yaml">
    yaml: goes here
    foo:
      - 1
      - 2
    </foo></li>
<li>YAML allows the deserialization of arbitrary Ruby objects (providing the class is loaded in the Ruby process at the time of the deserialization), setting provided instance variables.</li>
<li>Because of Ruby&rsquo;s dynamic nature, the YAML deserialization process itself can trigger code execution, including invoking methods on the objects being deserialized.</li>
<li>Some Ruby classes that are present in all Rails apps (e.g. an <code>ERB</code> template) evaluate arbitrary code that is stored in their instance variables (template source, in the case of <code>ERB</code>).</li>
<li>Evaluating arbitrary Ruby code allows for the execution of shell commands, giving the attacked the full privileges of the user running the application server (e.g. Unicorn) process.</li>
</ol>

<p>It&rsquo;s worth noting that any Ruby code which takes untrusted input and processes it with <code>YAML.load</code> is subject to a similar vulnerability (known as &ldquo;object injection&rdquo;). This could include third-party RubyGems beyond Rails, or your own application source code. Now is a good time to check for those cases as well.</p>

<h3>Proof of Concept</h3>

<p><em>At the suggestion of a member of the Rails team who I respect, I&rsquo;ve edited this post to withhold some details about how this vulnerability is being exploited. Please be aware however that full, automated exploits are already in the hands of the bad guys, so do not drag your feet on patching.</em></p>

<p>There are a number of proof of concepts floating around (see the External Links section), but the ones I saw all required special libraries. This is an example based on them with out-of-the-box Ruby (and Rack):</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #999988;font-style: italic"># Copyright (c) 2013 Bryan Helmkamp, Postmodern, GPLv3.0</span>
<span style="color: #0086B3">require</span> <span style="color: #d14">"net/https"</span>
<span style="color: #0086B3">require</span> <span style="color: #d14">"uri"</span>
<span style="color: #0086B3">require</span> <span style="color: #d14">"base64"</span>
<span style="color: #0086B3">require</span> <span style="color: #d14">"rack"</span>

<span style="background-color: #f8f8f8">url</span>   <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">ARGV</span><span style="background-color: #f8f8f8">[</span><span style="color: #009999">0</span><span style="background-color: #f8f8f8">]</span>
<span style="background-color: #f8f8f8">code</span>  <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">File</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">read</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">ARGV</span><span style="background-color: #f8f8f8">[</span><span style="color: #009999">1</span><span style="background-color: #f8f8f8">])</span>

<span style="color: #999988;font-style: italic"># Construct a YAML payload wrapped in XML</span>
<span style="background-color: #f8f8f8">payload</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">&lt;&lt;-</span><span style="color: #008080">PAYLOAD</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">strip</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">gsub</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"</span><span style="color: #d14">\n</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #d14">"&amp;#10;"</span><span style="background-color: #f8f8f8">)</span><span style="color: #d14">
&lt;fail type="yaml"&gt;
--- !ruby/object:ERB
  template:
    src: !binary |-
      </span><span style="color: #d14">#{</span><span style="color: #008080">Base64</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">encode64</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">code</span><span style="background-color: #f8f8f8">)</span><span style="color: #d14">}</span><span style="color: #d14">
&lt;/fail&gt;
</span><span style="color: #008080">PAYLOAD</span>

<span style="color: #999988;font-style: italic"># Build an HTTP request</span>
<span style="background-color: #f8f8f8">uri</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">URI</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">parse</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">url</span><span style="background-color: #f8f8f8">)</span>
<span style="background-color: #f8f8f8">http</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Net</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">HTTP</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">uri</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">host</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">uri</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">port</span><span style="background-color: #f8f8f8">)</span>
<span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">uri</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">scheme</span> <span style="color: #000000;font-weight: bold">==</span> <span style="color: #d14">"https"</span>
  <span style="background-color: #f8f8f8">http</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">use_ssl</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #000000;font-weight: bold">true</span>
  <span style="background-color: #f8f8f8">http</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">verify_mode</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">OpenSSL</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">SSL</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">VERIFY_NONE</span>
<span style="color: #000000;font-weight: bold">end</span>
<span style="background-color: #f8f8f8">request</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Net</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">HTTP</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Post</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">uri</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">request_uri</span><span style="background-color: #f8f8f8">)</span>
<span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"Content-Type"</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"text/xml"</span>
<span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"X-HTTP-Method-Override"</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"get"</span>
<span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">body</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">payload</span>

<span style="color: #999988;font-style: italic"># Print the response</span>
<span style="background-color: #f8f8f8">response</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">http</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">request</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">request</span><span style="background-color: #f8f8f8">)</span>
<span style="color: #0086B3">puts</span> <span style="color: #d14">"HTTP/1.1 </span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">response</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">code</span><span style="color: #d14">}</span><span style="color: #d14"> </span><span style="color: #d14">#{</span><span style="color: #008080">Rack</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Utils</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">HTTP_STATUS_CODES</span><span style="background-color: #f8f8f8">[</span><span style="background-color: #f8f8f8">response</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">code</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_i</span><span style="background-color: #f8f8f8">]</span><span style="color: #d14">}</span><span style="color: #d14">"</span>
<span style="background-color: #f8f8f8">response</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="background-color: #f8f8f8">{</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">header</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">value</span><span style="color: #000000;font-weight: bold">|</span> <span style="color: #0086B3">puts</span> <span style="color: #d14">"</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">header</span><span style="color: #d14">}</span><span style="color: #d14">: </span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">value</span><span style="color: #d14">}</span><span style="color: #d14">"</span> <span style="background-color: #f8f8f8">}</span>
<span style="color: #0086B3">puts</span>
<span style="color: #0086B3">puts</span> <span style="background-color: #f8f8f8">response</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">body</span>
</code></pre></div>
<p>There&rsquo;s not much to it beyond the payload itself. The only interesting detail is the use of the <code>X-Http-Method-Override</code> header which instructs Rails to interpret the POST request as a GET.</p>

<p>Originally reports indicated that the vulnerability could only be used on POST/PUT-accessible endpoints. With this trick, we can send a POST (with an XML body) which the Rails router resolves as a GET. This makes it even easier to exploit because you don&rsquo;t have to identify a POST-accessible URL for each application.</p>

<h3>How It Works</h3>

<p>Knowing that Rails will <code>YAML.load</code> the payload, the only difficulty is building a tree of objects that, when deserialized, executes arbitrary Ruby code in the payload. The object graph must be constructed using only classes that are present in the process.</p>

<p>This proof of concept uses <code>ERB</code>, a Ruby object that conveniently is designed to hold Ruby code in its <code>@src</code> instance variable, and execute it when <code>#result</code> is called. The only thing missing is triggering the <code>#result</code> call. Suffice it to say, a slighlty more complex YAML payload can achieve this. I&rsquo;ve decided to omit the exact specifics here, but I&rsquo;m aware of two vectors:</p>

<ul>
<li>Ruby&rsquo;s YAML parser calls <code>#init_with</code>, a hook that objects can define to control YAML deserialization. So any class that defines <code>#init_with</code> and also calls methods on its own instance variables in it could be leveraged to trigger a call into the malicious code.</li>
<li>Ruby&rsquo;s YAML parser can also trigger the invokation of the <code>#[]=</code> (hash setter) method on objects it is building, so objects that take dangerous action based on assigned hash values are also exploitable.</li>
</ul>

<h3>Assessment</h3>

<p>With the app source, check for the presence of an affected Rails version and the absence of a workaround. Assessing vulnerability without source code access is slightly more complex but still easy. By sending in payloads and checking the server&rsquo;s response, you can detect if the application seems to be performing YAML deserialization of params.</p>

<p>For example, Metasploit now includes a <a href="https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb">scanner</a> that sends two requests, one with a valid YAML object and one with an invalid YAML. If the server responds differently (for example, if it returns a 500 for the invalud YAML only), it is likely deserializing the YAML and vulnerable.</p>

<h3>Mitigation</h3>

<p>The simplest fix is to upgrade to a patched Rails releases: 3.2.11, 3.1.10, 3.0.19 or 2.3.15. If you cannot upgrade immediately, consider applying one of the <a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ">published patches</a>.</p>

<p>Workarounds exist for Rails 2.3 and above to disable the dangerous functionality from an initializer without requiring a Rails upgrade. You can find them in the <a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ">official disclosure</a>.</p>

<p>Because of the severity of this issue, if you cannot upgrade or patch your Rails version immediately, consider urgently applying the workaround.</p>

<h3>External Links</h3>

<ul>
<li><a href="https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ">Rails Security Mailing List: Multiple vulnerabilities in parameter parsing in Action Pack (CVE-2013-0156)</a></li>
<li><a href="https://community.rapid7.com/community/metasploit/blog/2013/01/09/serialization-mischief-in-ruby-land-cve-2013-0156">SecurityStreet - Serialization Mischief in Ruby Land (CVE-2013-0156)</a></li>
</ul>

<p><em>Thanks to Adam Baldwin of <a href="http://liftsecurity.io/">Lift Security</a> for reviewing this post.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>DCI, Concerns and Readable Code</title>
    <author>
      <name>Giles</name>
      <uri>https://twitter.com/gilesgoatboy</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/dci-concerns-and-readable-code/"/>
    <id>https://codeclimate.com/blog/dci-concerns-and-readable-code/</id>
    <updated>2012-12-19T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Our latest post comes from Giles Bowkett. Giles recently wrote a book, <a href="http://railsoopbook.com/">Rails As She Is Spoke</a>, which explores Rails&rsquo; take on OOP and its implications. It&rsquo;s an informative and entertaining read, and you should buy it.</em></p>

<p>A few days ago I wrote a blog post arguing that <a href="http://gilesbowkett.blogspot.com/2012/12/rails-developers-should-take-dci.html">rails developers should take DCI seriously</a>. Be careful what you wish for! A tumultuous brouhaha soon ensued on Twitter. I can&rsquo;t necessarily take the credit for that, but I&rsquo;m glad it happened, because one of the people at the center of the cyclone, Rails creator David Heinemeier Hansson, wrote <a href="http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns">a good blog post on <code>ActiveSupport::Concern</code></a>, which included a moment of taking DCI seriously.</p>

<blockquote>
<p>[&hellip;] breaking up domain logic into concerns is similar in some ways to the DCI notion of Roles. It doesn’t have the run-time mixin acrobatics nor does it have the “thy models shall be completely devoid of logic themselves” prescription, but other than that, it’ll often result in similar logic extracted using similar names.</p>
</blockquote>

<p>DCI (data, context, and interaction) is a paradigm for structuring object-oriented code. Its inventor, Trygve Reenskaug, also created MVC, an object-oriented paradigm every Rails developer should be familiar with. <a href="http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby">Most</a> <a href="http://saturnflyer.com/blog/jim/2011/10/04/oop-dci-and-ruby-what-your-system-is-vs-what-your-system-does/">Ruby</a> <a href="http://andrzejonsoftware.blogspot.com/2011/02/dci-and-rails.html">implementations</a> use mixins quite a lot, and there is indeed some similarity there.</p>

<p>However, <a href="http://clean-ruby.com/">there&rsquo;s a lot more to DCI than just mixins</a>, and since I&rsquo;ve already gone into detail about it elsewhere, as have many others, I won&rsquo;t get into that here. I&rsquo;m very much looking forward to <a href="http://twitter.com/andrzejkrzywda/status/279234595537440768">case studies from people who&rsquo;ve used it seriously</a>. Likewise, there are a lot of good reasons to <a href="http://blog.8thlight.com/eric-meyer/2012/11/16/composition-over-mixins.html">feel</a> <a href="https://gist.github.com/4172391">cautious</a> about using <a href="http://twitter.com/srbaker/status/281127692848463872">mixins</a>, either for Rails concerns or for DCI, but that discussion&rsquo;s ongoing and deserves (and is receiving) several blog posts of its own.</p>

<p>What I want to talk about is this argument in Hansson&rsquo;s blog post:</p>

<blockquote>
<p>I find that concerns are often just the right amount of abstraction and that they often result in a friendlier API. I far prefer <code>current_account.posts.visible_to(current_user)</code> to involving a third query object. And of course things like Taggable that needs to add associations to the target object are hard to do in any other way.</p>

<p>It’s true that this will lead to a proliferation of methods on some objects, but that has never bothered me. <strong>I care about how I interact with my code base through the source.</strong></p>
</blockquote>

<p>I added the emphasis to the final sentence because I think it&rsquo;s far more important than most people realize.</p>

<p>To explain, I want to draw an example from <a href="http://railsoopbook.com/">my new book <em>Rails As She Is Spoke</em></a>, which has a silly title but a serious theme, namely the ways in which Rails departs from traditional OOP, and what we can learn from that. The example concerns the familiar method <code>url_for</code>. But I should say &ldquo;methods,&rdquo; because the Rails code base (as of version 3.2) contains five different methods named <code>url_for</code>.</p>

<p>The implementations for most of these methods are hideous, and they make it impossible not to notice the absence of a <code>Url</code> class anywhere in the Rails code base &mdash; a truly bizarre bit of domain logic for a Web framework not to model &mdash; yet these same, hideously constructed methods enable application developers to use a very elegant API:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">url_for</span> <span style="color: #990073">controller: </span><span style="background-color: #f8f8f8">foo</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">action: </span><span style="background-color: #f8f8f8">bar</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">additional: </span><span style="background-color: #f8f8f8">whatnot</span>
</code></pre></div>
<p>Consider again what Hansson said about readable code:</p>

<blockquote>
<p>I care about how I interact with my code base through the source.</p>
</blockquote>

<p>I may be reading too much into a single sentence here, but after years of Rails development, I strongly believe that Rails uses this statement about priorities as an overarching design principle. How else do you explain a Web framework that does not contain a <code>Url</code> class within its own internal domain logic, yet provides incredible conveniences like automated migrations and generators for nearly every type of file you might need to create?</p>

<p>The extraordinary internal implementation of <code>ActiveRecord::Base</code>, and its <a href="https://github.com/rails/rails/blob/deb91690ae0883826950fa2cfb7c23944d7f03de/activerecord/lib/active_record/model.rb#L17-61">extremely numerous modules</a>, bends over backwards to mask all the complexity inherent in instantiating database-mapping objects. It does much, much less work to make its own internal operations easy to understand, or easy to reason about, or easy to subclass, and if you want to cherry-pick functionality from <code>ActiveRecord::Base</code>, your options span a baffling range from effortless to impossible.</p>

<p>Consider a brief quote from <a href="http://svs.io/post/38090231306/param-objects-in-rails">this recent blog post on the <code>params</code> object in Rails controllers</a>:</p>

<blockquote>
<p>In Ruby, everything is an object and this unembarrassed object-orientation gives Ruby much of its power and expressiveness. [&hellip;] In Rails, however, sadly, there are large swathes which are not object oriented, and in my opinion, these areas tend to be the most painful parts of Rails.</p>
</blockquote>

<p>I agree with part of this statement. I think it&rsquo;s fair to say that Ruby takes its object-oriented nature much more seriously than Rails does. I also agree that customizing Rails can be agonizingly painful, whenever you dip below the framework&rsquo;s beautifully polished surface into the deeper realms of its code, which is sometimes object-oriented and sometimes not. But if you look at this API:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">url_for</span> <span style="color: #990073">controller: </span><span style="background-color: #f8f8f8">foo</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">action: </span><span style="background-color: #f8f8f8">bar</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">additional: </span><span style="background-color: #f8f8f8">whatnot</span>
</code></pre></div>
<p>It doesn&rsquo;t look like object-oriented code at all. An object-oriented version would look more like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Url</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:foo</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:bar</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">additional: </span><span style="background-color: #f8f8f8">whatnot</span><span style="background-color: #f8f8f8">)</span>
</code></pre></div>
<p>The API Rails uses looks like Lisp, minus all the aggravating parentheses.</p>
<div class="highlight"><pre class="highlight plaintext"><code>(url_for ((controller, 'foo),
          (action, 'bar),
          (additional, whatnot)))
</code></pre></div>
<p>That API is absolutely not, in my opinion, one of &ldquo;the most painful parts of Rails.&rdquo; It&rsquo;s one of the least painful parts of Rails. I argue in my book that Rails owes a lot of its success to creating a wonderful user experience for developers &mdash; making it the open source equivalent of Apple &mdash; and I think this code is a good example.</p>

<p>Rails disregards object orientation whenever being object-oriented stands in the way of a clean API, and I actually think this is a very good design decision, with one <strong>enormous</strong> caveat: when Rails first debuted, Rails took a very firm position that it was an opinionated framework very highly optimized for one (and <em>only</em> one) particular class of Web application.</p>

<p>If (and <em>only</em> if) every Rails application hews to the same limited range of use cases, and never strays from the same narrow path of limited complexity, then (and <em>only</em> then) it makes perfect sense to prioritize the APIs which developers see over their ability to reason about the domain logic of their applications and of the framework itself.</p>

<p>Unfortunately, the conditions of my caveat do not pertain to the overwhelming majority of Rails apps. This is why Rails 3 abandoned the hard line on opinionated software for a more conciliatory approach, which is to say that Rails is very highly optimized for a particular class of Web application, but sufficiently modular to support other types of Web applications as well.</p>

<p>If you take this as a statement about the characteristics of Rails 3, it&rsquo;s <a href="http://gilesbowkett.blogspot.com/2012/02/rails-went-off-rails-why-im-rebuilding.html">outrageously false</a>, but if you take it as a design goal for Rails 3 and indeed (hopefully) Rails 4, it makes a lot of sense and is a damn good idea.</p>

<p>In this context, finding &ldquo;just the right amount of abstraction&rdquo; requires more than just defining the most readable possible API. It also requires balancing the most readable possible API with the most comprehensible possible domain model. There&rsquo;s an analogy to human writing: you can&rsquo;t just write beautiful sentences and call it a day. If you put beautiful sentences on pages at random, you might have poetry, if you get lucky, but you won&rsquo;t have a story.</p>

<p>This is an area where DCI demolishes concerns, because DCI provides an entire vocabulary for systematic decomposition. If there&rsquo;s any guiding principle for decomposing models with concerns, I certainly don&rsquo;t recall seeing it, ever, even once, in my 7 years as a Rails developer. As far as I can tell the closest thing is: &ldquo;Break the class into multiple files if&hellip;&rdquo;</p>

<ul>
<li>There are too many lines of code.</li>
<li>It&rsquo;s Tuesday.</li>
<li>It&rsquo;s not Tuesday.</li>
</ul>

<p>DCI gives developers something more fine-grained.</p>

<p>I&rsquo;m not actually a DCI zealot; I&rsquo;m waiting until I&rsquo;ve built an app with DCI and had it running for a while before I make any strident or definitive statements. The Code Climate blog itself featured some <a href="http://codeclimate.com/blog/7-ways-to-decompose-fat-activerecord-models/">alternative solutions to the overburdened models problem</a>, and these solutions emphasize classes over mixins. You could do worse than to follow them to the letter. Other worthwhile alternatives exist as well; there is no silver bullet.</p>

<p>However, Rails concerns are just one way to decompose overburdened models. Concerns are appropriate for some apps and inappropriate for others, and I suspect the same is true of DCI. Either way, if you want to support multiple types of applications, with multiple levels and types of complexity, then making a blanket decision about &ldquo;just the right amount of abstraction&rdquo; is pretty risky, because that decision may in fact function at the wrong level of abstraction itself.</p>

<p>It doesn&rsquo;t take a great deal of imagination to understand that different apps feature different levels of complexity, and you should choose which technique you use for managing complexity based on how much complexity you&rsquo;re going to be managing. <a href="http://en.wikipedia.org/wiki/Burning_Chrome#Reception_and_impact">As William Gibson said, &ldquo;the street finds its own uses for things,&rdquo;</a> and I think most Rails developers use Rails to build apps that are more complex than the apps Rails is optimized for. I&rsquo;ve certainly seen apps where that was true, and in those apps, concerns did not solve the problem.</p>

<p>It&rsquo;s possible this means people should be using Merb instead of Rails, although that train appears to have left the station (and of course <a href="http://instantrimshot.com/">it left the station on Rails</a>).</p>

<p>(PS: You should <a href="http://railsoopbook.com">read my book</a>.)</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Your Objects, the Unix Way</title>
    <author>
      <name>John Pignata</name>
      <uri>https://twitter.com/jpignata</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/your-objects-the-unix-way/"/>
    <id>https://codeclimate.com/blog/your-objects-the-unix-way/</id>
    <updated>2012-11-28T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><em>Today I&rsquo;m thrilled to present a guest post from my friend John Pignata. John is
Director of Engineering Operations at <a href="http://www.groupme.com">GroupMe</a> and
writes a great <a href="http://tx.pignata.com">blog</a> on Ruby software engineering that
you should absolutely check out.</em></p>

<p>In 1964, Doug McIlroy, an engineer at Bell Labs, wrote an internal memo
describing some of his ideas for the Multics operating system. The <a href="http://cm.bell-labs.com/who/dmr/mdmpipe.html">surviving
tenth page</a> summarizes the four
items he felt were most important. The first item on the list reads:</p>

<blockquote>
<p>&ldquo;We should have some ways of coupling programs like [a] garden hose &ndash; screw
in another segment when it becomes necessary to massage data in another way.&rdquo;</p>
</blockquote>

<p>This sentence describes what ultimately became the Unix pipeline: the chaining
together of a set of programs such that the output of one is fed into the next
as input. Every time we run a command like <code>tail -5000 access.log | awk &#39;{print
$4}&#39; | sort | uniq -c</code> we&rsquo;re benefiting from the legacy of McIlroy&rsquo;s garden
hose analogy. The pipeline enables each program to expose a small set of
features and, through the interface of the standard streams, collaborate
with other programs to deliver a larger unit of functionality.</p>

<p>It&rsquo;s mind-expanding when a Unix user figures out how to snap together their
system&rsquo;s various small command-line programs to accomplish tasks. The pipeline
renders each command-line tool more powerful as a stage in a larger operation
than it could have been as a stand-alone utility. We can couple together any
number of these small programs as necessary and build new tools which add
specific features as we need them. We can now speak Unix in compound sentences.</p>

<p>Without the interface of the standard streams to allow programs to collaborate,
Unix systems might have ended up with larger programs with duplicative feature
sets. In Microsoft Windows, most programs tend to be their own closed universes
of functionality. To get word count of a document you&rsquo;re writing on a Unix
system, you&rsquo;d run <code>wc -w document.md</code>. On a system running Windows you&rsquo;d likely
have to boot the entire Microsoft Word application in order to get a word count
of <code>document.docx</code>. The count functionality of Word is locked in the context of
use of editing a Word document.</p>

<p>Just as Unix and Windows are composed of programs as units of functionality,
our systems are composed of objects. When we build chunky, monolithic objects
that wrap huge swaths of procedural code, we&rsquo;re building our own closed
universes of functionality. We&rsquo;re trapping the features we&rsquo;ve built within a
given context of use. Our objects are obfuscating important domain concepts
by hiding them as implementation details.</p>

<p>In coarse-grained systems, each single object fills multiple roles increasing
their complexity and resistance to change. Extending an object&rsquo;s functionality
or swapping out an implementation for another sometimes involves major <a href="http://c2.com/cgi/wiki?ShotgunSurgery">shotgun
surgery</a>. The battle against complexity
is fought within the definition of every object in your system. Fine-grained
systems are composed of objects that are easier to understand, to modify, and
to use.</p>

<p>Some years after that memo, McIlroy summarized
the Unix philosophy as: &ldquo;write programs that do one thing and do it well. Write
programs to work together.&rdquo; Eric Raymond rephrased this in <a href="http://www.catb.org/esr/writings/taoup/html/"><em>The Art of Unix
Programming</em></a> as the
<a href="http://www.catb.org/esr/writings/taoup/html/ch01s06.html#id2877537">Rule of Modularity</a>:
&ldquo;write simple parts connected by clean interfaces.&rdquo; This philosophy is a
powerful strategy to help us manage complexity within our systems. Like Unix,
our systems should consist of many small components each of which are focused
on a specific task and work with each other via their interfaces to accomplish
a larger task.</p>

<h3>Everything But the Kitchen Sink</h3>

<p>Let&rsquo;s look at an example of an object that contains several different features.
The requirement represented in this code is to create an old-school web
guestbook for our home page. For anyone who missed the late nineties, like its
physical analog a web guestbook was a place for visitors to acknowledge a visit
to a web page and to leave public comments for the maintainer.</p>

<p>When we start the project the requirements are straightforward: save a name, an
IP address, and a comment from any visitor that fills out the form and display
those contents in an index view. We scaffold up a controller, generate a
migration, a new model, sprinkle web design in some ERB templates, high five,
and call it a day. This is a Rails system, I know this.</p>

<p>Over time our requirements begin growing and we slowly start adding new
features. First, in real-life operations we realize that spammers are posting
to the form so we want to build a simple spam filter to reject posts containing
certain words. We also realize we want some kind of rate-limiting to prevent
visitors from posting more than one message per day. Finally, we want to post
to Twitter when a visitor signs our guestbook because if we&rsquo;re going to be
anachronistic with our code example, let&rsquo;s get really weird with it.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #0086B3">require</span> <span style="color: #d14">"set"</span>

<span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">GuestbookEntry</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ActiveRecord</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Base</span>
  <span style="color: #008080">SPAM_TRIGGER_KEYWORDS</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">%w(viagra acne adult loans xxx mortgage)</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_set</span>
  <span style="color: #008080">RATE_LIMIT_KEY</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"guestbook"</span>
  <span style="color: #008080">RATE_LIMIT_TTL</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #009999">1</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">day</span>

  <span style="background-color: #f8f8f8">validate</span> <span style="color: #990073">:ensure_content_not_spam</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">on: :create</span>
  <span style="background-color: #f8f8f8">validate</span> <span style="color: #990073">:ensure_ip_address_not_rate_limited</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">on: :create</span>

  <span style="background-color: #f8f8f8">after_create</span> <span style="color: #990073">:post_to_twitter</span>
  <span style="background-color: #f8f8f8">after_create</span> <span style="color: #990073">:record_ip_address</span>

  <span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">ensure_content_not_spam</span>
    <span style="background-color: #f8f8f8">flagged_words</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">SPAM_TRIGGER_KEYWORDS</span> <span style="color: #000000;font-weight: bold">&amp;</span> <span style="color: #008080">Set</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">split</span><span style="background-color: #f8f8f8">)</span>

    <span style="color: #000000;font-weight: bold">unless</span> <span style="background-color: #f8f8f8">flagged_words</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">empty?</span>
      <span style="background-color: #f8f8f8">errors</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:content</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">&lt;&lt;</span> <span style="color: #d14">"Your post has been rejected."</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">ensure_ip_address_not_rate_limited</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">$redis</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">exists</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">RATE_LIMIT_KEY</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">errors</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:base</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">&lt;&lt;</span> <span style="color: #d14">"Sorry, please try again later."</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">post_to_twitter</span>
    <span style="background-color: #f8f8f8">client</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Twitter</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Configuration</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">twitter_options</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">update</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"We had a visitor! </span><span style="color: #d14">#{</span><span style="color: #0086B3">name</span><span style="color: #d14">}</span><span style="color: #d14"> said </span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">first</span><span style="background-color: #f8f8f8">(</span><span style="color: #009999">50</span><span style="background-color: #f8f8f8">)</span><span style="color: #d14">}</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">record_ip_address</span>
    <span style="color: #008080">$redis</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">setex</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"</span><span style="color: #d14">#{</span><span style="color: #008080">RATE_LIMIT_KEY</span><span style="color: #d14">}</span><span style="color: #d14">:</span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">ip_address</span><span style="color: #d14">}</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">RATE_LIMIT_TTL</span><span style="background-color: #f8f8f8">,</span> <span style="color: #d14">"1"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>These features are oversimplified but set that aside for the purposes of this
example. The above code shows us a hodgepodge of entwined features. Like the
Microsoft Word example of the word count feature, the features we&rsquo;ve built are
locked within the context of creating a <code>GuestbookEntry</code>.</p>

<p>This kind of approach has several real-world implications. For one, the tests
for this object likely exercise some of these features in the context of saving
a database object. We don&rsquo;t need to roundtrip to our database in order to
validate that our rate limiting code is working, but since we&rsquo;ve hung it off an
<code>after_create</code> callback that&rsquo;s likely what we might do because that&rsquo;s the
interface our application is using. These tests also likely littered with
unrelated details and setup due to the coupling to unrelated but neighboring
behavior and data.</p>

<p>At a glance it&rsquo;s difficult to untangle which code relates to what feature. When
looking at the code we have to think about at each line to discern which of the
object&rsquo;s behavior that line is principally concerned with. Clear naming helps
us in this example but in a system where each behavior was represented by a
domain object, we&rsquo;d be able to assume that a line of code related to the
object&rsquo;s assigned responsibility.</p>

<p>Lastly, it&rsquo;s easy for us to glance over the fact that we have, for example, the
acorn of a user content spam filter in our system because it&rsquo;s a minor detail
of another object. If this were its own domain concept it would be much
clearer that it was a first-class role within the system.</p>

<h3>Applying the Unix Philosophy</h3>

<p>Let&rsquo;s look at this implementation through the lens of the Rule of Modularity.
The above code fails the &ldquo;simple parts, clean interfaces&rdquo; sniff test. In our
current factoring, we can&rsquo;t extend or change these features without diffusing
more details about them into the <code>GuestbookEntry</code> object. The interface by
which our model uses this behavior through internal callbacks trigged
through the object&rsquo;s lifecycle. There are no external interfaces to these
features despite the fact that each has their own behavior and data. This
object now has several reasons to change.</p>

<p>Let&rsquo;s refactor these features by extracting this behavior to independent
objects to see how these shake out as stand-alone domain concepts.  First we&rsquo;ll
extract the code in our spam check implementation into its own object.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #0086B3">require</span> <span style="color: #d14">"set"</span>

<span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">UserContentSpamChecker</span>
  <span style="color: #008080">TRIGGER_KEYWORDS</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">%w(viagra acne adult loans xrated)</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_set</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@content</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">content</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">spam?</span>
    <span style="background-color: #f8f8f8">flagged_words</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">present?</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">flagged_words</span>
    <span style="color: #008080">TRIGGER_KEYWORDS</span> <span style="color: #000000;font-weight: bold">&amp;</span> <span style="color: #008080">@content</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">split</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Features like this have serious sprawl potential. When we first see the problem
of abuse we&rsquo;re likely we respond with the simplest thing that could work.
There&rsquo;s usually quite a bit of churn in this code as our combatants expose new
weaknesses in our implementation. The rate of change of our spam protection
strategy is inherently different than that of our <code>GuestbookEntry</code> persistence
object. Identifying our <code>UserContentSpamChecker</code> as its own dedicated domain
concept and establishing it as such will allow us to more easily maintain and
extend this functionality independently of where it&rsquo;s being used.</p>

<p>Next we&rsquo;ll extract our rate limiting code. Some small changes are required to
decouple it fully from the guestbook such as the addition of a namespace.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">UserContentRateLimiter</span>
  <span style="color: #008080">DEFAULT_TTL</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #009999">1</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">day</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ip_address</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">namespace</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">options</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">{})</span>
    <span style="color: #008080">@ip_address</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">ip_address</span>
    <span style="color: #008080">@namespace</span>  <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">namespace</span>
    <span style="color: #008080">@ttl</span>        <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">options</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">fetch</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:ttl</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">DEFAULT_TTL</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@redis</span>      <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">options</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">fetch</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">:redis</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">$redis</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">exceeded?</span>
    <span style="color: #008080">@redis</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">exists?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">key</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">record</span>
    <span style="color: #008080">@redis</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">setex</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">key</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">@ttl</span><span style="background-color: #f8f8f8">,</span> <span style="color: #d14">"1"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">key</span>
    <span style="color: #d14">"rate_limiter:</span><span style="color: #d14">#{</span><span style="color: #008080">@namespace</span><span style="color: #d14">}</span><span style="color: #d14">:</span><span style="color: #d14">#{</span><span style="color: #008080">@ip_address</span><span style="color: #d14">}</span><span style="color: #d14">"</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Now that we have a stand-alone domain object, more advanced requirements for
this rate limiting logic will only change this one object. Our tests can
exercise this feature in isolation apart from any potential consumer of its
functionality. This will not only speed up tests, but help future readers of
the code in reading the tests to understand the feature more quickly.</p>

<p>Finally we&rsquo;ll extract our call to the Twitter gem. It&rsquo;s tiny, but there&rsquo;s good
reason to keep it separate from our <code>GuestbookEntry</code>. Since Twitter and the gem
are third-party APIs, we&rsquo;d like to isolate the coupling to an adapter object
that we use to hide the nitty-gritty details of sending a tweet.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Tweeter</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">post</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">update</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">client</span>
    <span style="color: #008080">@client</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="color: #008080">Twitter</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Configuration</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">twitter_options</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Now that we have these smaller components, we can change our <code>GuestbookEntry</code>
object to make use of them. We&rsquo;ll replace the extracted logic with calls to
the objects we&rsquo;ve just created.</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">GuestbookEntry</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ActiveRecord</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Base</span>
  <span style="background-color: #f8f8f8">validate</span> <span style="color: #990073">:ensure_content_not_spam</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">on: :create</span>
  <span style="background-color: #f8f8f8">validate</span> <span style="color: #990073">:ensure_ip_address_not_rate_limited</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">on: :create</span>

  <span style="background-color: #f8f8f8">after_create</span> <span style="color: #990073">:post_to_twitter</span>
  <span style="background-color: #f8f8f8">after_create</span> <span style="color: #990073">:record_ip_address</span>

  <span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">ensure_content_not_spam</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">UserContentSpamChecker</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">spam?</span>
      <span style="background-color: #f8f8f8">errors</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:content</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">&lt;&lt;</span> <span style="color: #d14">"Post rejected."</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">ensure_ip_address_not_rate_limited</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">rate_limiter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">exceeded?</span>
      <span style="background-color: #f8f8f8">errors</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:base</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">&lt;&lt;</span> <span style="color: #d14">"Please try again later."</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">post_to_twitter</span>
    <span style="color: #008080">Tweeter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">post</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"New visitor! </span><span style="color: #d14">#{</span><span style="color: #0086B3">name</span><span style="color: #d14">}</span><span style="color: #d14"> said </span><span style="color: #d14">#{</span><span style="background-color: #f8f8f8">content</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">first</span><span style="background-color: #f8f8f8">(</span><span style="color: #009999">50</span><span style="background-color: #f8f8f8">)</span><span style="color: #d14">}</span><span style="color: #d14">"</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">record_ip_address</span>
    <span style="background-color: #f8f8f8">rate_limiter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">record</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">rate_limiter</span>
    <span style="color: #008080">@rate_limiter</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="color: #008080">UserContentRateLimiter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ip_address</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">:guestbook</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This new version is only a couple of lines shorter than our original
implementation but it knows much less about its constituent parts. Many of the
details of the &ldquo;how&rdquo; these features are implemented have found a dedicated home
in our domain with our model calling those collaborators to accomplish the
larger task of creating a <code>GuestbookEntry</code>. These features are now
independently testable and individually addressable. They are no longer locked
in the context of creating a <code>GuestbookEntry</code>. At the meager cost of a few more
files and some more code we now have simpler objects and a better set of
interfaces. These objects can be changed with less risk of ripple effects and
their interfaces can be called by other objects in the system.</p>

<h3>Wrapping Up</h3>

<blockquote>
<p>&ldquo;Good code invariably has small methods and small objects. I get lots of
resistance to this idea, especially from experienced developers, but no one
thing I do to systems provides as much help as breaking it into more pieces.&rdquo;</p>

<p>&ndash; Kent Beck, <a href="http://www.amazon.com/Smalltalk-Best-Practice-Patterns-Kent/dp/013476904X"><em>Smalltalk Best Practice Patterns</em></a></p>
</blockquote>

<p>The <a href="http://www.catb.org/esr/writings/taoup/html/ch01s06.html">Unix philosophy</a>
illustrates that small components that work together through an interface can
be extraordinarily powerful. Nesting an aspect of your domain as an
implementation detail of a specific model conflates responsibilities, bloats
code, makes tests less isolated and slower, and hides concepts that should be
first-class in your system.</p>

<p>Don&rsquo;t let your domain concepts be shy. Promote them to full-fledged objects to
make them more understandable, isolate and speed up their tests, reduce the
likelihood that changes in neighboring features will have ripple effects, and
provide the concepts a place to evolve apart from the rest of the system. The
only thing we know with certainty about the futures of our systems is that they
will change. We can design our systems to be more amenable to inevitable change
by following the Unix philosophy and building clean interfaces between small
objects that have one single responsibility.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Why Ruby Class Methods Resist&amp;nbsp;Refactoring</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/why-ruby-class-methods-resist-refactoring/"/>
    <id>https://codeclimate.com/blog/why-ruby-class-methods-resist-refactoring/</id>
    <updated>2012-11-14T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>One of the most common questions I received following my <a href="/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/">7 Patterns to Refactor Fat ActiveRecord Models</a> post was <em>&ldquo;Why are you using instances where class methods will do?&rdquo;</em>. I&rsquo;d like to address that. Simply put:</p>

<blockquote>
<p>I prefer object instances to class methods because <strong>class methods resist refactoring</strong>.</p>
</blockquote>

<p>To illustrate, let&rsquo;s look at an example background job for syncing data to a third-party analytics service:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SyncToAnalyticsService</span>
  <span style="color: #008080">ConnectionFailure</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Class</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">StandardError</span><span style="background-color: #f8f8f8">)</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">perform</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">data</span>              <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">symbolize_keys</span>
    <span style="background-color: #f8f8f8">account</span>           <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:account_id</span><span style="background-color: #f8f8f8">])</span>
    <span style="background-color: #f8f8f8">analytics_client</span>  <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Analytics</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">CC</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">config</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:analytics_api_key</span><span style="background-color: #f8f8f8">])</span>

    <span style="background-color: #f8f8f8">account_attributes</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">account_id:         </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_name:       </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">name</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_user_count: </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">count</span>
    <span style="background-color: #f8f8f8">}</span>

    <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">user</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create_or_update</span><span style="background-color: #f8f8f8">({</span>
        <span style="color: #990073">id:             </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
        <span style="color: #990073">email:          </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">email</span><span style="background-color: #f8f8f8">,</span>
        <span style="color: #990073">account_admin:  </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">administered_by?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">}.</span><span style="color: #990000;font-weight: bold">merge</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">))</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">rescue</span> <span style="color: #008080">SocketError</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="background-color: #f8f8f8">ex</span>
    <span style="color: #000000;font-weight: bold">raise</span> <span style="color: #008080">ConnectionFailure</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ex</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">message</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>The job iterates over each user sending a hash of attributes as an HTTP POST. If a <code>SocketError</code> is raised, it gets wrapped as a <code>SyncToAnalyticsService::ConnectionFailure</code>, which ensures it gets categorized properly in our error tracking system.</p>

<p>The <code>SyncToAnalyticsService.perform</code> method is pretty complex. It certainly has multiple responsibilities. The <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility Principle</a> (SRP) can be thought of as fractal, applying at a finer grained level of detail to all of applications, modules, classes and methods. <code>SyncToAnalyticsService.perform</code> is not a <a href="http://c2.com/ppr/wiki/WikiPagesAboutRefactoring/ComposedMethod.html">Composed Method</a> because not all of the operations of the method are at the same level of abstraction.</p>

<p>One solution would be to apply <a href="http://www.refactoring.com/catalog/extractMethod.html">Extract Method</a> a few times. You&rsquo;d end up with something like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SyncToAnalyticsService</span>
  <span style="color: #008080">ConnectionFailure</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Class</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">StandardError</span><span style="background-color: #f8f8f8">)</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">perform</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">data</span>                <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">symbolize_keys</span>
    <span style="background-color: #f8f8f8">account</span>             <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:account_id</span><span style="background-color: #f8f8f8">])</span>
    <span style="background-color: #f8f8f8">analytics_client</span>    <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Analytics</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">CC</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">config</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:analytics_api_key</span><span style="background-color: #f8f8f8">])</span>

    <span style="background-color: #f8f8f8">sync_users</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">sync_users</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">account_attributes</span>  <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">)</span>

    <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">user</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">sync_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">sync_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">create_or_update_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">rescue</span> <span style="color: #008080">SocketError</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="background-color: #f8f8f8">ex</span>
    <span style="color: #000000;font-weight: bold">raise</span> <span style="color: #008080">ConnectionFailure</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ex</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">message</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">create_or_update_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">attributes</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">user_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">merge</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create_or_update</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attributes</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">user_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">id:             </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">email:          </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">email</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_admin:  </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">administered_by?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">account_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">account_id:         </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_name:       </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">name</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_user_count: </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">count</span>
    <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This is a little better the original, but doesn&rsquo;t feel right. It&rsquo;s certainly not object oriented. It feels like a weird hybrid of procedural and functional programming, stuck in an object-based world. Additionally, you can&rsquo;t easily declare the extracted methods <code>private</code> because they are at the class level. (You&rsquo;d have to switch to an ugly <code>class &lt;&lt; self</code> form.)</p>

<p>If I came across the original <code>SyncToAnalyticsService</code> implementation, <strong>I wouldn&rsquo;t be eager to refactor only to end up with the above result.</strong> Instead, suppose we started with this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SyncToAnalyticsService</span>
  <span style="color: #008080">ConnectionFailure</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Class</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">StandardError</span><span style="background-color: #f8f8f8">)</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">perform</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">perform</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@data</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">symbolize_keys</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">perform</span>
    <span style="background-color: #f8f8f8">account</span>           <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@data</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:account_id</span><span style="background-color: #f8f8f8">])</span>
    <span style="background-color: #f8f8f8">analytics_client</span>  <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Analytics</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">CC</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">config</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:analytics_api_key</span><span style="background-color: #f8f8f8">])</span>

    <span style="background-color: #f8f8f8">account_attributes</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">account_id:         </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_name:       </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">name</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_user_count: </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">count</span>
    <span style="background-color: #f8f8f8">}</span>

    <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">user</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create_or_update</span><span style="background-color: #f8f8f8">({</span>
        <span style="color: #990073">id:             </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
        <span style="color: #990073">email:          </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">email</span><span style="background-color: #f8f8f8">,</span>
        <span style="color: #990073">account_admin:  </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">administered_by?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
      <span style="background-color: #f8f8f8">}.</span><span style="color: #990000;font-weight: bold">merge</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">))</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">rescue</span> <span style="color: #008080">SocketError</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="background-color: #f8f8f8">ex</span>
    <span style="color: #000000;font-weight: bold">raise</span> <span style="color: #008080">ConnectionFailure</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ex</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">message</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Almost identical, but this time the functionality is in an instance method rather than a class method. Again, applying Extract Method we might end up with something like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SyncToAnalyticsService</span>
  <span style="color: #008080">ConnectionFailure</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Class</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">StandardError</span><span style="background-color: #f8f8f8">)</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">perform</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">perform</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@data</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">data</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">symbolize_keys</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">perform</span>
    <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">user</span><span style="color: #000000;font-weight: bold">|</span>
      <span style="background-color: #f8f8f8">create_or_update_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">rescue</span> <span style="color: #008080">SocketError</span> <span style="color: #000000;font-weight: bold">=&gt;</span> <span style="background-color: #f8f8f8">ex</span>
    <span style="color: #000000;font-weight: bold">raise</span> <span style="color: #008080">ConnectionFailure</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">ex</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">message</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

<span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create_or_update_user</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">attributes</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">user_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">merge</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">account_attributes</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">analytics_client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create_or_update</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">attributes</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">user_attributes</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">id:             </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">email:          </span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">email</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_admin:  </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">administered_by?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">account_attributes</span>
    <span style="color: #008080">@account_attributes</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="background-color: #f8f8f8">{</span>
      <span style="color: #990073">account_id:         </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_name:       </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">name</span><span style="background-color: #f8f8f8">,</span>
      <span style="color: #990073">account_user_count: </span><span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">count</span>
    <span style="background-color: #f8f8f8">}</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">analytics_client</span>
    <span style="color: #008080">@analytics_client</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="color: #008080">Analytics</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Client</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">CC</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">config</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:analytics_api_key</span><span style="background-color: #f8f8f8">])</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">account</span>
    <span style="color: #008080">@account</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@data</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:account_id</span><span style="background-color: #f8f8f8">])</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Instead of adding class methods that have to pass around intermediate variables to get work done, we have methods like <code>#account_attributes</code> which memoize their results. I love this technique. When breaking down a method, extracting intermediate variables as memoized accessors is one of my favorite refactorings. <em>The class didn&rsquo;t start with any state, but as it was decomposed it was helpful to add some.</em></p>

<p>The result feels much cleaner to me. Refactoring to this feels like a clear win. There is now state and logic encapsulated together in an object. It&rsquo;s easier to test because you can separate the creation of the object (<em>Given</em>) from the invokation of the action (<em>When</em>). And we&rsquo;re not passing variables like the <code>Account</code> and <code>Analytics::Client</code> around everywhere.</p>

<p>Also, every piece of code that uses this logic won&rsquo;t be coupled to the (global) class name. You can&rsquo;t easily swap in new a class, but you can easily swap in a new instance. This encourages building up additional behavior with composition, rather than needing to re-open and expand classes for every change.</p>

<p><em>Refactoring note:</em> I&rsquo;d probably leave this class implemented as the last source listing shows. However, if the logic becomes more complex, this job is begging for a class to sync a single user to be split out.</p>

<p>So how does this relate to the premise of this article? <strong>I&rsquo;m unlikely to see the opportunities for refactoring a class method because decomposing them produces ugly code.</strong> Starting with the instance form makes your refactoring options clear, and reduces friction to taking action on them. I&rsquo;ve observed this effect many times in my own coding and also anecdotally across many Ruby teams over the years.</p>

<h2>Objections</h2>

<h4>YAGNI (You Aren&rsquo;t Going To Need It)</h4>

<p>YANGI is an important principle, but misapplied in this case. If you open these classes in your editor, neither form is more or less complicated than the other. <strong>Saying &ldquo;YAGNI an object here&rdquo; is sort of like saying &ldquo;YAGNI to indent with two spaces instead of a single tab.&rdquo;</strong> The variants are only different stylistically. Applying YAGNI to object oriented design only make sense if there&rsquo;s a difference in understandability (e.g. using one class versus two).</p>

<h4>It Uses an Extra Object</h4>

<p>Some people object on the basis that the instance form creates an additional object. That&rsquo;s true, but in practice it doesn&rsquo;t matter. Rails requests and background jobs create thousands upon thousands of Ruby objects. Optimizing object creation to lessen the stress on the Ruby garbage collector is a legitimate technique, but do it where it counts. You can only find out where it counts by measuring. It&rsquo;s inconceivable that the single additional object that the instance variant creates will have a measurable impact on the performance of your system. (If you have a counter example with data, I&rsquo;d love to hear about it.)</p>

<h4>It&rsquo;s Cumbersome to Call</h4>

<p>Finally, some object that it is just easier to type:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">Job</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">perform</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">args</span><span style="background-color: #f8f8f8">)</span>
<span style="color: #999988;font-style: italic">#  vs.</span>
<span style="color: #008080">Job</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">args</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">perform</span>
</code></pre></div>
<p>That is true. In that case I simply define a convenience class method that builds the object and delegates down. In fact, that is one of the few cases I think class methods are okay. You can have your cake and eat it too, in this regard.</p>

<h2>Wrapping Up</h2>

<p>Begin with an object instance, even if it doesn&rsquo;t have state or multiple methods right away. If you come back to change it later, you (and your team) will be more likely to refactor. If it never changes, the difference between the class method approach and the instance is negligible, and you certainly won&rsquo;t be any worse off.</p>

<p>There are very few cases where I am comfortable with class methods in my code. They are either convenience methods, wrapping the act of initializing an instance and invoking a method on it, or <em>extremely</em> simple factory methods (no more than two lines), to allow collaborators to more easily construct objects.</p>

<p>What do you think? Which form do you prefer and why? Are there any pros/cons that I missed? Post a comment and let me know what you think!</p>

<p>P.S. If this sort of thing interests you, and you want to read more articles like it, you might like the Code Climate newsletter (see below). It&rsquo;s just one email a month, and includes content about refactoring and object design with a Ruby focus.</p>

<h2>Further Reading</h2>

<ul>
<li><a href="http://nicksda.apotomo.de/2011/07/are-class-methods-evil/">Are class methods evil?</a></li>
<li><a href="http://mlomnicki.com/programming/ruby/2011/07/20/class-vs-instance-methods.html">Class vs instance methods</a></li>
</ul>

<p><em>Thanks to Doug Cole, Don Morrison and Josh Susser for reviewing this post.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>7 Patterns to Refactor Fat ActiveRecord&amp;nbsp;Models</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/7-ways-to-decompose-fat-activerecord-models/"/>
    <id>https://codeclimate.com/blog/7-ways-to-decompose-fat-activerecord-models/</id>
    <updated>2012-10-17T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>When teams use <a href="http://codeclimate.com/">Code Climate</a> to improve the quality of their Rails applications, they learn to break the habit of allowing models to get fat. <em>&ldquo;Fat models&rdquo;</em> cause maintenance issues in large apps. Only incrementally better than cluttering controllers with domain logic, they usually represent a failure to apply the <a href="http://www.objectmentor.com/resources/articles/srp.pdf">Single Responsibility Principle</a> (SRP). &ldquo;Anything related to what a user does&rdquo; is not a <em>single</em> responsibility.</p>

<p>Early on, SRP is easier to apply. ActiveRecord classes handle persistence, associations and not much else. But bit-by-bit, they grow. Objects that are inherently responsible for persistence become the <em>de facto</em> owner of all business logic as well. And a year or two later you have a <code>User</code> class with over 500 lines of code, and hundreds of methods in it&rsquo;s <em>public</em> interface. Callback hell ensues.</p>

<p>As you add more intrinsic complexity (read: features!) to your application, the goal is to spread it across a coordinated set of small, encapsulated objects (and, at a higher level, modules) just as you might spread cake batter across the bottom of a pan. Fat models are like the big clumps you get when you first pour the batter in. Refactor to break them down and spread out the logic evenly. Repeat this process and you&rsquo;ll end up with a set of simple objects with well defined interfaces working together in a veritable symphony.</p>

<p>You may be thinking:</p>

<blockquote>
<p><strong>&ldquo;But Rails makes it really hard to do OOP right!&rdquo;</strong></p>
</blockquote>

<p>I used to believe that too. But after some exploration and practice, I realized that Rails (the framework) doesn&rsquo;t impede OOP all that much. It&rsquo;s the Rails &ldquo;conventions&rdquo; that don&rsquo;t scale, or, more specifically, the lack of conventions for managing complexity beyond what the <a href="http://martinfowler.com/eaaCatalog/activeRecord.html">Active Record pattern</a> can elegantly handle. Fortunately, we can apply OO-based principles and best practices where Rails is lacking.</p>

<p><a id="no-mixins"></a></p>

<h2>Don&rsquo;t Extract Mixins from Fat Models</h2>

<p>Let&rsquo;s get this out of the way. I discourage pulling sets of methods out of a large ActiveRecord class into &ldquo;concerns&rdquo;, or modules that are then mixed in to only one model. I once heard someone say:</p>

<blockquote>
<p>&ldquo;Any application with an <code>app/concerns</code> directory is concerning.&rdquo;</p>
</blockquote>

<p>And I agree. <em>Prefer composition to inheritance.</em> Using mixins like this is akin to &ldquo;cleaning&rdquo; a messy room by dumping the clutter into six separate junk drawers and slamming them shut. Sure, it looks cleaner at the surface, but the junk drawers actually make it harder to identify and implement the decompositions and extractions necessary to clarify the domain model.</p>

<p>Now on to the refactorings!</p>

<p><a id="value-objects"></a></p>

<h2>1. Extract Value Objects</h2>

<p><a href="http://c2.com/cgi/wiki?ValueObject">Value Objects</a> are simple objects whose equality is dependent on their value rather than an identity. They are usually immutable. <code>Date</code>, <code>URI</code>, and <code>Pathname</code> are examples from Ruby&rsquo;s standard library, but your application can (and almost certainly should) define domain-specific Value Objects as well. Extracting them from ActiveRecords is low hanging refactoring fruit.</p>

<p>In Rails, Value Objects are great when you have an attribute or small group of attributes that have logic associated with them. Anything more than basic text fields and counters are candidates for Value Object extraction.</p>

<p>For example, a text messaging application I worked on had a <code>PhoneNumber</code> Value Object. An e-commerce application needs a <code>Money</code> class.  Code Climate has a Value Object named <code>Rating</code> that represents a simple A - F grade that each class or module receives. I could (and originally did) use an instance of a Ruby <code>String</code>, but <code>Rating</code> allows me to combine behavior with the data:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Rating</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">Comparable</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #445588;font-weight: bold">self</span><span style="color: #000000;font-weight: bold">.</span><span style="color: #990000;font-weight: bold">from_cost</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">cost</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">cost</span> <span style="color: #000000;font-weight: bold">&lt;=</span> <span style="color: #009999">2</span>
      <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"A"</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">elsif</span> <span style="background-color: #f8f8f8">cost</span> <span style="color: #000000;font-weight: bold">&lt;=</span> <span style="color: #009999">4</span>
      <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"B"</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">elsif</span> <span style="background-color: #f8f8f8">cost</span> <span style="color: #000000;font-weight: bold">&lt;=</span> <span style="color: #009999">8</span>
      <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"C"</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">elsif</span> <span style="background-color: #f8f8f8">cost</span> <span style="color: #000000;font-weight: bold">&lt;=</span> <span style="color: #009999">16</span>
      <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"D"</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"F"</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">letter</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@letter</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">letter</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">better_than?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">other</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #0086B3">self</span> <span style="color: #000000;font-weight: bold">&gt;</span> <span style="background-color: #f8f8f8">other</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">&lt;</span><span style="color: #000000;font-weight: bold">=&gt;</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">other</span><span style="background-color: #f8f8f8">)</span>
    <span style="background-color: #f8f8f8">other</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_s</span> <span style="color: #000000;font-weight: bold">&lt;=&gt;</span> <span style="color: #0086B3">to_s</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">hash</span>
    <span style="color: #008080">@letter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">hash</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">eql?</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">other</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #0086B3">to_s</span> <span style="color: #000000;font-weight: bold">==</span> <span style="background-color: #f8f8f8">other</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_s</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">to_s</span>
    <span style="color: #008080">@letter</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_s</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Every <code>ConstantSnapshot</code> then exposes an instance of <code>Rating</code> in its public interface:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">ConstantSnapshot</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ActiveRecord</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Base</span>
  <span style="color: #999988;font-style: italic"># …</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">rating</span>
    <span style="color: #008080">@rating</span> <span style="color: #000000;font-weight: bold">||=</span> <span style="color: #008080">Rating</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">from_cost</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">cost</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Beyond slimming down the ConstantSnapshot class, this has a number of advantages:</p>

<ul>
<li>The <code>#worse_than?</code> and <code>#better_than?</code> methods provide a more expressive way to compare ratings than Ruby&rsquo;s built-in operators (e.g. <code>&lt;</code> and <code>&gt;</code>).</li>
<li>Defining <code>#hash</code> and <code>#eql?</code> makes it possible to use a <code>Rating</code> as a hash key. Code Climate uses this to idiomatically group constants by their ratings using <code>Enumberable#group_by</code>.</li>
<li>The <code>#to_s</code> method allows me to interpolate a <code>Rating</code> into a string (or template) without any extra work.</li>
<li>The class definition provides a convenient place for a factory method, returning the correct <code>Rating</code> for a given &ldquo;remediation cost&rdquo; (the estimated time it would take to fix all of the smells in a given class).</li>
</ul>

<p><a id="service-objects"></a></p>

<h2>2. Extract Service Objects</h2>

<p>Some actions in a system warrant a Service Object to encapsulate their operation. I reach for Service Objects when an action meets one or more of these criteria:</p>

<ul>
<li>The action is complex (e.g. closing the books at the end of an accounting period)</li>
<li>The action reaches across multiple models (e.g. an e-commerce purchase using <code>Order</code>, <code>CreditCard</code> and <code>Customer</code> objects)</li>
<li>The action interacts with an external service (e.g. posting to social networks)</li>
<li>The action is not a core concern of the underlying model (e.g. sweeping up outdated data after a certain time period).</li>
<li>There are multiple ways of performing the action (e.g. authenticating with an access token or password). This is the Gang of Four <a href="http://en.wikipedia.org/wiki/Strategy_pattern">Strategy pattern</a>.</li>
</ul>

<p>As an example, we could pull a <code>User#authenticate</code> method out into a <code>UserAuthenticator</code>:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">UserAuthenticator</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">user</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">authenticate</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">unencrypted_password</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #000000;font-weight: bold">return</span> <span style="color: #000000;font-weight: bold">false</span> <span style="color: #000000;font-weight: bold">unless</span> <span style="color: #008080">@user</span>

    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">BCrypt</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Password</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">@user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">password_digest</span><span style="background-color: #f8f8f8">)</span> <span style="color: #000000;font-weight: bold">==</span> <span style="background-color: #f8f8f8">unencrypted_password</span>
      <span style="color: #008080">@user</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="color: #000000;font-weight: bold">false</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>And the <code>SessionsController</code> would look like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SessionsController</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ApplicationController</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create</span>
    <span style="background-color: #f8f8f8">user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">User</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">where</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">email: </span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:email</span><span style="background-color: #f8f8f8">]).</span><span style="color: #990000;font-weight: bold">first</span>

    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">UserAuthenticator</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">).</span><span style="color: #990000;font-weight: bold">authenticate</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:password</span><span style="background-color: #f8f8f8">])</span>
      <span style="color: #0086B3">self</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">current_user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">user</span>
      <span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">dashboard_path</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">flash</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:alert</span><span style="background-color: #f8f8f8">]</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #d14">"Login failed."</span>
      <span style="background-color: #f8f8f8">render</span> <span style="color: #d14">"new"</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p><a id="form-objects"></a></p>

<h2>3. Extract Form Objects</h2>

<p>When multiple ActiveRecord models might be updated by a single form submission, a Form Object can encapsulate the aggregation. This is far cleaner than using <a href="http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html"><code>accepts_nested_attributes_for</code></a>, which, in my humble opinion, should be deprecated. A common example would be a signup form that results in the creation of both a <code>Company</code> and a <code>User</code>:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">Signup</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">Virtus</span>

  <span style="color: #000000;font-weight: bold">extend</span> <span style="color: #008080">ActiveModel</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Naming</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">ActiveModel</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Conversion</span>
  <span style="color: #000000;font-weight: bold">include</span> <span style="color: #008080">ActiveModel</span><span style="color: #000000;font-weight: bold">::</span><span style="color: #008080">Validations</span>

  <span style="color: #0086B3">attr_reader</span> <span style="color: #990073">:user</span>
  <span style="color: #0086B3">attr_reader</span> <span style="color: #990073">:company</span>

  <span style="background-color: #f8f8f8">attribute</span> <span style="color: #990073">:name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">String</span>
  <span style="background-color: #f8f8f8">attribute</span> <span style="color: #990073">:company_name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">String</span>
  <span style="background-color: #f8f8f8">attribute</span> <span style="color: #990073">:email</span><span style="background-color: #f8f8f8">,</span> <span style="color: #008080">String</span>

  <span style="background-color: #f8f8f8">validates</span> <span style="color: #990073">:email</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">presence: </span><span style="color: #000000;font-weight: bold">true</span>
  <span style="color: #999988;font-style: italic"># … more validations …</span>

  <span style="color: #999988;font-style: italic"># Forms are never themselves persisted</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">persisted?</span>
    <span style="color: #000000;font-weight: bold">false</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">save</span>
    <span style="color: #000000;font-weight: bold">if</span> <span style="background-color: #f8f8f8">valid?</span>
      <span style="background-color: #f8f8f8">persist!</span>
      <span style="color: #000000;font-weight: bold">true</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="color: #000000;font-weight: bold">false</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>

<span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">persist!</span>
    <span style="color: #008080">@company</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Company</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create!</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">name: </span><span style="background-color: #f8f8f8">company_name</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">@company</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">users</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">create!</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">name: </span><span style="color: #0086B3">name</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">email: </span><span style="background-color: #f8f8f8">email</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>I&rsquo;ve started using <a href="https://github.com/solnic/virtus">Virtus</a> in these objects to get ActiveRecord-like attribute functionality. The Form Object quacks like an ActiveRecord, so the controller remains familiar:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">SignupsController</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ApplicationController</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create</span>
    <span style="color: #008080">@signup</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Signup</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:signup</span><span style="background-color: #f8f8f8">])</span>

    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">@signup</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">save</span>
      <span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">dashboard_path</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">render</span> <span style="color: #d14">"new"</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This works well for simple cases like the above, but if the persistence logic in the form gets too complex you can combine this approach with a Service Object. As a bonus, since validation logic is often contextual, it can be defined in the place exactly where it matters instead of needing to guard validations in the ActiveRecord itself.</p>

<p><a id="query-objects"></a></p>

<h2>4. Extract Query Objects</h2>

<p>For complex SQL queries littering the definition of your ActiveRecord subclass (either as scopes or class methods), consider extracting query objects. Each query object is responsible for returning a result set based on business rules. For example, a Query Object to find abandoned trials might look like this:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">AbandonedTrialQuery</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">relation</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">scoped</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@relation</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">relation</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">find_each</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">&amp;</span><span style="background-color: #f8f8f8">block</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@relation</span><span style="background-color: #f8f8f8">.</span>
      <span style="color: #990000;font-weight: bold">where</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">plan: </span><span style="color: #000000;font-weight: bold">nil</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">invites_count: </span><span style="color: #009999">0</span><span style="background-color: #f8f8f8">).</span>
      <span style="color: #990000;font-weight: bold">find_each</span><span style="background-color: #f8f8f8">(</span><span style="color: #000000;font-weight: bold">&amp;</span><span style="background-color: #f8f8f8">block</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>You might use it in a background job to send emails:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #008080">AbandonedTrialQuery</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">find_each</span> <span style="color: #000000;font-weight: bold">do</span> <span style="color: #000000;font-weight: bold">|</span><span style="background-color: #f8f8f8">account</span><span style="color: #000000;font-weight: bold">|</span>
  <span style="background-color: #f8f8f8">account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">send_offer_for_support</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Since <code>ActiveRecord::Relation</code> instances are first class citizens as of Rails 3, they make a great input to a Query Object. This allows you to combine queries using composition:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="background-color: #f8f8f8">old_accounts</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">Account</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">where</span><span style="background-color: #f8f8f8">(</span><span style="color: #d14">"created_at &lt; ?"</span><span style="background-color: #f8f8f8">,</span> <span style="color: #009999">1</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">month</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">ago</span><span style="background-color: #f8f8f8">)</span>
<span style="background-color: #f8f8f8">old_abandoned_trials</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">AbandonedTrialQuery</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">old_accounts</span><span style="background-color: #f8f8f8">)</span>
</code></pre></div>
<p>Don&rsquo;t bother testing a class like this in isolation. Use tests that exercise the object and the database together to ensure the correct rows are returned in the right order and any joins or eager loads are performed (e.g. to avoid N + 1 query bugs).</p>

<p><a id="view-objects"></a></p>

<h2>5. Introduce View Objects</h2>

<p>If logic is needed purely for display purposes, it does not belong in the model. Ask yourself, &ldquo;If I was implementing an alternative interface to this application, like a voice-activated UI, would I need this?&rdquo;. If not, consider putting it in a helper or (often better) a View object.</p>

<p>For example, the donut charts in Code Climate break down class ratings based on a snapshot of the codebase (e.g. <a href="https://codeclimate.com/github/rails/rails">Rails on Code Climate</a>) and are encapsulated as a View:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">DonutChart</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">snapshot</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@snapshot</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">snapshot</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">cache_key</span>
    <span style="color: #008080">@snapshot</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">id</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">to_s</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">data</span>
    <span style="color: #999988;font-style: italic"># pull data from @snapshot and turn it into a JSON structure</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>I often find a one-to-one relationship between Views and ERB (or Haml/Slim) templates. This has led me to start investigating implementations of the <a href="http://martinfowler.com/eaaCatalog/twoStepView.html">Two Step View</a> pattern that can be used with Rails, but I don&rsquo;t have a clear solution yet.</p>

<p><em>Note:</em> The term &ldquo;Presenter&rdquo; has caught on in the Ruby community, but I avoid it for its baggage and conflicting use. The &ldquo;Presenter&rdquo; term was <a href="http://blog.jayfields.com/2007/03/rails-presenter-pattern.html">introduced by Jay Fields</a> to describe what I refer to above as &ldquo;Form Objects&rdquo;. Also, Rails unfortunately uses the term &ldquo;view&rdquo; to describe what are otherwise known as &ldquo;templates&rdquo;. To avoid ambiguity, I sometimes refer to these View objects as &ldquo;View Models&rdquo;.</p>

<p><a id="policy-objects"></a></p>

<h2>6. Extract Policy Objects</h2>

<p>Sometimes complex read operations might deserve their own objects. In these cases I reach for a Policy Object. This allows you to keep tangential logic, like which users are considered active for analytics purposes, out of your core domain objects. For example:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">ActiveUserPolicy</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">user</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@user</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">user</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">active?</span>
    <span style="color: #008080">@user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">email_confirmed?</span> <span style="color: #000000;font-weight: bold">&amp;&amp;</span>
    <span style="color: #008080">@user</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">last_login_at</span> <span style="color: #000000;font-weight: bold">&gt;</span> <span style="color: #009999">14</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">days</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">ago</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>This Policy Object encapsulates one business rule, that a user is considered active if they have a confirmed email address and have logged in within the last two weeks. You can also use Policy Objects for a group of business rules like an <code>Authorizer</code> that regulates which data a user can access.</p>

<p>Policy Objects are similar to Service Objects, but I use the term &ldquo;Service Object&rdquo; for write operations and &ldquo;Policy Object&rdquo; for reads. They are also similar to Query Objects, but Query Objects focus on executing  SQL to return a result set, whereas Policy Objects operate on domain models already loaded into memory.</p>

<p><a id="decorators"></a></p>

<h2>7. Extract Decorators</h2>

<p>Decorators let you layer on functionality to existing operations, and therefore serve a similar purpose to callbacks. For cases where callback logic only needs to run in some circumstances or including it in the model would give the model too many responsibilities, a Decorator is useful.</p>

<p>Posting a comment on a blog post might trigger a post to someone&rsquo;s Facebook wall, but that doesn&rsquo;t mean the logic should be hard wired into the <code>Comment</code> class. One sign you&rsquo;ve added too many responsibilities in callbacks is slow and brittle tests or an urge to stub out side effects in wholly unrelated test cases.</p>

<p>Here&rsquo;s how you might extract Facebook posting logic into a Decorator:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">FacebookCommentNotifier</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">initialize</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">comment</span><span style="background-color: #f8f8f8">)</span>
    <span style="color: #008080">@comment</span> <span style="color: #000000;font-weight: bold">=</span> <span style="background-color: #f8f8f8">comment</span>
  <span style="color: #000000;font-weight: bold">end</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">save</span>
    <span style="color: #008080">@comment</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">save</span> <span style="color: #000000;font-weight: bold">&amp;&amp;</span> <span style="background-color: #f8f8f8">post_to_wall</span>
  <span style="color: #000000;font-weight: bold">end</span>

<span style="color: #000000;font-weight: bold">private</span>

  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">post_to_wall</span>
    <span style="color: #008080">Facebook</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">post</span><span style="background-color: #f8f8f8">(</span><span style="color: #990073">title: </span><span style="color: #008080">@comment</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">title</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">user: </span><span style="color: #008080">@comment</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">author</span><span style="background-color: #f8f8f8">)</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>And how a controller might use it:</p>
<div class="highlight"><pre class="highlight ruby"><code><span style="color: #000000;font-weight: bold">class</span> <span style="color: #445588;font-weight: bold">CommentsController</span> <span style="color: #000000;font-weight: bold">&lt;</span> <span style="color: #008080">ApplicationController</span>
  <span style="color: #000000;font-weight: bold">def</span> <span style="color: #990000;font-weight: bold">create</span>
    <span style="color: #008080">@comment</span> <span style="color: #000000;font-weight: bold">=</span> <span style="color: #008080">FacebookCommentNotifier</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="color: #008080">Comment</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">new</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">params</span><span style="background-color: #f8f8f8">[</span><span style="color: #990073">:comment</span><span style="background-color: #f8f8f8">]))</span>

    <span style="color: #000000;font-weight: bold">if</span> <span style="color: #008080">@comment</span><span style="background-color: #f8f8f8">.</span><span style="color: #990000;font-weight: bold">save</span>
      <span style="background-color: #f8f8f8">redirect_to</span> <span style="background-color: #f8f8f8">blog_path</span><span style="background-color: #f8f8f8">,</span> <span style="color: #990073">notice: </span><span style="color: #d14">"Your comment was posted."</span>
    <span style="color: #000000;font-weight: bold">else</span>
      <span style="background-color: #f8f8f8">render</span> <span style="color: #d14">"new"</span>
    <span style="color: #000000;font-weight: bold">end</span>
  <span style="color: #000000;font-weight: bold">end</span>
<span style="color: #000000;font-weight: bold">end</span>
</code></pre></div>
<p>Decorators differ from Service Objects because they layer on responsibilities to existing interfaces. Once decorated, collaborators just treat the <code>FacebookCommentNotifier</code> instance as if it were a <code>Comment</code>. In its standard library, Ruby provides a number of <a href="http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in">facilities to make building decorators easier</a> with metaprogramming.</p>

<h2>Wrapping Up</h2>

<p>Even in a Rails application, there are many tools to manage complexity in the model layer. None of them require you to throw out Rails. ActiveRecord is a fantastic library, but any pattern breaks down if you depend on it exclusively. Try limiting your ActiveRecords to persistence behavior. Sprinkle in some of these techniques to spread out the logic in your domain model and the result will be a much more maintainable application.</p>

<p>You&rsquo;ll also note that many of the patterns described here are quite simple. The objects are just &ldquo;Plain Old Ruby Objects&rdquo; (PORO) used in different ways. And that&rsquo;s part of the point and the beauty of OOP. Every problem doesn&rsquo;t need to be solved by a framework or library, and naming matters a great deal.</p>

<p>What do you think of the seven techniques I presented above? What are your favorites and why? Have I missed any? Let me know in the comments!</p>

<p><strong>P.S.</strong> If you found this post useful, you may want to subscribe to our email newsletter (see below). It&rsquo;s low volume, and includes content about OOP and refactoring Rails applications like this.</p>

<h2>Further Reading</h2>

<ul>
<li><a href="http://objectsonrails.com/">Objects on Rails</a></li>
<li><a href="http://jamesgolick.com/2010/3/14/crazy-heretical-and-awesome-the-way-i-write-rails-apps.html">Crazy, Heretical, and Awesome: The Way I Write Rails Apps</a></li>
<li><a href="http://blog.steveklabnik.com/posts/2011-12-30-active-record-considered-harmful">ActiveRecord (and Rails) Considered Harmful</a></li>
<li><a href="http://solnic.eu/2012/07/09/single-responsibility-principle-on-rails-explained.html">Single Responsibility Principle on Rails Explained</a></li>
</ul>

<p><em>Thank you to Steven Bristol, Piotr Solnica, Don Morrison, Jason Roelofs, Giles Bowkett, Justin Ko, Ernie Miller, Steve Klabnik, Pat Maddox, Sergey Nartimov and Nick Gauthier for reviewing this post.</em></p>
]]>
    </content>
  </entry>
  <entry>
    <title>Code Climate is free for Open Source</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-climate-is-free-for-open-source/"/>
    <id>https://codeclimate.com/blog/code-climate-is-free-for-open-source/</id>
    <updated>2012-07-10T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Today I&rsquo;m excited to announce that Code Climate is free for open source projects. Many open source projects were added during the closed beta, and you can <strong>see them all on the new <a href="https://codeclimate.com/explore">Explore page</a>.</strong> <em>(To learn more about what Code Climate provides and how it works, <a href="https://codeclimate.com/">check out the homepage</a>.)</em></p>

<p>This has been in the plans since the beginning and was one of the common requests since the launch for private accounts. It feels great to finally have it out the door. My hope is that Code Climate becomes as valuable a tool to Ruby open source development as <a href="http://travis-ci.org/">Travis CI</a>.</p>

<p>Code quality is especially important for OSS because of the large number of contributors they attract. Now quality metrics can complement a suite of automated tests to help ensure you&rsquo;re shipping rock solid releases. Look out for more features around this coming soon.</p>

<h2>Popular projects on Code Climate</h2>

<p>You might be interested in taking a look at:</p>

<ul>
<li><a href="https://codeclimate.com/github/rails/rails">Rails</a></li>
<li><a href="https://codeclimate.com/github/rspec/rspec-core">RSpec</a></li>
<li><a href="https://codeclimate.com/github/plataformatec/devise">Devise</a></li>
<li><a href="https://codeclimate.com/github/thoughtbot/paperclip">Paperclip</a></li>
<li><a href="https://codeclimate.com/github/rubinius/rubinius">Rubinius</a> (Ruby static analysis for a Ruby implementation!)</li>
</ul>

<h2>How to add repositories</h2>

<p>To add any Ruby app or library that is hosted in a public GitHub repository, <strong>visit <a href="https://codeclimate.com/github/signup">the Add GitHub Repository page</a>.</strong> Just provide the name of the repo (e.g. <code>thoughtbot/paperclip</code>) and your email address. Code Climate will clone the project, analyze it, and shoot you an email when the metrics are ready. This only takes a few minutes.</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Sublime Text 2 for Ruby</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/sublime-text-2-for-ruby/"/>
    <id>https://codeclimate.com/blog/sublime-text-2-for-ruby/</id>
    <updated>2012-06-21T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>Matz has said he wants Ruby to be the &ldquo;80% language&rdquo;, the ideal tool for 80% of software development. After switching from TextMate to <a href="http://www.sublimetext.com/2">Sublime Text 2</a> (ST2) a few months ago, I believe it&rsquo;s the &ldquo;80% editor&rdquo;. <strong>You should switch to it, especially if you&rsquo;re using TextMate.</strong></p>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/sublime-text-2/editor-61724782.png" alt="Sublime Text 2 with Soda Light theme editing Ruby" /></p>

<h2>Why Sublime Text 2?</h2>

<ul>
<li><p><strong>Speed.</strong> It&rsquo;s got the responsiveness of Vim/Emacs but in a full GUI environment. It doesn&rsquo;t freeze/beachball. No need to install a special plugin just to have a workable &ldquo;Find In Project&rdquo; solution.</p></li>
<li><p><strong>Polish.</strong> Some examples: Quit with one keystroke and windows and unsaved buffers are retained when you restart. Searching for files by name includes fuzzy matching and directory names. Whitespace is trimmed and newlines are added at the end of files. Configuration changes are applied instantly.</p></li>
<li><p><strong>Split screen.</strong> I never felt like I missed this that much with TextMate, but I really appreciate it now. It&rsquo;s ideal for having a class and unit test side-by-side on a 27-inch monitor.</p></li>
<li><p><strong>Extensibility.</strong> The Python API is great for easily building your own extensions. There&rsquo;s lots of example code in the wild to learn from. (More about this later.) ST2 support TextMate snippets and themes out-of-the-box.</p></li>
<li><p><strong>Great for pair programming.</strong> TextMate people feel right at home. Vim users can use <a href="http://www.sublimetext.com/docs/2/vintage.html">Vintage mode</a>. When pairing with Vim users, they use command mode when they are driving. I just switch out of command mode and everything &ldquo;just works&rdquo;. (It also works on Linux, if that&rsquo;s your thing.)</p></li>
<li><p><strong>Updates.</strong> This is mainly just a knock on TextMate, but it&rsquo;s comforting to see new <a href="http://www.sublimetext.com/dev">dev builds</a> pushed every couple weeks. The author also seems to be quite responsive in the user community. A build already shipped with support for retina displays, which I believe is scheduled for a TextMate release in 2014.</p></li>
</ul>

<h2>Getting Started</h2>

<p>I&rsquo;ve helped a handful of new ST2 users get setup over the past few months. Here are the steps I usually follow to take a new install from good to awesome:</p>

<ol>
<li><p><strong>Install the <code>subl</code> command line tool.</strong> Assuming ~/bin is in your path:</p>
<div class="highlight"><pre class="highlight plaintext"><code>  ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" ~/bin/subl
</code></pre></div>
<p>It works like <code>mate</code>, but has more options. Check <code>subl --help</code>.</p></li>
<li><p><strong>Install <a href="http://wbond.net/sublime_packages/package_control">Package Control</a>.</strong> Package Control makes it easy to install/remove/upgrade ST2 packages.</p>

<p>Open the ST2 console with Ctrl+` (like Quake). Then paste this Python code from <a href="http://wbond.net/sublime_packages/package_control/installation">this page</a> and hit enter. Reboot ST2. (You only need to do this once. From now on you&rsquo;ll use Package Control to manage ST2 packages.)</p></li>
<li><p><strong>Install the <a href="https://github.com/buymeasoda/soda-theme">Soda theme</a>.</strong> This dramatically improves the look and feel of the editor. Use Package Control to install the theme:</p></li>
</ol>
<div class="highlight"><pre class="highlight plaintext"><code>* Press ⌘⇧P to open the Command Palette.
* Select "Package Control: Install Package" and hit Enter.
* Type "Theme - Soda" and hit Enter to install the Soda package.
</code></pre></div>
<ol>
<li><p><strong>Start with a basic Settings file.</strong> You can use <a href="https://github.com/brynary/sublime-text-2-user-settings/blob/master/Preferences.sublime-settings">mine</a>, which will activate the Soda Light theme. Reboot Sublime Text 2 so the Soda theme applies correctly. You can browse the default settings that ship with ST2 by choosing &ldquo;Sublime Text 2&rdquo; &gt; &ldquo;Preferences&hellip;&rdquo; &gt; &ldquo;Settings - Default&rdquo; to learn what you can configure.</p></li>
<li><p><strong>Install more packages.</strong> My essentials are SCSS, <a href="https://github.com/SublimeText/RSpec">RSpec</a>, <a href="https://github.com/phillipkoebbe/DetectSyntax">DetectSyntax</a> and <a href="https://github.com/kemayo/sublime-text-2-git">Git</a>. DetectSyntax solves the problem of ensuring your RSpec, Rails and regular Ruby files open in the right mode.</p></li>
<li><p><strong>Install <a href="https://github.com/SublimeText/CTags">CTags</a>.</strong> CTags let you quickly navigate to code definitons (classes, methods, etc.). First:</p>
<div class="highlight"><pre class="highlight plaintext"><code>  $ brew install ctags
</code></pre></div>
<p>Then use Package Control to install the ST2 package. Check out the <a href="https://github.com/SublimeText/CTags#commands-listing">default CTags key bindings</a> to see what you can do.</p></li>
</ol>

<h2>Leveling Up with Custom Commands</h2>

<p>Sublime Text 2 makes it dead simple to write your own commands and key bindings in Python. Here are some custom bindings that I use:</p>

<ul>
<li>Copy the path of the current file to the clipboard. <a href="https://github.com/neilsarkar/sublime_user_directory/blob/master/copy_path_to_clipboard.py">Source</a></li>
<li>Close all tabs except the current one (reduces &ldquo;tab sprawl&rdquo;). <a href="https://github.com/neilsarkar/sublime_user_directory/blob/master/close_other_tabs.py">Source</a></li>
<li>Switch between test files and class definitions (much faster than TextMate). <a href="https://github.com/brynary/sublime-text-2-user-settings/blob/master/rspec.py">Source</a></li>
<li>Compile CoffeeScript to JavaScript and display in a new buffer. <a href="https://github.com/neilsarkar/sublime_user_directory/blob/master/coffeescript.py">Source</a></li>
</ul>

<p>New key bindings are installed by dropping Python class files in <code>~/Library/Application Support/Sublime Text 2/Packages/User</code> and then binding them from <code>Default (OSX).sublime-keymap</code> in the same directory. The ST2 Unofficial Documentation has <a href="http://docs.sublimetext.info/en/latest/customization/key_bindings.html">more details</a>.</p>

<p><em><a href="http://neilsarkar.com/">Neil Sarkar</a>, my colleague, wrote most of the code for all of the above within a few weeks of switching to ST2.</em></p>

<h2>Running RSpec from Sublime Text 2</h2>

<p><img src="https://d341kum51qu34d.cloudfront.net/images/posts/sublime-text-2/tests_and_code-f19117c4.png" alt="Using Sublime Text 2 with Ruby" /></p>

<p><strong>This is my favorite part of my Sublime Text 2 config.</strong> I&rsquo;ll admit: Out of the box (even with the RSpec package installed), ST2 sucks for running tests. Fortunately, Neil wrote a Python script that makes running RSpec from Sublime Text 2 much better than running it from TextMate via the RSpec bundle.</p>

<p>With <a href="https://github.com/neilsarkar/sublime_user_directory/blob/master/rspec.py">this script</a> installed, you can bind ⌘R to run the current file and ⌘⇧R to run the current test. <strong>The tests will run in Terminal.</strong> This is great for a number of reasons:</p>

<ul>
<li>You can use any RSpec formatter and get nice, colored output.</li>
<li>Adding calls to <code>debugger</code> or <code>binding.pry</code> works. No need to change how you run your tests when you want to debug.</li>
<li>Window management. It&rsquo;s smart enough to reuse the Terminal window for new test runs if you don&rsquo;t close it. I put my Terminal window on the right 40% of my monitor.</li>
</ul>

<p>This has really improved my TDD workflow when working on individual classes.</p>

<h2>More Resources</h2>

<ul>
<li>Be sure to check out <a href="http://opensoul.org/blog/archives/2012/01/12/getting-started-with-sublime-text-2/">Brandon Keeper&rsquo;s post</a> on getting started with ST2.</li>
<li><a href="http://net.tutsplus.com/tutorials/tools-and-tips/sublime-text-2-tips-and-tricks/">This article</a> on NetTuts has some good tips. (Although it&rsquo;s a little out of date.)</li>
<li>My entire <a href="https://github.com/brynary/sublime-text-2-user-settings">ST2 user directory</a> is on GitHub, as is <a href="https://github.com/neilsarkar/sublime_user_directory">Neil&rsquo;s</a>.</li>
<li>You can search for ST2 packages <a href="http://wbond.net/sublime_packages/community">here</a>. Don&rsquo;t be afraid to dive into their source &ndash; it&rsquo;s usually quite approachable.</li>
</ul>

<p>If you&rsquo;ve tried Sublime Text 2, what did you think? What packages, key bindings, etc. are your favorites? What do you miss most from other editors?</p>
]]>
    </content>
  </entry>
  <entry>
    <title>Code quality at GORUCO</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/code-quality-at-goruco/"/>
    <id>https://codeclimate.com/blog/code-quality-at-goruco/</id>
    <updated>2012-06-07T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p><a href="http://goruco.com/">GORUCO 2012</a>, NYC&rsquo;s premier Ruby conference, is around the corner (<a href="http://bit.ly/goruco-2012-registration">tickets</a> are still available) and it&rsquo;s going to be great. (I may be biased, as I help organize the conference, but it&rsquo;s still true!) We have some fantastic speakers this year, and I&rsquo;m especially looking forward to three talks that focus on different aspects of code quality:</p>

<ul>
<li><p><strong><a href="http://goruco.com/speakers/2012/05/22/chelimsky-david.html">&ldquo;Maintaining Balance while Reducing Duplication &ndash; Part 2&rdquo;</a></strong> by <a href="http://blog.davidchelimsky.net/">David Chelimsky</a>. This is a follow up to David&rsquo;s excellent talk from RubyConf 2010 that explored the <a href="http://c2.com/cgi/wiki?DontRepeatYourself">DRY Principle</a> (Don&rsquo;t Repeat Yourself) in depth and illustrated how it can be misapplied. The inherent tensions between different OO design principles is particularly interesting to me. I highly recommend watching the <a href="http://www.confreaks.com/videos/434-rubyconf2010-maintaining-balance-while-reducing-duplication">video</a>, if you haven&rsquo;t seen the original.</p></li>
<li><p><strong><a href="http://goruco.com/speakers/2012/05/22/leitgeb-justin.html">&ldquo;Sensible Testing&rdquo;</a></strong> by <a href="http://justinleitgeb.com/">Justin Leitgeb</a>. Justin really impressed me with his lightning talk at a recent NYC.rb about Ruby mixins and their problems (see his related <a href="http://justinleitgeb.com/?p=199">blog post</a>). With this talk, I think he&rsquo;ll do a great job exploring testing strategies for Rails apps in a practical, nuanced way. I wouldn&rsquo;t be surprised if the <a href="http://www.mountaingoatsoftware.com/blog/the-forgotten-layer-of-the-test-automation-pyramid">Testing Pyramid</a> comes up, which more developers should take to heart. <a href="http://smartic.us/2008/08/15/tatft-i-feel-a-revolution-coming-on/">TATFT</a> is great mnemonic, but applying it well over a large codebase and a long period of time requires a great deal of consideration.</p></li>
<li><p><strong><a href="http://goruco.com/speakers/2012/05/22/wynne-matt.html">&ldquo;Hexagonal Rails&rdquo;</a></strong> by <a href="http://blog.mattwynne.net/">Matt Wynne</a>. Alistair Cockburn has been talking about <a href="http://alistair.cockburn.us/Hexagonal+architecture">Hexagonal Architecture</a> (which he now calls &ldquo;Ports and Adapters&rdquo;) for years as a way to structure applications for better maintainability. It&rsquo;s always been enticing to me, but it&rsquo;s never been clear how to apply it to a Rails application. Matt has started exploring just that <a href="http://blog.mattwynne.net/2012/04/09/hexagonal-rails-introduction/">on his blog</a> and I&rsquo;m thrilled he&rsquo;ll be giving a full-length talk on it at GORUCO. Personally, I hope he covers the implications on the model layer at least as much as controllers/views, and perhaps how this architecture might relate to the <a href="http://martinfowler.com/bliki/AnemicDomainModel.html">Anemic Domain Model</a> antipattern described by Martin Fowler. (If not, I&rsquo;ll ask him during Q&amp;A. Hah.)</p></li>
</ul>

<p>And before you ask, yes, the good folks at <a href="http://www.confreaks.com/">Confreaks</a> will be recording the talks and we hope to have them posted within a few weeks of the conference (if not sooner).</p>

<p>If you&rsquo;re attending GORUCO this year, definitely stop me and say &ldquo;Hello!&rdquo; (Either during the day, or aboard the <em>::ahem::</em> <a href="http://goruco.com/party/">yacht</a> during the evening.)</p>

<p><em>Full disclosure:</em> I had the honor of being a member of the GORUCO Program Committee this year that selected the speakers, so it may not be a complete coincidence that my interests are well represented. :)</p>
]]>
    </content>
  </entry>
  <entry>
    <title>What code goes in the lib/ directory?</title>
    <author>
      <name>Bryan Helmkamp</name>
      <uri>https://twitter.com/brynary</uri>
    </author>
    <link rel="alternate" href="https://codeclimate.com/blog/what-code-goes-in-the-lib-directory/"/>
    <id>https://codeclimate.com/blog/what-code-goes-in-the-lib-directory/</id>
    <updated>2012-02-07T07:00:00+00:00</updated>
    <content type="html">
      <![CDATA[<p>A common question teams run into while building a Rails app is &ldquo;What code should go in the <code>lib/</code> directory?&rdquo;. The generated Rails README proclaims:</p>

<blockquote>
<p><code>lib</code> &ndash; Application specific libraries. Basically, any kind of custom code that doesn&rsquo;t belong under controllers, models, or helpers. This directory is in the load path.</p>
</blockquote>

<p>That&rsquo;s not particularly helpful. By using the word &ldquo;libraries&rdquo; in the definition, it&rsquo;s recursive. And what does &ldquo;application specific&rdquo; mean? Isn&rsquo;t all the code in my Rails app &ldquo;application specific&rdquo; by definition?</p>

<p>So teams are left to work out their own conventions. If you quizzed the members of most teams, I&rsquo;d bet they&rsquo;d give different answers to the &ldquo;What goes in <code>lib/</code>?&rdquo; question.</p>

<h2>Antipattern: Anything that&rsquo;s not an ActiveRecord</h2>

<p>As we know from the <a href="http://blog.steveklabnik.com/posts/2011-09-06-the-secret-to-rails-oo-design">secret to Rails object oriented design</a>, well crafted applications grow many plain old Ruby object that don&rsquo;t inherit from anything (and certainly not the framework). However, the most common antipattern is pushing any classes that are not ActiveRecord models into <code>lib/</code>. This tremendously harmful to fostering a well designed application.</p>

<p><strong>Treat non-ActiveRecord classes as first class citizens.</strong> Requiring these classes be stored in a <code>lib/</code> junk drawer away from the rest of the domain model creates enough friction that they tend not be created at all.</p>

<h2>Pattern: Store code that is not domain specific in <code>lib/</code></h2>

<p>As an alternative, I recommend <strong>any code that is not specific to the domain of the application goes in <code>lib/</code></strong>. Now the issue is how to define &ldquo;specific to the domain&rdquo;. I apply a litmus test that almost always provides a clear answer:</p>

<blockquote>
<p>If instead of my app, I were building a social networking site for pet turtles (let&rsquo;s call it <em>MyTurtleFaceSpace</em>) is there a chance I would use this code?</p>
</blockquote>

<p>Now things get easier. Let&rsquo;s look at some examples:</p>

<ul>
<li>An <code>OnboardingReport</code> class goes in <code>app/</code>. This depends on the specific steps the users must go through to get started with the application.</li>
<li>A <code>SSHTunnel</code> class used for deployment goes in <code>lib/</code>. MyTurtleFaceSpace needs to be deployed too.</li>
<li>Custom Resque extensions go in <code>lib/</code>. Any site may use a background processing system.</li>
<li>A <code>ShippingRatesImporter</code> goes in <code>app/</code> if it imports a data format the company developed internally. On the other hand, a <code>FedExRateImporter</code> would probably go in <code>lib/</code>.</li>
<li>A <code>GPGEncrypter</code> class goes in <code>lib/</code>. Turtles need privacy too.</li>
</ul>

<p>Some developers find it distasteful to have classes like <code>OnboardingReport</code> and <code>ShippingRatesImporter</code> living in <code>app/models/</code>. This doesn&rsquo;t bother me as I consider them to be part of the broadly defined &ldquo;domain model&rdquo;, but I&rsquo;ll often introduce modules like <code>Reports</code> and <code>Importers</code> to group these classes which avoids them cluttering up the root of the <code>app/models/</code> directory.</p>

<p>I&rsquo;m sure there are other patterns for dividing code between <code>lib/</code> and <code>app/</code>. What rule of thumb does your team follow? What are the pros and cons?</p>
]]>
    </content>
  </entry>
</feed>
