<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace V5 Site Server v5.13.156 (http://www.squarespace.com) on Sun, 19 May 2013 03:21:48 GMT--><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Four Cups</title><link>http://4cupsr.us/blog/</link><description></description><lastBuildDate>Sun, 14 Apr 2013 19:05:49 +0000</lastBuildDate><copyright></copyright><language>en-US</language><generator>Squarespace V5 Site Server v5.13.156 (http://www.squarespace.com)</generator><item><title>What the heck should I be doing right now?</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sun, 14 Apr 2013 19:05:08 +0000</pubDate><link>http://4cupsr.us/blog/2013/4/14/what-the-heck-should-i-be-doing-right-now.html</link><guid isPermaLink="false">1039052:11943401:33331391</guid><description><![CDATA[<p>I forbade myself from coding this weekend.</p>
<p>I desperately want to code. That's why I've forbidden myself. I've spent the last two weeks writing a sweet set of iOS build scripts. At first, the entire iOS build process made no sense and I was hacking blindly. Then I started to figure things out. And then the vision of the Perfect Build started to burn into my mind. I could think about nothing else. And I willingly flung myself at it. Each commit brought me closer, but my progress enlightened me to how much better things could be. &nbsp;I left work on Friday night at 10 pm happy, but exhausted. On my Saturday train ride to Philadelphia, I mentally obsessed about how to eliminate three more configuration settings and how to blow away a hard-coded value.</p>
<p>This feeling of exhausted, obsessed happiness is what first got me excited about coding. I remember experiencing it for the first time in 1992, when my friend Jed and I were on the phone late every night trying to figure out our AP Pascal assignments. I didn't sleep much. I didn't care. Nothing felt as great or as fulfilling as a problem's transformation from impossible to solvable to perfectable.</p>
<p>I think people without this obsessive streak have limited potential as programmers. Sooner or later, you hit the bug or the limitation that requires you to understand your code really deeply. At GameChanger, for instance, our DB developers have become MongoDB whisperers. To build a scalable system on top of MongoDB, they've had to understand how it works really well, and they've had to become absurdly familiar with its logging and its quirks. I hit this point with CSS a few years ago and with Javascript. And now I'm hitting it with Apple's serpentine build tools and process.</p>
<p>There's a paradox, though. You need to obsess about code to be a good engineer. To obsess about code, you need to willfully ignore the big picture sometimes. You can't get to an adequate depth of understanding if you always stop at the point where customers are happy and where the business makes money. Increasing your understanding enables you to do things that make customers even happier and that makes the business even more successful. But losing sight of the big picture makes your work less valuable, and that makes you a <em>bad</em>&nbsp;engineer.</p>
<p>After working all Friday night on my build scripts, dreaming about them, and then mulling them on my train ride, I decided it was time to step away. My build scripts will benefit GameChanger, but were they really the best way for me to spend a working Saturday? Reluctantly, I decided that they were not. I probably should be spending my time regaining the perspective that I suspend when I write code. So I spent a few hours actually <strong>using our product</strong>&nbsp;at the Penn-Princeton baseball game. And I learned a few things while doing so.</p>
<p>I stuck to my pledge not to code (save for a short Facebook API emergency). It wasn't easy. I really wanted my coding fix. But my weekend of perspective was valuable. I should do this every weekend.</p><p><br/></p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-33331391.xml</wfw:commentRss></item><item><title>Nobody codes alone</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sun, 14 Oct 2012 14:58:12 +0000</pubDate><link>http://4cupsr.us/blog/2012/10/14/nobody-codes-alone.html</link><guid isPermaLink="false">1039052:11943401:29832706</guid><description><![CDATA[<p>For the past few months at GameChanger, my team has had a "nobody codes alone" policy. Our three developers &mdash; Nick, Ben, and I &mdash; work together on the same features at the same time. It's an unusual practice. Conventional wisdom says that we should work on separate projects to minimize coordination overhead.</p>
<p>Conventional wisdom is wrong for two reasons. The first reason is pretty intuitive, but the second one is surprising.</p>
<p>The intuitive reason: working together simplifies code and reduces bugs. Any time wasted on coordination is gained back by time NOT spent on fixing bugs. I've lost count of the number of times that I've taken a complex, esoteric idea and simplified it after talking with someone else. Bugs reveal themselves more quickly in simple code. People working together are good at simplifying and distilling each other's ideas.</p>
<p>The surprise, though, is that co-development makes non-engineers more productive. Designers, testers, and product managers have to juggle every project that's in flight. When a bunch of projects are happening simultaneously, the burden falls on non-engineers who have to deal with interruptions and last-second requests. In most places I've worked, PMs, testers, and designers are overworked and stressed out. They crave the opportunity to do few things and to do them well. Co-developing features helps non-engineers become happier and more productive.</p>
<p>Not every team is capable of working together on everything. Ben, Nick and I can do it because we don't freak out at ambiguous situations. Our work collides frequently, and, when it does, someone invariably speaks up. When that happens, we stop what we're doing and we talk. Then we figure out a plan and get back to coding.</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-29832706.xml</wfw:commentRss></item><item><title>Reducing the TDD cycle</title><category>Daren Desjardins</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Mon, 08 Oct 2012 21:22:44 +0000</pubDate><link>http://4cupsr.us/blog/2012/10/8/reducing-the-tdd-cycle.html</link><guid isPermaLink="false">1039052:11943401:29733082</guid><description><![CDATA[<h3>Rails and Rspec</h3>
<p>If you've been practicing Test Driven Development, you are familiar with the normal cycle:</p>
<table>
<tbody>
<tr>
<td>&nbsp;</td>
<td><span class="full-image-float-right ssNonEditable"> <ol>
<li>Write a failing test</li>
<li>Write enough code to pass the test</li>
<li>Refactor while keeping the test in a passing state</li>
</ol> </span></td>
<td><img src="http://4cupsr.us/storage/TDD_cycle.png?__SQUARESPACE_CACHEVERSION=1349732027381" alt="" /></td>
</tr>
</tbody>
</table>
<p>Earlier this year I started developing in Rails with Rspec and found my cycle to be closer to the following:</p>
<table>
<tbody>
<tr>
<td>&nbsp;</td>
<td><span class="full-image-float-right ssNonEditable"> <ol>
<li>Write a failing test</li>
<li>Wait for Rails environment to load and my test to run</li>
<li>Write enough code to pass the test</li>
<li>Wait for Rails environment to load and my test to run</li>
<li>Refactor while keeping the test in a passing state</li>
<li>Wait for Rails environment to load and my test to run</li>
</ol> </span></td>
<td><span class="full-image-float-right ssNonEditable"><img src="http://4cupsr.us/storage/Slow_TDD.png?__SQUARESPACE_CACHEVERSION=1349732298502" alt="" /></span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>These wait stages will vary depending on your environment, but in my case it can be high as 15 seconds to run a test that is measured in ms. After a while I found myself starting to skip steps, writing larger and larger tests, filling in more code at once, etc. My rationale was, if its going to take so long to run one test, I might as well write a few at once. When I realized what I was doing I thought there had to be a better way. After some brief searching, I found it!</p>
<p>&nbsp;</p>
<h3>Spork</h3>
<p>Spork is a service that preloads your Rails environment, and then forks a copy of your server when you run tests. This reduces your TDD cycle back to the normal 3 step process, saving you valuable time.</p>
<p>Setting up Spork only takes a few minutes. For the latest instructions, see the <a class="external-link" rel="nofollow" href="https://github.com/sporkrb/spork-rails" target="_top">spork-rails</a> gem.</p>
<h4><strong>Installing</strong></h4>
<p>This assumes you have already installed the <strong>rspec-rails</strong> gem, and configured your <strong>spec_helper.rb</strong> file.</p>
<p>Add<strong> spork-rails</strong> to your Gemfile</p>
<pre class="code-java" style="padding-left: 30px;">group :test, :development <span class="code-keyword">do</span>
...
   gem <span class="code-quote">"spork-rails"</span>
...</pre>
<h4>Configuring</h4>
<p><span>After installing the gem, you need to configure Spork. You can bootstrap your test helper file by running:</span></p>
<pre class="code-java" style="padding-left: 30px;">spork rspec --bootstrap</pre>
<p><span><span>When it completes, it will tell you to modify your&nbsp;</span><strong>spec_helper.rb</strong><span>&nbsp;file and follow the instructions within. The bootstrap command will have edited your </span><strong>spec_helper.rb</strong><span> file and added two new blocks at the top:</span></span></p>
<pre class="code-ruby" style="padding-left: 30px;">require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.

end

Spork.each_run do
  # This code will be run each time you run your specs.

end

# The previous contents of the file will be at the bottom
...
</pre>
<p>Generally, all you need to is move everything that was in the file before, and is now below the Spork sections, within the <strong>Spork.prefork</strong> block. This block instructs Spork to perform this work only when it starts your initial Rails environment. Thus, when your environment is forked by Spork, all this overhead is avoided.</p>
<p>If you need to do some activity for each forked environment, place it in the <strong>Spork.each_run</strong> block.</p>
<h4>Usage</h4>
<p>Now that Spork is configured, you can start it and see how much faster your test runs are.</p>
<p>To start Spork:</p>
<pre class="code-ruby" style="padding-left: 30px;">$ spork
Using RSpec, Rails
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
</pre>
<p>Spork is now up and running, and listening on port 8989</p>
<p><span>To run your tests using Spork:</span></p>
<pre class="code-ruby" style="padding-left: 30px;">rspec --drb spec/
</pre>
<p>You will know its working because:</p>
<ul>
<li>your tests run immediately</li>
<li>in your spork terminal you see a message indicating it is running your tests</li>
</ul>
<p>If you want RSpec to default to using Spork, you can edit your <strong>.rspec</strong> file and add the <em>--drb</em> option to it. This way when you run RSpec it will look for Spork and use it if available, otherwise it will load your Rails environment normally.</p>
<div></div>
<h3>Rubymine Support</h3>
<p>For those of you using Rubymine, you can also leverage Spork. They have a great help page that provides the instructions here: <a href="http://www.jetbrains.com/ruby/webhelp/using-drb-server.html">Using DRB Server</a></p>
<h3>Caveats</h3>
<p>If you are making changes that would normally require you to restart Rails, you will now need to remember to restart Spork instead. This can be automated using tools like Guard which I'll cover in another post.</p><p><br/><br/><br/><br/></p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-29733082.xml</wfw:commentRss></item><item><title>How we fixed more bugs by deleting our bug DB</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sat, 15 Sep 2012 19:31:17 +0000</pubDate><link>http://4cupsr.us/blog/2012/9/15/how-we-fixed-more-bugs-by-deleting-our-bug-db.html</link><guid isPermaLink="false">1039052:11943401:28947288</guid><description><![CDATA[<p>&nbsp;</p>
<p><span class="full-image-float-right ssNonEditable"><span><img src="http://4cupsr.us/storage/post-images/Screen Shot 2012-09-15 at 4.14.37 PM.png?__SQUARESPACE_CACHEVERSION=1347740132431" alt="" /></span><span class="thumbnail-caption" style="width: 249px;">The entirety of our new bug database</span></span></p>
<p>Two weeks ago, I got frustrated with the hundreds of bugs and feature requests in our database. So I deleted the whole thing. Then an odd thing happened: we started fixing bugs. We fixed almost 30 bugs last week, easily our best bug fix rate since I've been at GameChanger.</p>
<p>Joel Spolsky inspired me with his post on <a href="http://www.joelonsoftware.com/items/2012/07/09.html">Software Inventory</a>. I followed his advice almost to the letter:</p>
<blockquote>
<p><span>At some point you realize that you&rsquo;ve put too much work into the bug database and not quite enough work into the product.</span></p>
<ul>
<li>Suggestion: use a triage system to decide if a bug is even worth recording.</li>
<li>Do not allow more than two weeks (in fix time) of bugs to get into the bug database.</li>
<li>If you have more than that, stop and fix bugs until you feel like you&rsquo;re fixing stupid bugs. Then close as &ldquo;won&rsquo;t fix&rdquo; everything left in the bug database. Don&rsquo;t worry, the severe bugs will come back.</li>
</ul>
</blockquote>
<p>In our release cycle, two weeks is an eternity. So we don't wait for two weeks of bugs to pile up. We wait until our bug column in Trello is roughly a screen-and-a-half tall.</p>
<p>Then we fix bugs! Our new bug column is&nbsp;<strong>too small to ignore.</strong>&nbsp;Some of the bugs that popped up were old bugs that customers had complained about for months. They had nowhere to hide in our tiny Trello column. So we fixed them.</p>
<p>The normal Huge Bug Database works in the opposite way. It requires a triage system (meeting), which requires agreement on a system of priority and severity (something to argue about). Then there needs to be some sort of scheme (meeting) for scheduling bug fixes along with feature work. And someone's got to make sure (emails) that the small percentage of Chosen Bugs are actually fixed before release goes out. That's a ton of meetings, arguments, emails, and management for little benefit.</p>
<p>Instead of documenting, categorizing, and scheduling bugs, we're fixing them and going back to writing features. Yay!</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-28947288.xml</wfw:commentRss></item><item><title>Transforming a 200k-line pile of spaghetti</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sun, 05 Aug 2012 20:21:47 +0000</pubDate><link>http://4cupsr.us/blog/2012/8/5/transforming-a-200k-line-pile-of-spaghetti.html</link><guid isPermaLink="false">1039052:11943401:21543668</guid><description><![CDATA[<p>This week, an intriguing question made the rounds at StackExchange: "<a href="http://programmers.stackexchange.com/questions/155488/ive-inherited-200k-lines-of-spaghetti-code-what-now">I've inherited 200k lines of spaghetti code &mdash; what now?</a>"&nbsp;Since I apparently lack enough karma to post on StackExchange &mdash; I created my account today &mdash; I'll respond here.</p>
<p>At its core, this is a people problem and not a technology problem. I've failed when I haven't recognized this fact. The core question isn't one of SCM, build systems, or coding practices. The core problem is convincing a group of people (scientists, in this case) to adopt a new set of practices and to&nbsp;<em>change the behaviors that led to spaghetti code.</em>&nbsp;</p>
<p>To make this transformation, some of the same people who are writing spaghetti code today will have to become evangelists for your ideas.</p>
<p>Here's what I'd do:&nbsp;</p>
<ul>
<li><strong style="font-weight: bold;">Observe for a couple of weeks.</strong><strong>&nbsp;</strong>Understand where the team is experiencing the most pain. What short term pressures does the team face? Learn what people are good at. Figure out who's most excited about making changes.</li>
<li><strong>Form a rough vision of what success looks like. </strong>The <a href="http://programmers.stackexchange.com/questions/155488/ive-inherited-200k-lines-of-spaghetti-code-what-now/155505#155505">leading answer</a> at StackExchange is quite thorough and it's a great starting point. But remember that this vision will necessarily be unique to each organization.</li>
<li><strong>Start by solving a problem that people already care about. </strong>Are people complaining about lost source code? Embarrassing bugs? Time spent on supporting legacy code? Too many feature requests and too little time? Bad user experience? Late releases? Whatever it is, a 200k-line code base is going to have lots of problems. The team is going to care about some of those problems more than others. With your first big initiative, earn people's gratitude! At a past job, the team became resentful when I tried to solve an important problem that the team didn't care about. I likely would have succeeded if I'd spent my first few months on problems that mattered to them.</li>
<li><strong>Support other people's good ideas.</strong>&nbsp;You can't tame a 200k-line code base by yourself. If you need other people to come up with good ideas, you better support those people when their ideas come along. My colleague Andrew was incensed at our group chat software and drove our adoption of <a href="https://www.hipchat.com/">HipChat</a>. A few weeks later, our entire development workflow is built on HipChat. Build notifications, deploy notifications, code review requests, and production alerts all route to HipChat rooms. At a company that hates email, nobody's&nbsp;ideas on continuous integration, monitoring, and alerting would have worked without a chat platform that the team loved.</li>
<li><strong>Be optimistic. </strong>Every problem has a solution. Your 200k-line code base won't be beautiful overnight, but there are going to be some great victories along the way. Enjoy them.</li>
<li><strong>Don't obsess over your failures. </strong>When you're dealing with a 200k-line code base, you're going to have to make a lot of changes. Not every change will work. Don't worry about it. I tried to turn every Monday into a bug-fixing day. It worked for a little bit but it proved hard to keep our attention on bugs when we were hustling to wrap up higher priority work on Mondays. I didn't force the issue. We'll find another way to prioritize bug fixes.</li>
<li><strong>Sell, sell, sell. </strong>When you make something better, make sure that other people understand it and can adopt it themselves. Do demos. Hold training classes. Pair program. Do what you need to do to make sure that good ideas get <a href="http://4cupsr.us/blog/2012/3/24/critical-mass-and-aspiration.html">critical mass</a>.</li>
</ul>
<p>Transforming a codebase is really about transforming a team. And transforming a team is about getting people excited to make big changes. Enjoy the challenge, and good luck!</p>
<p>&nbsp;</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-21543668.xml</wfw:commentRss></item><item><title>Risk is invisible</title><dc:creator>Oskar and Phil</dc:creator><pubDate>Wed, 04 Jul 2012 14:56:12 +0000</pubDate><link>http://4cupsr.us/blog/2012/7/4/risk-is-invisible.html</link><guid isPermaLink="false">1039052:11943401:16791682</guid><description><![CDATA[<p>Risk is invisible but reward is not. This basic fact has been at the root of more than a few calamities, not the least of which are the recent financial crisis and the dot-com boom and bust. A company's or a society's attitude towards risk is a core part of its culture. And we'd like to have a culture that encourages smart risks and discourages stupid ones. How do we do that?</p>
<p>Software engineers are responsible for avoiding stupid risks. But we often don't. Under pressure to meet a public deadline or to ship a highly visible feature, engineers routinely take reckless &mdash; but invisible &mdash; risks. We can introduce security loopholes, skimp on testing, or skip monitoring entirely. To make matters worse, customers &mdash; who can't see the risks &mdash; are usually thrilled by this behavior and software managers sometimes reward it. When you aren't attuned to the risks of software development, it's easy to mistake recklessness for&nbsp;"customer focus." How do we prevent this from happening?</p>
<p>It obviously helps when managers already understand risk. I was pleasantly surprised and impressed when our investor&nbsp;<a href="http://www.crunchbase.com/person/jos-white">Jos White</a>&nbsp;stopped by GameChanger and advised us to <strong>prioritize technical architecture</strong>. Jos is a wildly successful three-time entrepreneur. He founded three $100M+ companies, but he's never been an engineer. So when came to speak with us, I was excited to hear his story. And I wasn't surprised to hear him talk about finding untapped markets and finding great teams who <a href="http://www.thedaringjourney.com/2012/06/believe-it-in-your-bones/">believed in their bones</a> that they could bring their products to life. But I wasn't expecting a self-described marketing guy to talk about the importance of doing architecural work. Jos understood that good architecture was essential for scaling at low risk, even if that work doesn't pay off instantly. Jos has been around the block a few times, and so he seemingly "gets" the risk management balance that software companies need to master. Others learn to "get it" by working with technical people they trust.</p>
<p>As with many interesting problems, the root answer is cultural. Companies need to create a culture that values good risks and that discourages bad ones. In software, this comes down to valuing risk reduction and the people who practice it well:</p>
<ul>
<li>Does your company have a technical career path that rewards people for paying attention to details?</li>
<li>Do engineers get public attention and praise for risk mitigation? Or, alternatively, do they get attention and praise for heroic responses to problems that they should have prevented?</li>
<li>Do engineers have prestige in your company's culture?</li>
<li>Do engineers get rewarded or chastised for speaking truth to power?</li>
</ul>
<p>For our part, engineers need to use direct no-nonsense language when informing others about risk. At GameChanger, I was impressed when my colleague <a href="https://twitter.com/#!/dougwoos">Doug</a> made risk tangible by illustrating risks with graphs. A line that moved down and to the right was a good way to illustrate that we lowered our risk of crippling performance problems in the future.</p>
<p>It's hard to create a culture that takes good risks and avoids foolish ones. But it's an essential challenge for any company to grasp.</p><p><br/><br/><br/></p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-16791682.xml</wfw:commentRss></item><item><title>I won't grow up</title><dc:creator>Oskar and Phil</dc:creator><pubDate>Sun, 27 May 2012 22:08:04 +0000</pubDate><link>http://4cupsr.us/blog/2012/5/27/i-wont-grow-up.html</link><guid isPermaLink="false">1039052:11943401:16464773</guid><description><![CDATA[<blockquote>
<p><span>I won't grow up,</span><br /><span>I don't want to go to school.</span><br /><span>Just to learn to be a parrot,</span><br /><span>And recite a silly rule.</span><br /><span>If growing up means</span><br /><span>It would be beneath my dignity to climb a tree,</span><br /><span>I'll never grow up, never grow up, never grow up</span><br /><span>Not me!</span></p>
</blockquote>
<p style="padding-left: 30px;">- Peter Pan</p>
<p>I love what Facebook calls the <a href="http://www.wired.com/epicenter/2012/02/zuck-letter/">Hacker Way</a>, the idea that anyone can make a difference by doing more and by talking less, by moving quickly, and by constantly improving. I love that GameChanger has embraced this ethos. But some of our recent hack attempts have lead to embarrassing and unacceptable site crashes. And with those screwups came pressure to "grow up" and shelve the Hacker Way.</p>
<p>Three months ago, we decided to fix our problems without "growing up." Though we can't tolerate embarrassing bugs and crashes, we need to eradicate them in a way that doesn't destroy the hacker spirit that fuels the company. Instead, our answer to these problems is to&nbsp;<span id="internal-source-marker_0.7090726266615093">relentlessly driving down the risk of hackery.</span></p>
<p>I didn't always take that approach. At a past company, we &mdash; and I was a primary culprit &mdash; established a culture of extreme caution. Though we described ourselves as "agile", we introduced a functional spec process, and then a design spec process and then a test spec process. We mandated signoffs by an ever-growing list of stakeholders. We took responsibilities away from individual developers and delegated them to specialists. In short, we systematically eliminated any possibility of screwing up by adding processes, reviews, and checklists. To be fair, it worked at preventing catastrophes. But, in the process, we de-empowered ourselves. New employees never felt as if they could change things. We sucked the fun out of what we were doing. And we slowed down.</p>
<p>Preserving the Hacker Way is as important as preventing screwups. My colleagues at GameChanger are building a foundation of technology and process that lets us have fun and make customers happy. I should note that I can't take credit. Lots of people are working hard to make our product safe for customers and hackers alike. Here's what we're doing.</p>
<h4>Measure everything</h4>
<p>We realized that we didn't know enough about how our system was behaving.&nbsp;We installed <a href="http://readthedocs.org/projects/graphite/">graphite</a> and <a href="https://github.com/etsy/statsd">statsd</a>&nbsp;and built APIs that made it easy for everyone to measure the behavior of the systems they were building. The graphs were a quick prod to action and improvement. Were we really making that many database calls? Were our queues really blowing up dramatically under load? The graphs surfaced bugs, which we fixed. And we proudly demo'ed "before" and "after" graphs to the whole company.</p>
<h4>Monitor aggressively</h4>
<p>Having data handy was only useful if we acted on it. Automated alerts were our prod to action. If a bad deploy causes errors to spike, we find out right away. If a queue suddenly explodes in size, we get notified. We constantly tune our thresholds so that they are just right &mdash; not so frequent to spam us with false positives, not so laid back that our customers suffer needlessly.</p>
<h4>Automate relentlessly</h4>
<p>Testing GameChanger is hard. It's a distributed, asynchronous system comprising a web site, and API, dozens of queue processors, an iOS app, and an Android app. All of these parts interact and they change frequently.</p>
<p>To assure that these parts work together well, we've been relentlessly automating our testing. We've set up a&nbsp;<a href="http://jenkins-ci.org/">Jenkins</a> instance that runs&nbsp;&nbsp;</p>
<ul>
<li><a href="http://www.logilab.org/857">pylint</a> checks and <a href="http://heynemann.github.com/pyvows/">PyVows</a> tests against our server-side code</li>
<li>Javascript tests in a headless browser</li>
<li>mobile app tests againsts headless simulators</li>
<li>Selenium <a href="http://seleniumhq.org/projects/webdriver/">WebDriver</a> "smoke tests" against multiple browsers</li>
<li>continuous deployment of test versions of our mobile app</li>
</ul>
<p>In the mean time, our mobile team is working on automating crash reporting and response with <a href="http://beta.crashlytics.com/">Crashlytics</a>.</p>
<h4>Eliminate noise</h4>
<p>Noise is the enemy of automation. People ignore automated alerts and tests when there are false positives and duplicate notifications. We hate noise. We keep our email inboxes clear of Jenkins notifications by routing them to <a href="http://www.hipchat.com">HipChat</a>. We're moving our alerts to nagios, which allows us to acknowledge known problems and clear our inboxes of noise.</p>
<h4>Reduce batch size&nbsp;</h4>
<p><a href="http://www.startuplessonslearned.com/2009/02/work-in-small-batches.html">Big changes are inherently riskier than small ones</a>. But keeping changes small requires conscious effort. Our mobile team is building tighter, more focused releases. Our server teams rely on a feature flag framework that lets us ship and test incomplete features without exposing them to customers.</p>
<h4>Eat our own dog food</h4>
<p>We routinely release risky changes to staff before enabling them for everyone. A couple of weeks back, we noticed that a staff-only jQuery upgrade broke our core checkout flow. We fixed the problem before releasing that upgrade to all users.</p>
<h4>Review prudently</h4>
<p>Every code change goes through mandatory pre-commit code review. Because we keep our batches small, code reviews only take a few minutes and require few changes. Since I'm a new employee, code reviews have often corrected my misunderstandings about our system. Reviews have also prompted us to come to quick agreement on design conventions and coding standards. It's easy to get carried away with code reviews, but I've been impressed with our commitment to keeping reviews quick and informative.</p>
<h4>Fix stuff that doesn't work</h4>
<p>When a part of our system constantly causes us problems, we fix it. We recently launched a rewritten version of our streaming server &mdash; and crushed a bunch of database load in the process. We also fixed post-deploy error spikes caused by inadequate load balancing.</p>
<h4>Learn from every mistake</h4>
<p>Despite our efforts, we still screw up sometimes. A common conclusion from our post-mortems is that we need to simplify development. Recently, for instance, we broke some page layouts in IE when accidentally deleted an HTML doctype from a base template. In our post-mortem, we realized that we were making a repetitive change to our&nbsp;<em>thirteen</em>&nbsp;base templates, and that we messed up one of the thirteen edits. The mistake slipped past the original committer and the code reviewer (me). We realized that having so many base templates was an invitation for error and we're now working on consolidating those thirteen templates into one.</p>
<p>We're also reducing library version management by using a standardized <a href="http://www.pip-installer.org/en/latest/requirements.html">requirements.txt</a> file. We're simplifying web UI development with a style guide.</p>
<p>Over time, we're getting smarter and our system is getting simpler. That's the point.</p>
<h3>So, is it working?</h3>
<p>We only started these initiatives three months ago and the results have been incredible:</p>
<ul>
<li>Web error spikes are half as frequent as they used to be, and that doesn't include improvements we made before we started measuring.</li>
<li>Our support team used to tell us when our messaging and streaming queues weren't working. Now we tell them &mdash; and we fix them fast.</li>
<li>More times than we can count, a failing smoke test or pylint check has preventing us from a disastrous deploy.</li>
</ul>
<p>We all recognize that there's tons more to do. Our system can become a lot simpler and more reliable. We need to close some monitoring loopholes. We still to root out some false positives. We are honing our skills at writing automated tests. But the bottom line is that we're becoming more reliable, and we're keeping the Hacker Way alive and well. We haven't burdened ourselves with tons of rules and processes. We're continuing to experiment with new libraries, to roll out new tools, to invent quirky traditions, and to have fun.</p>
<p>We haven't grown up and we don't plan on it.</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-16464773.xml</wfw:commentRss></item><item><title>Being Careful Is Not a Solution</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sun, 15 Apr 2012 21:19:26 +0000</pubDate><link>http://4cupsr.us/blog/2012/4/15/being-careful-is-not-a-solution.html</link><guid isPermaLink="false">1039052:11943401:15858482</guid><description><![CDATA[<p>When someone makes a big mistake, it's tempting to tell him or her to be careful. The developer who deployed buggy code should have been more careful. The support rep who messed up a customer's data should have followed the procedure more carefully. Nobody should have deployed anything during a high traffic time. When problems happen, people get angry and ask, "Why wasn't someone more careful?" And most of the time, some contrite person steps up and says, "I screwed up and should have been more careful."</p>
<p>Being careful is good, but being too careful is bad. An excess of carefulness doesn't atone for systemic flaws. That is, we shouldn't transfer responsibility from an error-prone system to whoever happened to make the most recent error. When I find myself promising to be more careful or telling someone else to be careful, a little voice in my head tells me, "You're ignoring the real problem."</p>
<p><strong>It should be hard for a developer to break significant functionality.</strong></p>
<p><strong>It should be hard for the product to crash.</strong></p>
<p><strong>It should be hard for a customer to make a mistake that requires them to contact support.</strong></p>
<p><strong>It should be easy to know quickly when something is wrong.</strong></p>
<p>All of those aspirations are possible. They just require more hard thought than being careful does. But, through good system design, judicious automation, meaningful alerting, and obsessive iteration, I've found that it is possible to build systems that enable me and my customers to be carefree.</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-15858482.xml</wfw:commentRss></item><item><title>Critical Mass and Aspiration</title><category>Phil's Booklet</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sat, 24 Mar 2012 17:54:31 +0000</pubDate><link>http://4cupsr.us/blog/2012/3/24/critical-mass-and-aspiration.html</link><guid isPermaLink="false">1039052:11943401:15573926</guid><description><![CDATA[<p>Some weeks back, Kiril Savino (GameChanger&rsquo;s CTO) <a href="http://kirilsavino.com/blog/2012/3/2/code-aspires.html"><span>wrote</span></a> that it&rsquo;s important for developers to understand and support the aspirations of a code base. Kiril argues that it&rsquo;s alright for a particular work of  code to be messy and imperfect if it&rsquo;s not inconsistent with the  codebase&rsquo;s <em>aspirations</em>. A hacked together method isn&rsquo;t great, but it  might be acceptable. But it&rsquo;s a bad idea to directly access the database  by circumventing an API designed for that purpose.<br /><br />I  love the concept of code aspiration, but I consider an aspiration  successful only if it eventually comes true. I&rsquo;ve seen a lot of  half-adopted aspirations that only add confusion. I&rsquo;ve found that  aspirations get adopted when they reach a critical mass,  in our minds and in code. When an aspiration reaches critical mass,  it&rsquo;s easier and more natural to follow the aspiration than not to.<br /><br />I&rsquo;ve  succeeded and failed before at getting critical mass for my  aspirations. There&rsquo;s no formula, but here are a few things I&rsquo;ve seen  work well:</p>
<ul>
<li><strong>"Open source" your aspirations</strong><strong>.</strong> At a previous job, I started to organize our codebase around the principles of <a href="http://www.amazon.com/dp/0321125215/ref=asc_df_03211252151949084?smid=ATVPDKIKX0DER&amp;tag=hyprod-20&amp;linkCode=asn&amp;creative=395093&amp;creativeASIN=0321125215&amp;hvpos=none&amp;hvexid=&amp;hvnetw=g&amp;hvrand=7299826151320451359&amp;hvpone=&amp;hvptwo=&amp;hvqmt="><span>Domain-Driven Design</span></a>.  A couple of weeks before I left that job, I explained my aspirations to  others. They liked the idea, tinkered with it, and simplified it to the  point where it was practical in our environment &mdash; all after I had left  for graduate school.</li>
<li><span><strong>Make adoption easy.</strong></span><span> Good documentation, good code examples, and time-saving tools make it  easy to follow the aspiration of a code base. I&rsquo;m hoping that our  interface to </span><a href="http://readthedocs.org/docs/graphite/en/latest/"><span>Graphite</span></a><span> at GameChanger will be so easy that everyone will use it to create graphs of system behavior.</span></li>
<li><strong>Create examples in code "hot spots."</strong>&nbsp;I  once rolled out a new template engine in parallel with a legacy engine.  Migrating all of our code to the new engine would take years, and so I  prioritized migrations of code that was modified frequently by a broad  variety of people. Forcing most people to use the new engine at least  sometimes caused them to become familiar with its aspirations.</li>
<li><span><strong>Code review.</strong></span><span> Yesterday, a code reviewer informed me that I was violating an  aspiration I didn&rsquo;t know about. These misunderstandings happen all the  time, and code review is a good way to fix them.</span></li>
<li><span><strong>Appeal to higher authority.</strong></span><span> I&rsquo;ve never been a huge fan of this technique, but I&rsquo;ve seen people  successfully enforce code aspirations by seeking an executive mandate.  Amazon.com&rsquo;s migration away from its legacy </span><a href="http://en.wikipedia.org/wiki/Obidos_%28software%29"><span>Obidos</span></a><span> web stack was enforced by an order from above.</span></li>
</ul>
<p><span>I&rsquo;ve  failed at this before too. I&rsquo;ve aspired to things that, in retrospect,  were dumb. I&rsquo;ve failed to make my aspirations clear, and I&rsquo;ve failed to  get people to adopt aspirations. And, on one project, an ill-timed  adoption of Adobe Flex, I committed all of these sins.</span><br /><br /><span>Aspiration is good. It&rsquo;s even better when it comes true.</span></p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-15573926.xml</wfw:commentRss></item><item><title>CSS Code Smells</title><category>Phil's Booklet</category><category>code smells</category><category>css</category><category>oocss</category><dc:creator>Oskar and Phil</dc:creator><pubDate>Sat, 25 Feb 2012 22:08:42 +0000</pubDate><link>http://4cupsr.us/blog/2012/2/25/css-code-smells.html</link><guid isPermaLink="false">1039052:11943401:15102192</guid><description><![CDATA[<p class="p1">Writing stable, cross-browser CSS isn't nearly as easy as it should be. Wouldn't it be nice if you could easily avoid some of the most painful CSS pitfalls?</p>
<p class="p2">In this&nbsp;post, I'm going to follow the spirit of Martin Fowler's classic <a href="http://martinfowler.com/bliki/CodeSmell.html">code smells</a> and list a small number of CSS-specific smells that cause bugs and limit productivity.&nbsp;I'm limiting my list to writing for modern browsers and IE versions 7 and later. This isn't a definitive or final list, and I plan to add to it as I get feedback and advice.</p>
<p class="p2">As Martin Fowler <a href="http://martinfowler.com/bliki/CodeSmell.html">points out</a>, "<span>The best smells are something that's easy to spot and most of time lead you to really interesting problems." Not every instance of a code smell indicates that there's a problem, but the presence of one should at least cause you to pause and think.</span></p>
<p class="p2">Nothing on this list is original. I think of it as a complement to&nbsp;<a href="http://csslint.net/">CSSLint</a> tool by Nicholas Zakas and Nicole Sullivan, which automatically scans your CSS for a set of problems. I'm also a huge fan of Nicole Sullivan's <a href="http://oocss.org/">OOCSS</a> methodology and I've liberally repeated some of its ideas in this post.</p>
<h3>My (least) favorite code smells</h3>
<p>Here's a small list of some of my least favorite code smells.</p>
<h4><strong>Smell: Width/height properties mixed with padding/margin/border properties</strong></h4>
<p class="p1">I stole this one straight from the CSSLint <code>box-model</code> <a href="https://github.com/stubbornella/csslint/wiki/Beware-of-box-model-size">rule</a>. An element's actual width and height is the sum of its content area width/height, its padding, its borders, and its margins.&nbsp;</p>
<p class="p1">To make things look right, I used to do mental arithmetic. If I had a 300px-wide module that needed 10px of horizonal padding, I'd define the width to be 280px and the horizontal padding to be 10px. This approach didn't work for three reasons.</p>
<ol>
<li>The arithmetic made things harder to understand at a glance that my element took up 300px of horizontal space and not 280px.</li>
<li>I've found several cases (see screenshot below) where a container's padding varied depending on its content. It didn't always make sense to preordain a container's padding.</li>
<li>It just won't work for containers with fluid (percentage) width and fixed (pixel) padding.</li>
</ol>
<p>&nbsp;</p>
<p class="p1"><span class="full-image-block ssNonEditable"><span><img src="http://4cupsr.us/storage/post-images/Screen Shot 2012-02-19 at 4.50.53 PM.png?__SQUARESPACE_CACHEVERSION=1329688352430" alt="" /></span><span class="thumbnail-caption" style="width: 611px;">Two instances of the same container, one internally padded and one not</span></span></p>
<p class="p2">There are two workarounds.&nbsp;If you don't need to support IE7, you can use the <code>box-sizing:&nbsp;border-box</code> CSS property setting. This will cause the width and height properties to set the width/height of the content area, padding, and borders together. An alternative workaround that works before IE7 is <em>to add padding and borders on contained elements only</em>. e.g.,</p>
<pre>&lt;section class="aContainerType"&gt; &lt;!-- width and height applied here. --&gt;
  &lt;div class="body"&gt; &lt;!-- Padding and borders applied here. --&gt;
  &lt;/div&gt;<p>&nbsp;
&lt;/section&gt;</p></pre>
<p class="p1">This workaround feels a little icky, but it works consistently and it's remarkably flexible.&nbsp;</p>
<h4><span style="font-weight: bold;">Smell: Overuse of explicit widths</span></h4>
<p class="p1">If your layout catastrophically breaks when you change the width of a column or container, then you're probably overusing explicit widths.</p>
<p class="p1">Twitter's website gives a good example of how to do things right. The right column has a width of 522px.</p>
<p class="p1"><span class="full-image-block ssNonEditable"><span><img style="width: 600px;" src="http://4cupsr.us/storage/post-images/Screen%20Shot%202012-02-25%20at%203.48.15%20PM.png?__SQUARESPACE_CACHEVERSION=1330203102478" alt="" /></span></span></p>
<p class="p1">But, if I hack the width to be 300px, the tweets still lay out in a reasonable way:</p>
<p class="p1"><span class="full-image-block ssNonEditable"><span><img src="http://4cupsr.us/storage/post-images/Screen Shot 2012-02-25 at 3.49.18 PM.png?__SQUARESPACE_CACHEVERSION=1330203219661" alt="" /></span></span></p>
<p class="p1"><em>Make your container widths fluid except when they have to be fixed.</em>&nbsp;You might need to practice a little to make this work, but, once you have the hang of it, you'll love the flexibility that fluid widths provide you.</p>
<h4><strong>Smell: Application semantics</strong></h4>
<p class="p1">Avoid CSS class names that say too much about your application's <em>behavior</em> and too little about its <em>design language</em>.</p>
<p class="p1">But shouldn't markup and styles be semantic? The meaning of "semantic" is a little confusing. <em>CSS semantics are visual</em>.&nbsp;For example, the classes <code>buttonLarge</code> and <code>buttonSmall</code> are decent class names because they describe two types of buttons that your design allows. The classes <code>addUser</code> or <code>hideProfile</code> are poor choices because they likely refer to a visual style that applies equally well to other behaviors. e.g., a button or link style.</p>
<p class="p1">Why does this matter? If your application succeeds, its functionality will expand dramatically. But its CSS should remain relatively small in size.&nbsp;If you tie your classes to your design language instead of to your application's functionality, then you'll easily be able to apply them to new functionality while writing a minimum amount of new CSS.</p>
<p class="p1">To see a good example of well-defined class names, see Bootstrap's&nbsp;<a href="http://twitter.github.com/bootstrap/components.html">button color and list styles</a>.&nbsp;</p>
<div></div>
<h4>Smell: Deep nesting (aka high specificity)</h4>
<p class="p2">Deeply nested styles &ndash; those preceeded by a long chain of IDs or selectors &ndash; are very hard to reuse. This is the core message of <a href="http://oocss.org/">OOCSS</a>. This smell is similar to the Application Semantics smell. A section header is a section header is a section header. There's no need for its styling to be nested under&nbsp;<code>.rightColumn</code> or <code>.feedbackBox</code>.</p>
<p class="p2">If you have multiple styles of a particular type (say, multiple section headers), then <em>define style variants that work across the board</em>&nbsp;and <em>separate content styles from container styles</em>. Here's a simple example from my company's style guide:</p>
<p class="p2"><span class="full-image-block ssNonEditable"><span><img src="http://4cupsr.us/storage/post-images/Screen%20Shot%202012-02-25%20at%204.18.12%20PM.png?__SQUARESPACE_CACHEVERSION=1330204798890" alt="" /></span><span class="thumbnail-caption" style="width: 612px;">A darkerHeaderBar and an urgentHeaderBar can be used anywhere on the site. They aren't nested under other selectors. They can also contain anything: lists, tables, even other sections.</span></span></p>
<p class="p2">Writing good container-independent styles with low nesting is tricky and it takes some practice. I highly recommend reading Nicole Sullivan's blog (I love <a href="http://www.stubbornella.org/content/2009/02/12/css-doesn%E2%80%99t-suck-you%E2%80%99re-just-doing-it-wrong/">this post</a>) on the subject and watching <a href="http://www.stubbornella.org/content/2009/03/23/object-oriented-css-video-on-ydn/">this video</a>.</p>
<h4>Smell: Hand-rolled float layouts</h4>
<p class="p2">This one will be the most controversial. Floats cause a ton of layout glitches because floated elements are taken out of the document flow. Floats were intended to support flow of text around images. But, because developers lacked alternatives, they used floats to lay out columns. There are subtleties involved in correctly floating elements and in clearing floats. And I've seen a lot of people trip up on those subtleties.&nbsp;</p>
<p class="p1"><em>Either take the time to learn how floats work, or use a grid framework.</em>&nbsp;I advise the latter because I've found it easier for people to grasp how grids work than to understand the nuances of floats.</p>
<h3>The future is brighter</h3>
<p>While I don't think we'll ever <em>love</em>&nbsp;CSS, it's going to get a lot cleaner in the coming years. The <a href="http://www.w3.org/TR/css3-flexbox/">flexible box model</a>&nbsp;should make more trickly layout problems easy to fix. And the eventual obsolecence of IE7 will make CSS authoring more fun still.</p>
<p>In the mean time, keep practicing! And please send along your candidates for CSS code smells.</p>]]></description><wfw:commentRss>http://4cupsr.us/blog/rss-comments-entry-15102192.xml</wfw:commentRss></item></channel></rss>