<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hartley Brody</title>
	<atom:link href="https://blog.hartleybrody.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.hartleybrody.com</link>
	<description>Hartley is a 20-something trying to learn as much as he can while adjusting to the lifestyle of a grown-up. He works on the marketing team at HubSpot where he gets to build cool things and work with great people. He&#039;s a world-class marketer with a hacker mentality. Author of Marketing for Hackers.</description>
	<lastBuildDate>Tue, 16 Aug 2016 16:08:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.5.3</generator>
	<item>
		<title>How to Scrape Amazon.com: 19 Lessons I Learned While Crawling 1MM+ Product Listings</title>
		<link>https://blog.hartleybrody.com/scrape-amazon/</link>
		<pubDate>Wed, 03 Aug 2016 18:55:13 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2956</guid>
		<description><![CDATA[In its simplest form, web scraping is about making requests and extracting data from the response. For a small web scraping project, your code can be simple. You just need to find a few patterns in the URLs and in the HTML response and you&#8217;re in business. But everything changes when you&#8217;re trying to pull [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In its simplest form, <a href="/web-scraping/">web scraping is about making requests and extracting data from the response</a>. For a small web scraping project, your code can be simple. You just need to find a few patterns in the URLs and in the HTML response and you&#8217;re in business.</p>
<p>But everything changes when you&#8217;re trying to <strong>pull over 1,000,000 products from the largest ecommerce website on the planet.</strong></p>
<p><img src="https://i.imgur.com/2kKKyvv.jpg" alt="Amazon Crawling" class="aligncenter" width="500" /></p>
<p>When crawling a sufficiently large website, the actual web scraping (making requests and parsing HTML) becomes a very minor part of your program. Instead, you spend a lot of time figuring out how to keep the entire crawl running smoothly and efficiently.</p>
<p>This was my first time doing a scrape of this magnitude. I made some mistakes along the way, and learned a lot in the process. It took several days (and quite a few false starts) to finally crawl the millionth product. If I had to do it again, knowing what I now know, it would take just a few hours.</p>
<p>In this article, I&#8217;ll walk you through the high-level challenges of pulling off a crawl like this, and then run through all of the lessons I learned. At the end, I&#8217;ll show you the code I used to <strong>successfully pull 1MM+ items from amazon.com.</strong></p>
<p>I&#8217;ve broken it up as follows:</p>
<ol>
<li><a href="/scrape-amazon/#challenges">High-Level Challenges I Ran Into</a></li>
<li><a href="/scrape-amazon/#crawl-lessons">Crawling At Scale Lessons Learned</a></li>
<li><a href="/scrape-amazon/#amazon-lessons">Site-Specific Lessons I Learned About Amazon.com</a></li>
<li><a href="/scrape-amazon/#code">How My Finished, Final Code Works</a></li>
</ol>
<hr>
<p><span id="more-2956"></span><br />
<h3 id="challenges">High-Level Challenges I Ran Into</h3>
<p>There were a few challenges I ran into that you&#8217;ll see on any large-scale crawl of more than a few hundred pages. These apply to crawling any site or running a sufficiently large crawling operation across multiple sites.</p>
<h4>High-Performance is a Must</h4>
<p><img src="https://i.imgur.com/uWe4o9u.jpg" alt="Now that is high-throughput" class="aligncenter" width="500" /></p>
<p>In a simple web scraping program, you make requests in a loop &#8212; one after the other. If a site takes 2-3 seconds to respond, then you&#8217;re looking at making 20-30 requests a minute. At this rate, your crawler would have to run for a month, non-stop before you made your millionth request.</p>
<p>Not only is this very slow, it&#8217;s also wasteful. The crawling machine is sitting there idly for those 2-3 seconds, waiting for the network to return before it can really do anything or start processing the next request. That&#8217;s a lot of dead time and wasted resources.</p>
<p>When thinking about crawling anything more than a few hundred pages, you really have to think about putting the pedal to the metal and pushing your program until it hits the bottleneck of some resources &#8212; most likely network or disk IO.</p>
<p>I didn&#8217;t need to do this for my purposeses (more later), but you can also think about ways to scale a single crawl across multiple machines, so that you can even start to push past single-machine limits.</p>
<h4>Avoiding Bot Detection</h4>
<p><img src="https://i.imgur.com/0gvAqwn.jpg" alt="Battling with Bots" class="aligncenter" width="500" /></p>
<p>Any site that has a vested interest in protecting its data will usually have some basic anti-scraping measures in place. Amazon.com is certainly no exception.</p>
<p>You have to have a few strategies up your sleeve to make sure that individual HTTP requests &#8212; as well as the larger pattern of requests in general &#8212; don&#8217;t appear to be coming from one centralized bot.</p>
<p>For this crawl, I made sure to:</p>
<ol>
<li>Spoof headers to make requests seem to be coming from a browser, not a script</li>
<li>Rotate IPs using a list of over 500 proxy servers I had access to</li>
<li>Strip &#8220;tracking&#8221; query params from the URLs to remove identifiers linking requests together</li>
</ol>
<p>More on all of these in a bit.</p>
<h4>The Crawler Needed to be Resilient</h4>
<p><img src="https://i.imgur.com/TKZrEyX.jpg" alt="Just Keep Swimming" class="aligncenter" width="500" /></p>
<p>The crawler needs to be able to operate smoothly, even when faced with common issues like network errors or unexpected responses. </p>
<p>You also need to be able to pause and continue the crawl, updating code along the way, without going back to &#8220;square one&#8221;. This allows you to update parsing or crawling logic to fix small bugs, without needing to rescrape everything you did in the past few hours.</p>
<p>I didn&#8217;t have this functionality initially and I regretted it, wasting tons of hours hitting the same URLs again and again whenever I need to make updates to fix small bugs affecting only a few pages.</p>
<hr>
<h3 id="crawl-lessons">Crawling At Scale Lessons Learned</h3>
<p>From the simple beginnings to the <a href="#code">hundreds of lines of python I ended up with</a>, I learned a lot in the process of running this project. All of these mistakes cost me time in some fashion, and learning the lessons I present here will make your amazon.com crawl much faster from start to finish.</p>
<h4>1. Do the Back of the Napkin Math</h4>
<p>When I did a sample crawl to test my parsing logic, I used a simple loop and made requests one at a time. After 30 minutes, I had pulled down about 1000 items.</p>
<p>Initially, I was pretty stoked. &#8220;Yay, my crawler <em>works</em>!&#8221; But when I turned it loose on a the full data set, I quickly realized it wasn&#8217;t feasible to run the crawl like this at full scale.</p>
<p>Doing the back of the napkin math, I realized I needed to be doing dozens of requests every second for the crawl to complete in a reasonable time (my goal was 4 hours).</p>
<p>This required me to go back to the drawing board.</p>
<h4>2. Performance is Key, Need to be Multi-Threaded</h4>
<p>In order to speed things up and not wait for each request, you&#8217;ll need to make your crawler multi-threaded. This allows the CPU to stay busy working on one response or another, even when each request is taking several seconds to complete.</p>
<p>You can&#8217;t rely on single-threaded, network blocking operations if you&#8217;re trying to do things quickly. I was able to get 200 threads running concurrently on my crawling machine, giving me a <strong>200x speed improvement</strong> without hitting any resource bottlenecks. </p>
<h4>3. Know Your Bottlenecks</h4>
<p>You need to keep an eye on the four key resources of your crawling machine (CPU, memory, disk IO and network IO) and make sure you know which one you&#8217;re bumping up against.</p>
<p>What is keeping your program from making 1MM requests all at once?</p>
<p>The most likely resource you&#8217;ll use up is your network IO &#8212; the machine simply won&#8217;t be capable of writing to the network (making HTTP requests) or reading from the network (getting responses) fast enough, and this is what your program will be limited by.</p>
<p><em>Note that it&#8217;ll likely take hundreds of simultaneous requests before you get to this point.</em> You should look at performance metrics before you assume your program is being limited by the network.</p>
<p>Depending on the size of your average requests and how complex your parsing logic, you also could run into CPU, memory or disk IO as a bottleneck.</p>
<p>You also might find bottlenecks before you hit any resource limits, like if your crawler gets blocked or throttled for making requests too quickly.</p>
<p>This can be avoided by properly disguising your request patterns, as I discuss below.</p>
<h4>4. Use the Cloud</h4>
<p>I used a single beefy EC2 cloud server from Amazon to run the crawl. This allowed me to spin up a very high-performance machine that I could use for a few hours at a time, without spending a ton of money.</p>
<p>It also meant that the crawl wasn&#8217;t running from my computer, burning my laptop&#8217;s resources and my local ISP&#8217;s network pipes.</p>
<h4>5. Don&#8217;t Forget About Your Instances <img src="https://s.w.org/images/core/emoji/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h4>
<p>The day after I completed the crawl, I woke up and realized I had left an m4.10xlarge running idly overnight. My reaction:</p>
<p><img src="https://i.imgur.com/Cr88uSY.gif" class="aligncenter" /></p>
<p>I probably wasted an extra $50 in EC2 fees for no reason. Make sure you stop your instances when you&#8217;re done with them!</p>
<h4>6. Use a Proxy Service</h4>
<p>This one is a bit of a no-brainer, since 1MM requests all coming from the same IP will definitely look suspicious to a site like amazon that can track crawlers.</p>
<p>I&#8217;ve found that it&#8217;s much easier (and cheaper) to let someone else orchestrate all of the proxy server setup and maintenance for hundreds of machines, instead of doing it yourself.</p>
<p>This allowed me to use one high-performance EC2 server for orchestration, and then rent bandwidth on hundreds of other machines for proxying out the requests.</p>
<p>I used <a href="https://proxybonanza.com/?aff_id=629" target="_blank">ProxyBonanza</a> and found it to be quick and simple to get access to hundreds of machines.</p>
<h4>7. Don&#8217;t Keep Much in Runtime Memory</h4>
<p>If you keep big lists or dictionaries in memory, you&#8217;re asking for trouble. What happens when you accidentally hit Ctrl-C when 3 hours into the scrape (as I did at one point)? Back to the beginning for you!</p>
<p>Make sure that the important progress information is stored somewhere more permanent.</p>
<h4>8. Use a Database for Storing Product Information</h4>
<p>Store each product that you crawl as a row in a database table. Definitely don&#8217;t keep them floating in memory or try to write them to a file yourself.</p>
<p>Databases will let you perform basic querying, exporting and deduping, and they also <a href="https://blog.hartleybrody.com/databases-intro/">have lots of other great features</a>. Just get in a good habit of using them for storing your crawl&#8217;s data.</p>
<h4>9. Use Redis for Storing a Queue of URLs to Scrape</h4>
<p>Store the &#8220;frontier&#8221; of URLs that you&#8217;re waiting to crawl in an in-memory cache like redis. This allows you to pause and continue your crawl without losing your place.</p>
<p>If the cache is accessible over the network, it also allows you to spin up multiple crawling machines and have them all pulling from the same backlog of URLs to crawl.</p>
<h4>10. Log to a File, Not `stdout`</h4>
<p>While it&#8217;s temptingly easy to simply <code>print</code> all of your output to the console via stdout, it&#8217;s much better to pipe everything into a log file. You can still view the log lines coming in, in real-time by running <code>tail -f</code> on the logfile.</p>
<p>Having the logs stored in a file makes it much easier to go back and look for issues. You can log things like network errors, missing data or other exceptional conditions.</p>
<p>I also found it helpful to log the current URL that was being crawled, so I could easily hop in, grab the current URL that was being crawled and see how deep it was in any category. I could also watch the logs fly by to get a sense of how fast requests were being made.</p>
<h4>11. Use `screen` to Manage the Crawl Process instead of your SSH Client</h4>
<p>If you SSH into the server and start your crawler with <code>python crawler.py</code>, what happens if the SSH connection closes? Maybe you close your laptop or the wifi connection drops. You don&#8217;t want that process to get orphaned and potentially die.</p>
<p>Using the built-in Unix <code>screen</code> command allows you to disconnect from your crawling process without worrying that it&#8217;ll go away. You can close your laptop and simple SSH back in later, reconnect to the screen, and you&#8217;ll see your crawling process still humming along.</p>
<h4>12. Handle Exceptions Gracefully</h4>
<p>You don&#8217;t want to start your crawler, go work on other stuff for 3 hours and then come back, only to find that it crashed 5 minutes after you started it.</p>
<p>Any time you run into an exceptional condition, simply log that it happened and continue. It makes sense to add exception handling around any code that interacts with the network or the HTML response.</p>
<p>Be especially aware of non-ascii characters breaking your logging.</p>
<hr>
<h3 id="amazon-lessons">Site-Specific Lessons I Learned About Amazon.com</h3>
<p>Every site presents its own web scraping challenges. Part of any project is getting to know which patterns you can leverage, and which ones to avoid.</p>
<p>Here&#8217;s what I found.</p>
<h4>13. Spoof Headers</h4>
<p>Besides using proxies, the other classic obfuscation technique in web scraping is to spoof the headers of each request. For this crawl, I just grabbed the User Agent that my browser was sending as I visited the site.</p>
<p>If you don&#8217;t spoof the User Agent, you&#8217;ll get a generic anti-crawling response for every request Amazon.</p>
<p>In my experience, there was no need to spoof other headers or keep track of session cookies. Just make a GET request to the right URL &#8212; through a proxy server &#8212; and spoof the User Agent and that&#8217;s it &#8212; you&#8217;re past their defenses.</p>
<h4>14. Strip Unnecessary Query Parameters from the URL</h4>
<p>One thing I did out of an abundance of caution was to strip out unnecessary tracking parameters from the URL. I noticed that clicking around the site seemed to append random IDs to the URL that weren&#8217;t necessary to load the product page.</p>
<p>I was a bit worried that they could be used to tie requests to each other, even if they were coming from different machines, so I made sure my program stripped down URLs to only their core parts before making the request.</p>
<h4>15. Amazon&#8217;s Pagination Doesn&#8217;t Go Very Deep</h4>
<p>While some categories of products claim to contain tens of thousands of items, Amazon will only let you page through about 400 pages per category. </p>
<p>This is a common limit on many big sites, including Google search results. Humans don&#8217;t usually click past the first few pages of results, so the sites don&#8217;t bother to support that much pagination. It also means that going too deep into results can start to look a bit fishy.</p>
<p>If you want to pull in more than a few thousand products per category, you need to start with a list of lots of smaller subcategories and paginate through each of those. But keep in mind that many products are listed in multiple subcategories, so there may be a lot of duplication to watch out for.</p>
<h4>16. Products Don&#8217;t Have Unique URLs</h4>
<p>The same product can live at many different URLs, even after you strip off tracking URL query params. To dedupe products, you&#8217;ll have to use something more specific than the product URL.</p>
<p>How to dedupe depends on your application. It&#8217;s entirely possible for the exact same product to be sold by multiple sellers. You might look for ISBN or SKU for some kinds of products, or something like the primary product image URL or a hash of the primary image.</p>
<h4>17. Avoid Loading Detail Pages</h4>
<p>This realization helped me <strong>make the crawler 10-12x faster</strong>, and much simpler. I realized that I could grab all of the product information I needed from the subcategory listing view, and didn&#8217;t need to load the full URL to each of the products&#8217; detail page.</p>
<p>I was able to grab 10-12 products with one request, including each of their titles, URLs, prices, ratings, categories and images &#8212; instead of needing to make a request to load each product&#8217;s detail page separately.</p>
<p>Whether you need to load the detail page to find more information like the description or related products will depend on your application. But if you can get by without it, you&#8217;ll get a pretty nice performance improvement.</p>
<h4>18. Cloudfront has no Rate Limiting for Amazon.com Product Images</h4>
<p>While I was using a list of 500 proxy servers to request the product listing URLs, I wanted to avoid downloading the product images through the proxies since it would chew up all my bandwidth allocation.</p>
<p>Fortunately, the product images are served using Amazon&#8217;s CloudFront CDN, which doesn&#8217;t appear to have any rate limiting. I was able to download over 100,000 images with no problems &#8212; until my EC2 instance ran out of disk space.</p>
<p>Then I broke out the image downloading into its own little python script and simply had the crawler store the URL to the product&#8217;s primary image, for later retrieval.</p>
<h4>19. Store Placeholder Values</h4>
<p>There are lots of different types of product pages on Amazon. Even within one category, there can be several different styles of HTML markup on individual product pages, and it might take you a while to discover them all.</p>
<p>If you&#8217;re not able to find a piece of information in the page with the extractors you built, store a placeholder value like &#8220;&lt;No Image Detected&gt;&#8221; in your database.</p>
<p>This allows you to periodically query for products with missing data, visit their product URLs in your browser and find the new patterns. Then you can pause your crawler, update the code and then start it back up again, recognizing the new pattern that you had initially missed.</p>
<hr>
<h3 id="code">How My Finished, Final Code Works</h3>
<p><em><strong>TL;DR:</strong> Here&#8217;s <a href="https://github.com/hartleybrody/public-amazon-crawler" target="_blank">a link to my code on github</a>. It has a readme for getting you setup and started on your own amazon.com crawler.</em></p>
<p>Once you get the code downloaded, the libraries installed and the connection information stored in the settings file, you&#8217;re ready to start running the crawler!</p>
<p>If you run it with the &#8220;start&#8221; command, it looks at the list of category URLs you&#8217;re interested in, and then goes through each of those to find all of the subcategory URLs that are listed on those page, since paginating through each category is limited (see lesson #15, above).</p>
<p>It puts all of those subcategory URLs into a redis queue, and then spins up a number of threads (based on <code>settings.max_threads</code>) to process the subcategory URLs. Each thread pops a subcategory URL off the queue, visits it, pulls in the information about the 10-12 products on the page, and then puts the &#8220;next page&#8221; URL back into the queue.</p>
<p>The process continues until the queue is empty or <code>settings.max_requests</code> has been reached.</p>
<p>Note that the crawler does not currently visit each individual product page since I didn&#8217;t need anything that wasn&#8217;t visible on the subcategory listing pages, but you could easily add another queue for those URLs and a new function for processing those pages.</p>
<hr>
<p>Hope that helps you get a better sense of how you can conduct a large scrape of amazon.com or a similar ecommerce website.</p>
<p>If you&#8217;re interested in learning more about web scraping, <a href="https://scrapethissite.com/lessons/sign-up/">I have an online course that covers the basics and teaches you how to get your own web scrapers running in 15 minutes</a>.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Facebook Messenger Bot Tutorial: Step-by-Step Instructions for Building a Basic Facebook Chat Bot</title>
		<link>https://blog.hartleybrody.com/fb-messenger-bot/</link>
		<pubDate>Wed, 15 Jun 2016 21:23:26 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2892</guid>
		<description><![CDATA[First there were desktop software products, then everything moved to the web. Then there were email-based products and even SMS-based ones. The latest craze in software interfaces is messenger bots, and Facebook has the largest chat platform by a long shot. In this tutorial, I&#8217;ll show you how to build your own Facebook Messenger Chat [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>First there were desktop software products, then everything moved to the web. Then there were email-based products and even SMS-based ones. The latest craze in software interfaces is messenger bots, and Facebook has the largest chat platform by a long shot.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-chatbot.png" alt="facebook-chatbot" width="500" class="aligncenter size-full wp-image-2916" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-chatbot.png 738w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-chatbot-300x169.png 300w" sizes="(max-width: 738px) 100vw, 738px" /></p>
<p>In this tutorial, I&#8217;ll show you how to build your own <strong>Facebook Messenger Chat Bot in python</strong>. We&#8217;ll use Flask for some basic web request handling, and we&#8217;ll deploy the app to Heroku.</p>
<p>Let&#8217;s get started.</p>
<p><span id="more-2892"></span><br />
<h3>Step #1: Create a Working Webhook Endpoint</h3>
<p>We&#8217;ll get into the meat of sending and receiving messages in a bit, but first you need to have a working endpoint that returns a 200 response code and echoes back some information in order to verify your bot with Facebook.</p>
<p><a href="https://github.com/hartleybrody/fb-messenger-bot" target="_blank"><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/fb-chat-bot-github-1024x533.png" alt="fb-chat-bot-github" width="500" class="aligncenter size-large wp-image-2921" /></a></p>
<p>First, <code>git clone</code> the <a href="https://github.com/hartleybrody/fb-messenger-bot" target="_blank">Github repository that I set up for this project</a>:</p>
<p><code>git clone git@github.com:hartleybrody/fb-messenger-bot.git</code></p>
<p>Then, <code>cd</code> into it and install python dependencies:<br />
<code><br />
mkvirtualenv test-bot<br />
pip install -r requirements.txt<br />
</code></p>
<p>For simplicity, we&#8217;ll deploy this to Heroku, but you could also deploy this Flask web app to any server you have access to.</p>
<p>Assuming you already have the <a href="https://toolbelt.heroku.com/" target="_blank">Heroku CLI Toolbelt</a> installed, you can run</p>
<p><code>heroku create</code></p>
<p>to get your new application setup.</p>
<p>We&#8217;re also using Heroku&#8217;s convention for the Procfile to tell it how to run the app, but you could set this up on your own server with something like nginx in front of one or more gunicorn processes.</p>
<p>To verify that Heroku can run things locally on your machine, start your local server with:</p>
<p><code>heroku local</code></p>
<p>Then, in your browser, visit <a href="http://localhost:5000/" target="_blank">http://localhost:5000/</a> and you should see &#8220;Hello world&#8221;.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/localhost-1024x628.png" alt="localhost" width="500" class="aligncenter size-large wp-image-2924" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/localhost-1024x628.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/localhost-300x184.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/localhost-768x471.png 768w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/localhost.png 1252w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Kill the local server with <code>Ctrl+C</code>. To deploy this endpoint to Heroku</p>
<p><code>git push heroku master</code></p>
<p>And to open it in your browser</p>
<p><code>heroku open</code></p>
<p>Now you&#8217;ve got a &#8220;working&#8221; webhook URL that you can use to setup your bot. Make sure you grab the full <code>https://*.herokuapp.com</code> URL from your browser since we&#8217;ll need it in a bit.</p>
<h3>Step #2: Create a Facebook Page</h3>
<p>If you don&#8217;t already have one, you need to <a href="https://www.facebook.com/pages/create/" target="_blank">create a Facebook Page</a>. The Facebook Page is the &#8220;identity&#8221; of your bot, including the name and image that appears when someone chats with it inside Facebook Messenger.</p>
<p>If you&#8217;re just creating a dummy one for your chatbot, it doesn&#8217;t really matter what you name it or how you categorize it. You can skip through most of the setup steps.</p>
<p>In order to communicate with your bot, people will need to go through your Page, which we&#8217;ll look at in a bit.</p>
<h3>Step #3: Create a Facebook App</h3>
<p>Go to the <a href="https://developers.facebook.com/quickstarts/?platform=web" target="_blank">Facebook Developer&#8217;s Quickstart Page</a> and click &#8220;Skip and Create App ID&#8221; at the top right. Then create a new Facebook App for your bot and give your app a name, category and contact email.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/create-fb-app-1024x604.png" alt="create-fb-app" width="500" class="aligncenter size-large wp-image-2926" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/create-fb-app-1024x604.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/create-fb-app-300x177.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/create-fb-app-768x453.png 768w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/create-fb-app.png 1486w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>You&#8217;ll see your new App ID at the top right on the next page. Scroll down and click &#8220;Get Started&#8221; next to Messenger.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-fb-messenger-app-1024x613.png" alt="setup-fb-messenger-app" width="500" class="aligncenter size-large wp-image-2944" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-fb-messenger-app-1024x613.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-fb-messenger-app-300x180.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-fb-messenger-app-768x460.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h3>Step #4: Setup Your Messaging App</h3>
<p>Now you&#8217;re in the Messenger settings for your Facebook App. There are a few things in here you&#8217;ll need to fill out in order to get your chatbot wired up to the Heroku endpoint we setup earlier.</p>
<p><strong>Generate a Page Access Token</strong><br />
Using the Page you created earlier (or an existing Page), click through the auth flow and you&#8217;ll receive a Page Access Token for your app.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/page-access-token-generation-1024x346.png" alt="page-access-token-generation" width="500" class="aligncenter size-large wp-image-2931" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/page-access-token-generation-1024x346.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/page-access-token-generation-300x102.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/page-access-token-generation-768x260.png 768w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/page-access-token-generation.png 1596w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Click on the Page Access Token to copy it to your clipboard. You&#8217;ll need to set it as an environment variable for your Heroku application. On the command line, in the same folder where you cloned the application, run:</p>
<p><code>heroku config:add PAGE_ACCESS_TOKEN=$your_page_token_here</code></p>
<p>This token will be used to authenticate your requests whenever you try to send a message or reply to someone. </p>
<p><strong>Setup Webhook</strong><br />
When you go to setup your webhook, you&#8217;ll need a few bits of information:</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-webhook-annotated-1024x491.png" alt="setup-webhook-annotated" width="500" class="aligncenter size-large wp-image-2949" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-webhook-annotated-1024x491.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-webhook-annotated-300x144.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/setup-webhook-annotated-768x368.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<ul>
<li><strong>Callback URL</strong> &#8211; The Heroku (or other) URL that we setup earlier.</li>
<li><strong>Verification Token</strong> &#8211; A secret value that will be sent to your bot, in order to verify the request is coming from Facebook. Whatever value you set here, make sure you add it to your Heroku environment using <code>heroku config:add VERIFY_TOKEN=$your_verification_token_here</code></li>
<li><strong>Subscription Fields</strong> &#8211; This tells Facebook what messaging events you care about and want it to notify your webhook about. If you&#8217;re not sure, just start with &#8220;messages,&#8221; as you can change this later</li>
</ul>
<p>After you&#8217;ve configured your webhook, you&#8217;ll need to subscribe to the specific page you want to receive message notifications for.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/subscribe-to-page-1024x352.png" alt="subscribe-to-page" width="500" class="aligncenter size-large wp-image-2946" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/subscribe-to-page-1024x352.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/subscribe-to-page-300x103.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/subscribe-to-page-768x264.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Once you&#8217;ve gotten your Page Access Token and set up your webhook, make sure you set both the <code>PAGE_ACCESS_TOKEN</code> and <code>VERIFY_TOKEN</code> config values in your Heroku application, and you should be good to go!</p>
<h3>Step #5: Start Chatting with Your Bot</h3>
<p>Go to the Facebook Page you created and click on &#8220;Message&#8221; button, next to the &#8220;Like&#8221; button near the top of the page. This should open a message pane with your Page.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/fb-page-chat-bot-1024x668.png" alt="fb-page-chat-bot" width="500" class="aligncenter size-large wp-image-2947" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/fb-page-chat-bot-1024x668.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/fb-page-chat-bot-300x196.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/fb-page-chat-bot-768x501.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Start sending your Page messages and the bot should reply!</p>
<p>To see what&#8217;s happening, check the logs of your application</p>
<p><code>heroku logs -t</code></p>
<p>You should see the POST data that Facebook is sending to your endpoint whenever a new message is sent to your Page&#8217;s bot.</p>
<p>Here&#8217;s an example JSON POST body that I got when I sent &#8220;does this work?&#8221; to my bot</p>
<pre>
        {
            "object":"page",
            "entry":[
                {
                    "messaging":[
                        {
                            "message":{
                                "text":"does this work?",
                                "seq":20,
                                "mid":"mid.1466015596912:7348aba4de4cfddf91"
                            },
                            "timestamp":1466015596919,
                            "sender":{
                                "id":"885721401551027"
                            },
                            "recipient":{
                                "id":"260317677677806"
                            }
                        }
                    ],
                    "time":1466015596947,
                    "id":"260317677677806"
                }
            ]
        }
</pre>
<p>By default, the bot should respond to everything with &#8220;got it, thanks!&#8221;</p>
<h3>Step #6: Customize Your Bot&#8217;s Behavior</h3>
<p>Here&#8217;s where we finally start to dive into the code.</p>
<p>There are really only two key parts to a messaging bot: receiving and sending messages</p>
<p><strong>Receiving Messages</strong><br />
We handle incoming messages starting <a href="https://github.com/hartleybrody/fb-messenger-bot/blob/master/app.py#L24" target="_blank">on line 24 inside app.py, in our `webhook()` view function.</a></p>
<p>First we load in the JSON POST data that&#8217;s sent to the webhook from Facebook whenever a new messaging event is triggered, usually when someone sends a message to our Page.</p>
<p>Then we loop over each entry &#8212; in my testing experience, there&#8217;s only ever been one entry sent to the webhook at a time.</p>
<p>Then we loop over each of the messaging events. Here, there may be several messaging events.</p>
<p>In step #4, we told Facebook what message types we want our webhook to be notified about. If you followed my advice, then our endpoint will only receive &#8220;message&#8221; events, but we could also receive delivery confirmations, optins and postbacks (more on those later). I left some code in place for detecting those other types of messaging events, but I don&#8217;t actually handle them.</p>
<p>The messaging event that will be most useful to most applications will be the &#8220;message&#8221; event, meaning someone has sent your Page a new message. I wrote some basic code to handle that event, parsing out the sender&#8217;s ID, and simply responding back to them.</p>
<p><strong>Sending Messages</strong><br />
In order to send a simple text message, you only need two things:</p>
<ul>
<li>the recipient&#8217;s Facebook ID</li>
<li>the text of the message you want to send</li>
</ul>
<p>I&#8217;ve created a simple <code>send_message()</code> function that automatically hits the Facebook API and sends those pieces of information.</p>
<p>Remember that the request is authenticated using the <code>PAGE_ACCESS_TOKEN</code> environment variable that we got back in step #4.</p>
<p>There are many more complex message types you can send, including messages with images and buttons. <a href="https://developers.facebook.com/docs/messenger-platform/implementation#send_message" target="_blank">More information on those message types here.</a></p>
<p>Important to note is the ability to send a &#8220;postback&#8221; button in a message. These are essentially buttons that, when tapped by a user, send a postback messaging event to your webhook. </p>
<p>This essentially allows users to &#8220;press buttons&#8221; in your app, all while inside Facebook Messenger. You could use this for placing an order, confirming a request or lots of other things.</p>
<p>Whenever a user taps a postback button, your webhook is notified and can perform any sort of subsequent follow-up action necessary.</p>
<h3>Step #7: Submit Your App to be Reviewed</h3>
<p>While you&#8217;re testing your bot, only you and other Page admins can message with the bot directly. You have to go through a review process before your bot is open to the world, ready to chat with anyone.</p>
<p>Facebook seems to be very thorough in their review process, and with good reason. The code for a messaging bot runs on your own servers and could change at any time, without Facebook knowing.</p>
<p>They seem to be trying hard to make sure you&#8217;re a good actor, and not submitting a simple dummy app to get approved, only to change it to some spam bot down the road.</p>
<p>Obviously, they could still revoke your API access tokens if you did that, but they&#8217;d rather not have any abuse on the Messenger platform at all.</p>
<p>Go back to your Messenger App Settings page that we used in Step #4. Scroll down to &#8220;App Review for Messenger&#8221; and click &#8220;Request Permissions.&#8221;</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/chat-bot-approval-1024x556.png" alt="chat-bot-approval" width="500" class="aligncenter size-large wp-image-2935" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/chat-bot-approval-1024x556.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/chat-bot-approval-300x163.png 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/chat-bot-approval-768x417.png 768w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/chat-bot-approval.png 1598w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Request the permissions that you need, and then you&#8217;ll be taken to the &#8220;Review Status&#8221; page. This page requires a ton of information to ensure that developers aren&#8217;t going to abuse the platform.</p>
<p>It requires you to</p>
<ul>
<li>check several boxes verifying that you&#8217;ve read their policies and guidelines</li>
<li>promise you won&#8217;t engage in unsolicited, outbound messaging</li>
<li>describe how you&#8217;re going to interact with users through your bot</li>
<li>provide a test user that the review team can use to interact with your bot</li>
<li>upload a screencast of you interacting with your bot via Messenger</li>
<li>have a privacy policy</li>
<li>verify that you&#8217;re explaining the bot and setting expectations with users</li>
</ul>
<p>On this page, you can also ask to be granted extra information about users, like their email or profile information.</p>
<p>Then it all goes to the Facebook review team to sign off and give you full access to the Messenger platform. <a href="https://developers.facebook.com/docs/messenger-platform/app-review" target="_blank">More information about the approval process here.</a></p>
<hr>
<p>Even if you don&#8217;t intend to go all the way through the review process, hopefully you&#8217;ve learned a thing or two about how to build a simple chat bot for Facebook Messenger.</p>
<p><a href="https://github.com/hartleybrody/fb-messenger-bot/">Check out my code here</a>.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-messenger.png" alt="facebook-messenger" width="500" class="aligncenter size-full wp-image-2919" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-messenger.png 720w, https://blog.hartleybrody.com/wp-content/uploads/2016/06/facebook-messenger-300x142.png 300w" sizes="(max-width: 720px) 100vw, 720px" /></p>
]]></content:encoded>
			</item>
		<item>
		<title>7 Reasons I Won&#8217;t Sign Your NDA Before a Coffee Meeting</title>
		<link>https://blog.hartleybrody.com/wont-sign-nda/</link>
		<pubDate>Wed, 17 Feb 2016 20:17:38 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2850</guid>
		<description><![CDATA[In my work as a full stack web developer, I often meet clients who request that I sign a Non-Disclosure Agreement (NDA) at various stages of the project. By signing an NDA, the client is basically asking me to agree that I won&#8217;t take their idea and work on it myself, or share it with [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>In my work as a <a href="https://www.hartleybrody.com" target="_blank">full stack web developer</a>, I often meet clients who request that I sign a Non-Disclosure Agreement (NDA) at various stages of the project.</p>
<p>By signing an NDA, the client is basically asking me to agree that I won&#8217;t take their idea and work on it myself, or share it with anyone else who will.</p>
<p>For most entrepreneurs, that sounds like a smart idea, right?</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2016/02/A4L95KYSJ2-1024x816.jpg" alt="arms folded" width="600" class="aligncenter size-large wp-image-2875" srcset="https://blog.hartleybrody.com/wp-content/uploads/2016/02/A4L95KYSJ2-1024x816.jpg 1024w, https://blog.hartleybrody.com/wp-content/uploads/2016/02/A4L95KYSJ2-300x239.jpg 300w, https://blog.hartleybrody.com/wp-content/uploads/2016/02/A4L95KYSJ2-768x612.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>Here&#8217;s why I won&#8217;t sign them.</p>
<p><span id="more-2850"></span><br />
<h3>I Hear a Lot of Ideas</h3>
<p>For every client that I end up starting a project with, I often talk to a dozen different businesses at various stages of needing help. As such, I hear lots of product ideas in any given week.</p>
<p>Have you ever started a sentence with &#8220;Oh, I can&#8217;t remember where I read this, but&#8230;&#8221; It&#8217;s hard to keep track of who told me what when you consider the sheer number of business ideas and products that I hear.</p>
<p>Similarly, it&#8217;s hard for me to keep track of which ideas are protected by an NDA. It&#8217;s not worth my time to make a catalogue of who told me exactly what idea and what agreement I had with them. It&#8217;s much easier to simply never sign NDAs.</p>
<h3>No Value for Me</h3>
<p>If you ask me to sign an NDA before we even have an introductory meeting to talk about the project, then by definition I know very little about you or your idea.</p>
<p>In the legal system, whenever two parties sign a contract, there&#8217;s a concept of &#8220;<a href="https://en.wikipedia.org/wiki/Consideration" target="_blank">consideration</a>&#8221; which basically means that all parties are receiving something of value by signing.</p>
<p>I don&#8217;t even know what we&#8217;re going to be talking about yet! How am I supposed to know what the value is or what I&#8217;m getting by signing the NDA?</p>
<h3>Creates Liability for Me</h3>
<p>Without knowing anything about your business, I can&#8217;t know ahead of time what ideas I&#8217;m agreeing to not compete with you on.</p>
<p>What if you tell me the idea and it&#8217;s something I already worked on or have thought of myself? Now you have a claim to any ideas I might already have about that topic.</p>
<h3>Creates Liability for my Other Clients</h3>
<p>Similarly, if I&#8217;m working with another client &#8212; or end up working with someone down the line &#8212; and that person comes up with their own version of your idea on their own, I could open <em>them</em> to liability.</p>
<p>If you find out that I worked on a project that sounds similar to your idea, you&#8217;d sue me and potentially my other client. I wouldn&#8217;t want to expose my other clients to that risk.</p>
<h3>Sign of a Worthless Idea</h3>
<p>Most experienced entrepreneurs know that ideas are a dime a dozen. I have several notebooks full of &#8220;million dollar startup&#8221; ideas lying around my apartment.</p>
<p><em>Execution</em> on an idea is what matters. That&#8217;s what creates a valuable business. If the idea itself is so easy to execute on that it must be kept secret, then it&#8217;s probably not very strong.</p>
<h3>Sign of an Overly Litigious Client</h3>
<p>I&#8217;m a small business too, and as a small business owner, I want to play it conservative and keep myself out of any potential legal trouble.</p>
<p>As a contractor who relies on my reputation, I work on relationships founded in trust and us both keeping up our ends of the bargain on a good-faith gentlemen&#8217;s agreement.</p>
<p>Why would I intentionally meet with a potential client who comes in guns blazing with legal documents for me to sign? That&#8217;s a big red flag that you&#8217;re not very trusting and likely not trustworthy.</p>
<h3>They&#8217;re not really worth anything</h3>
<p>Now you may be reading all of this thinking &#8212; &#8220;woah woah woah, calm down! NDAs aren&#8217;t that big of a deal, I&#8217;m not going to sue you!&#8221;</p>
<p>You realize that&#8217;s the point of an NDA right? To make it easier for you to sue me?</p>
<p>If your legal advisor is &#8220;making&#8221; you have people sign it, just stop. NDAs are basically a super easy way for lawyers to cash in on naive first-time founders.</p>
<p>If you really think an NDA will stop someone from &#8220;stealing your idea&#8221; do some research into how valuable they are. Spoiler alert: they&#8217;re very rarely enforced, and the burden of proof is very high. You&#8217;re not likely to win, even in questionable cases.</p>
<hr>
<p>I hope that gives you a better idea of my perspective on the issue. If you&#8217;re still okay with chatting, I&#8217;m happy to proceed without an NDA in the early stages.</p>
<p>If we actually start <a href="https://blog.hartleybrody.com/building-products/">specing out a project together</a> and I&#8217;ll be getting into the guts of the execution, then I&#8217;d be happy to sign one.</p>
<p>But if you really insist on me signing one this early, then I&#8217;m afraid I must say no.</p>
<hr>
<p>More discussions on the topic:</p>
<ol>
<li><a href="https://www.reddit.com/r/freelance/comments/33jkrh/thoughts_on_requiring_a_deposit_for_signing_an_nda/" target="_blank">Thoughts on Requiring a Deposit for Signing an NDA?</a> (reddit)</li>
<li><a href="https://www.reddit.com/r/freelance/comments/2prcow/potential_client_has_fundamental_lack_of/" target="_blank">Potential Client has Fundamental Lack of Understanding of the Point of an NDA</a> (reddit)</li>
<li><a href="http://blog.jpl-consulting.com/2012/04/why-i-wont-sign-your-nda/#fnref-107-1">A similar article on the topic that I found after publishing mine. Hits a lot of the same points.</a> (jpl-consulting.com)</li>
<li><a href="https://news.ycombinator.com/item?id=3844893">Hacker News Discussion on &#8220;No I won&#8217;t sign your NDA, here&#8217;s why.&#8221;</a> (news.ycombinator.com)</li>
</ol>
<hr>
]]></content:encoded>
			</item>
		<item>
		<title>The 3 Mistakes Every Junior Developer Makes (And How to Stop Making Them)</title>
		<link>https://blog.hartleybrody.com/junior-developer-mistakes/</link>
		<pubDate>Wed, 14 Oct 2015 19:40:06 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2726</guid>
		<description><![CDATA[As more and more people are learning to code, there are an increasing number of new developers in the work force. Code bootcamps are springing up everywhere that promise to land candidates a job with only a few months of experience. Having worked with a number of junior developers (and having been one myself, at [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>As more and more people are <a href="https://blog.hartleybrody.com/learning-to-code/">learning to code</a>, there are an increasing number of new developers in the work force. Code bootcamps are springing up everywhere that promise to land candidates a job with only a few months of experience.</p>
<p>Having worked with a number of junior developers (and having been one myself, at one point <img src="https://s.w.org/images/core/emoji/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ) I&#8217;ve noticed a lot of the same mistakes crop up.</p>
<p>In an effort to help junior developers <a href="https://blog.hartleybrody.com/hacker-developer-engineer/">level up to eventually become engineers</a>, I decided to enumerate some of the mistakes I see most often, as well as my recommended solutions and takeaways.</p>
<p><span id="more-2726"></span><br />
<h3>Saying You&#8217;re &#8220;Done&#8221; with a Task Prematurely</h3>
<p>This is probably the most common so I mention it first. New developers have tendency to slap the last semicolon onto whatever code they&#8217;re writing, hastily commit it and proudly declare that they&#8217;re &#8220;done&#8221; to the rest of the team.</p>
<p>As soon as they&#8217;ve finished their first pass at an implementation, it&#8217;s &#8220;ready&#8221; for code review and testing. Except usually, it&#8217;s not.</p>
<p>Features of the product are very obviously broken, and it only takes someone a few seconds to notice. Or their code only implements half of the features it was supposed to, or doesn&#8217;t work for common use cases. </p>
<p>Since the junior developer has been heads down in the weeds wrestling with language syntax or the API of some new library, they haven&#8217;t yet lifted their head to survey the scene of where they came from and where they still need to go.</p>
<p>As a result, code reviews can be brutal, product and business stake holders are confused about why things don&#8217;t work as they should, and the team generally loses faith in the junior developer&#8217;s autonomy. &#8220;Why would she say this is done when it clearly needs more work?&#8221;</p>
<p><strong>Solution</strong><br />
The solution I always advocate for is the &#8220;step away from your desk&#8221; maneuver. If you&#8217;ve pushed up your last commit and are ready to check off the asana ticket or move the trello card &#8212; PAUSE. </p>
<p>Go get some water, walk around for 5 minutes and then come back to your desk. Reread the spec or ticket that you&#8217;re working from, and go back through the email thread where the last-minute adjustments were made. Make sure that everything that&#8217;s supposed to be in there is.</p>
<p>Then, try to actually use the feature you just built. Do a bit of your own quality assurance, even if that&#8217;s supposed to be &#8220;someone else&#8217;s job&#8221;. Click around the product and make sure nothing is obviously wrong.</p>
<p><strong>Takeaway</strong><br />
As an engineer, your job isn&#8217;t just to write code, it&#8217;s to build a product or add features &#8212; and do no harm in the process.</p>
<p>Putting in the extra few minutes to review your work before you show it off will save you lots of embarrassment and help build the team&#8217;s trust that you know what you&#8217;re doing.</p>
<h3>Implementing the First Solution You Think Of</h3>
<p>Most of a junior developer&#8217;s first few projects will be largely spec&#8217;d out for them. They&#8217;ll be handed not only &#8220;what&#8221; to build, but also a list of steps for &#8220;how&#8221; to build it, at a high level.</p>
<p>But eventually, there will come a time when the team lead decides to trust a new developer to come up with their own technical implementation plan. And while this can be a great chance for someone who is newer to &#8220;earn their stripes,&#8221; it&#8217;s often a place where many falter.</p>
<p>The developer will come up with a plan forward, and stop there. &#8220;I&#8217;ve got it!&#8221;</p>
<p>The reality in software is that there are often dozens of different ways to implement something. Some solutions may reuse existing parts, while others may require new dependencies, abstractions or technologies.</p>
<p>To feel confident about a path forward, a good engineer will think through and then weigh the pros and cons of multiple potential solutions before establishing a path forward.</p>
<p>&#8220;We could use this library, but that adds a dependency. Or we could implement it ourselves, but it might take a while and be harder to test.&#8221;</p>
<p>When the junior developer presents their plan to the team and the team starts asking questions about it, the developer is often caught off guard, having not really considered where their plan might have some holes in it, or why it&#8217;s better than competing ideas.</p>
<p><strong>Solution</strong><br />
If you&#8217;re putting together a technical plan, try to come up with two or three alternative solutions, and understand when and how some are better or worse than each other.</p>
<p>Think up a list of a few pros and cons for each solution, considering both technical merits as well as business ones (&#8220;this would save us time, be cheaper to implement, etc&#8221;).</p>
<p><strong>Takeaway</strong><br />
The opportunity to come up with your first <a href="https://blog.hartleybrody.com/building-products/#technical-spec">technical spec or implementation plan</a> can be a great moment in your career.</p>
<p>To really hit it out of the park, do your research and be ready to defend your recommendations &#8212; don&#8217;t just present the first ones you come up with.</p>
<h3>Forgetting that Code is Read More than it is Written</h3>
<p>Most code that gets shipped will ideally live on production for more than just a few weeks. Which is plenty of time for everyone who worked on it to completely forget everything about it.</p>
<p>While it might be written over the course of a few hours or days, it&#8217;ll likely be read dozens of times over months and years by other engineers.</p>
<p>Every line of code that&#8217;s written should be clear, concise and self-documenting. Abstractions should make sense and be reusable in other contexts. Code should follow <a href="https://blog.hartleybrody.com/python-style-guide/">a style guide</a> for consistency.</p>
<p>By definition, someone who is new to the profession won&#8217;t have experience trying to find bugs or add features to code that they wrote a long time ago. </p>
<p>Hopefully they&#8217;ll have some experience reading and working with other engineers&#8217; old code, but they might not appreciate its elegance or clarity (or lack thereof).</p>
<p>One of the most important things you can learn as a junior developer is how to write clear, readable code. While your language&#8217;s interpreter might not care if you use confusing, nonsensical variable or function names, your colleagues certainly will.</p>
<p>While doing a code review a few years ago, I saw a javascript function called <code>is_ready()</code> which &#8212; from its name alone &#8212; would seem to return a boolean indicating whether something was &#8220;ready&#8221;. </p>
<p>But instead, it returned a jQuery node which resulted in code like <code>var modal = is_ready();</code>. And while that&#8217;s valid javascript that any browser would happily interpret, as a human I could make no sense of what was happening here.</p>
<p><strong>Solution</strong><br />
After you&#8217;ve gotten a new feature working, go back and read through all the code you just wrote. Maybe you started out calling a function one way but then you added more parameters and changed the implementation slightly and now it does something different. Rename it (and update all the places you call it) so that it reads closer to english and makes sense.</p>
<p><strong>Takeaway</strong><br />
Deciding what is &#8220;more readable&#8221; can sometimes be subjective. But it&#8217;s good practice to work on it in your own code and to try to recognize it in other people&#8217;s code as well.</p>
<h3>Final Thought</h3>
<p>If you&#8217;re a junior developer who feels like you&#8217;ve made some of these mistakes, don&#8217;t be discouraged! I decided to write this because I&#8217;ve seen so many new engineers who needed help learning about these same issues.</p>
<p>Being a good software engineer is an on-going learning progress &#8212; not just learning how to wrangle code, but also learning how to be a productive, effective and well-liked member of your team.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Scaling Your Web App 101: Lessons in Architecture Under Load</title>
		<link>https://blog.hartleybrody.com/scale-load/</link>
		<pubDate>Wed, 09 Sep 2015 00:47:41 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2514</guid>
		<description><![CDATA[It&#8217;s the classic champagne problem that most successful web apps will deal with &#8212; there are so many users on your site that things are starting to get bogged down. Pages load slowly, network connections start timing out and your servers are starting to creak under heavy load. Congratulations &#8212; your web app has hit [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/08/Champagne-Glass-212x300.jpg" alt="" width="100" class="alignright size-medium wp-image-2696" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/08/Champagne-Glass-212x300.jpg 212w, https://blog.hartleybrody.com/wp-content/uploads/2015/08/Champagne-Glass-723x1024.jpg 723w, https://blog.hartleybrody.com/wp-content/uploads/2015/08/Champagne-Glass.jpg 892w" sizes="(max-width: 212px) 100vw, 212px" />It&#8217;s the classic champagne problem that most successful web apps will deal with &#8212; there are so many users on your site that things are starting to get bogged down.</p>
<p>Pages load slowly, network connections start timing out and your servers are starting to creak under heavy load. Congratulations &#8212; your web app has hit scale!</p>
<p>But now what? You need to keep everything online and want the user&#8217;s experience to be fast &#8212; speed is a feature after all.</p>
<h3>Scaling Comes at a Price</h3>
<p>But before we go any further, an important caveat &#8212; you shouldn&#8217;t attempt to &#8220;scale&#8221; your web app before you&#8217;ve actually run into real scaling problems.</p>
<p>While it may be fun to read about Facebook&#8217;s architecture on their engineering blog, it can be disastrous to think that their solutions apply to your fledgling project.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/08/server-complexity.jpg" alt="server-complexity" width="500" class="aligncenter size-full wp-image-2699" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/08/server-complexity.jpg 648w, https://blog.hartleybrody.com/wp-content/uploads/2015/08/server-complexity-300x199.jpg 300w" sizes="(max-width: 648px) 100vw, 648px" /></p>
<p>A lot of the solutions to common scaling bottleneck introduce complexity, abstraction and indirection which makes systems more difficult to reason about. This can create all sorts of problems:</p>
<ul>
<li>Adding new features takes longer</li>
<li>Code can be harder to test</li>
<li>Finding and fixing bugs is more frustrating</li>
<li>Getting local and production environments to match is more difficult</li>
</ul>
<p>You should only be willing to accept these tradeoffs if your app is actually at the limits of what it can handle. Don&#8217;t introduce complexity until it&#8217;s warranted.</p>
<p>As the famous quote goes:</p>
<blockquote><p>
  Premature optimization is the root of all evil.<br />
  &mdash; <a href="http://premature optimization is the root of all evil" target="_blank">Donald Knuth</a>
</p></blockquote>
<p><span id="more-2514"></span><br />
<h3>Find the Actual Bottleneck using Metrics</h3>
<p>The first step to alleviating any problem &#8212; in software or otherwise &#8212; is to clearly and accurately define what the problem actually is.</p>
<blockquote><p>
  A problem well stated is a problem half-solved.<br />
  &mdash; Charles Kettering
</p></blockquote>
<p>For a web app that&#8217;s under too much load, that means finding out what resource your application is running out of on the server. </p>
<p>At a high level, the answer is usually going to be one of four things:</p>
<ol>
<li>Memory</li>
<li>CPU</li>
<li>Network I/O</li>
<li>Disk I/O</li>
</ol>
<p>Until you figure out what resource your application is bounded by, no one can help you scale your app and any solutions you come up with will be complete guesses.</p>
<p>Figuring out what you&#8217;re bounded by means checking your resource monitoring &#8212; or adding some if you&#8217;ve never done it before.</p>
<blockquote><p>
  What gets measured, gets managed<br />
  &mdash; <a href="https://www.entheos.com/quotes/by_teacher/Peter+Drucker" target="_blank">Peter Drucker</a>
</p></blockquote>
<p>If you&#8217;re managing your own servers, installing Munin is a great first step. If you&#8217;re running on Amazon&#8217;s EC2, AWS offers some decent instance monitoring out of the box. If you&#8217;re on Heroku, New Relic seems to be the best approach.</p>
<p>Use the graphs to look for spikes or flat tops. These usually imply that some resource was overwhelmed or completely at capacity and couldn&#8217;t handle any new operations.</p>
<p>If you don&#8217;t see any resources that seem to be at capacity, but your app is just slow in general, sprinkle some logging throughout heavily-used operations and check the logs to see if there&#8217;s some resource that&#8217;s taking a long time to load over the network.</p>
<p>It could be that another server is introducing delays &#8212; potentially your database server or a third-party API.</p>
<p>If you host your database on a different machine than your web servers (which you should) it&#8217;s important to check your resource monitoring for that machine as well as for your web servers.</p>
<p><strong>The database is usually the first place scaling issues start to show up.</strong></p>
<h3>Scaling a Web App from 10,000 Feet</h3>
<p>Now that you&#8217;ve got a much better sense of what the problem is, you should start to tackle it by trying the simplest solution that directly addresses the issues &#8212; remember, we&#8217;re always trying to avoid adding unnecessary complexity.</p>
<p><strong>At a high level, the goal of any scaling solutions should be to make your web stack do less work.</strong></p>
<p>If you&#8217;ve already figured out the answer to a query, reuse it. Or if you can avoid computing it or looking up all together, even better.</p>
<p>In a tangible sense, this usually means one of the following:</p>
<ul>
<li>Store results of common operations so you&#8217;re not repeating work</li>
<li>Reuse data you&#8217;ve already looked up, even if it&#8217;s a bit stale</li>
<li>Avoid doing complex operations in the request-response cycle</li>
<li>Don&#8217;t make requests from the client for things it already has</li>
</ul>
<p>These all basically boil down to some form of caching.</p>
<p>Memory is not only inexpensive to add to a server, it&#8217;s usually <a href="https://gist.github.com/jboner/2841832" target="_blank">many orders of magnitude faster</a> for accessing data when compared to disk or the network.</p>
<h3>Hosting Topology</h3>
<p>Whether your application is hosted in the cloud or on hardware, some part of your stack will inevitably fail. You should host and arrange your web servers to take this into account.</p>
<p><img src="http://i.imgur.com/OMcg9DZ.jpg" width="500" class="aligncenter" alt="If your domain points directly at a web server, your topology is bad and you should feel bad." /></p>
<p>Your domain should point to some sort of load balancer, which should then route requests between two or more web servers. </p>
<p>Not only does this setup make it easy to survive failures, it also makes handling increased load easier as well.</p>
<p>With a load balancer in front of two web servers, you can horizontally scale your application by bring up new web servers and putting them behind the load balancer. Now the requests are spread across more machines, meaning each one is doing less work overall.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/08/Screen-Shot-2015-08-24-at-6.58.07-PM-1024x610.png" alt="Ideal small web app topology" width="500" class="aligncenter size-large wp-image-2703" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/08/Screen-Shot-2015-08-24-at-6.58.07-PM-1024x610.png 1024w, https://blog.hartleybrody.com/wp-content/uploads/2015/08/Screen-Shot-2015-08-24-at-6.58.07-PM-300x179.png 300w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p>This allows you to grow your application gracefully over time, as well as handle temporary surges of traffic.</p>
<p>I should also add that setting up a load balancer and two web servers is a one-time setup that doesn&#8217;t add much on-going complexity, so it&#8217;s something you should consider doing up-front, even before you&#8217;ve run into scaling problems.</p>
<h3>Cache Database Queries</h3>
<p>This is one of the simplest improvements you can make. There&#8217;s usually a few common queries that make up the majority of load on your database.</p>
<p>Most databases support query logging, and there are many tools that will ingest those logs and run some analysis to tell you what queries are run most frequently, and what queries tend to take the longest to complete.</p>
<p>Simply cache the responses to frequent or slow queries so they live in memory on the web server and don&#8217;t require a round-trip over the network or any extra load on the database.</p>
<p>Obviously, data that&#8217;s cached can grow &#8220;stale&#8221; or out-of-date quickly if the underlying information in the database is updated frequently. Your business or product requirements will dictate what can or can&#8217;t be cached.</p>
<h3>Database Indexes</h3>
<p><a href="https://blog.hartleybrody.com/databases-intro/#indexes">Database indexes</a> ensure that needle-in-a-haystack type lookups are O(1) instead of O(n).</p>
<p>In layman&#8217;s terms, this means the database can find the right row immediately, rather than having to compare the queried conditions against every single row in the table.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/08/needle-in-haystack.jpg" alt="needle-in-haystack" width="500" class="aligncenter size-full wp-image-2706" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/08/needle-in-haystack.jpg 650w, https://blog.hartleybrody.com/wp-content/uploads/2015/08/needle-in-haystack-300x199.jpg 300w" sizes="(max-width: 650px) 100vw, 650px" /></p>
<p>If your table has tens of thousands of rows, this could shave noticeable amount of time off of any queries that use that column.</p>
<p>As a very simple example, if your application has profile pages that look up a user by their handle or username, an un-indexed query would examine every single row in the users table, looking for the ones where the &#8220;handle&#8221; column matched the handle in the URL.</p>
<p>By simply adding an index to that table for the &#8220;handle&#8221; column, the database could pull out that row immediately without requiring a full table scan.</p>
<h3>Session Storage</h3>
<p>A lot of applications handle sessions by storing a session ID in a cookie, and then storing the actual key/value data for each and every session in a database table.</p>
<p>If you find your database is getting slammed and your application does a lot of reading and writing to session data, it might be smart to rethink how and where you store your session data.</p>
<p>One option is to move your session storage to a faster, in-memory caching tool like redis or memcached. </p>
<p>Since these use volatile memory rather than persistent disk storage (which most databases use) they&#8217;re usually much faster to access &#8212; but the tradeoff is that you run the risk of losing all of your session data if the caching system needs to reboot or go offline.</p>
<p>Another option is to move the session information into the cookie itself. This obviously leaves it open to being tampered with by the user, so it shouldn&#8217;t be used if you&#8217;re storing anything private or sensitive in the session.</p>
<p>By moving session data out of the database, you&#8217;ll likely eliminate several database queries per page load, which can help your database&#8217;s performance tremendously.</p>
<h3>Run Computations Offline</h3>
<p>If you have some long-running queries or complex business logic that takes several seconds to run, you probably shouldn&#8217;t be running it in the request-response cycle during a page load.</p>
<p>Instead, make it &#8220;offline&#8221; and have a pool of workers that can chug away at it and put the results in a database or in-memory cache.</p>
<p>Then when the page loads, your web server can simply and quickly pull the precomputed data out of the cache and show it to the user.</p>
<p>A drawback here is that the data you&#8217;re showing the user is no longer &#8220;real time,&#8221; but having data that&#8217;s a few minutes old is often good enough for many use-cases.</p>
<p>If the data really takes a long time to generate, see if it can be parallelized so that multiple workers can work on different parts of the computation at the same time.</p>
<p>You&#8217;ll probably want to setup another cluster of machine for the work queue and the workers, since those will likely have different scaling properties than your web servers.</p>
<p>To take this architectural style to its logical conclusion, you can generate the HTML for your entire web app offline and simply serve it to users as static files.</p>
<p>This is the inspiration behind static site generators that are used to power a growing number of blogs, and it&#8217;s what the <a href="http://open.blogs.nytimes.com/2010/12/20/using-flat-files-so-elections-dont-break-your-server/?_r=0" target="_blank">New York Times did</a> to serve election night results.</p>
<h3>HTML Fragment Caching</h3>
<p>If you&#8217;re rendering HTML templates on the server-side, you want to avoid having your template engine wasting CPU cycles on every request generating the same HTML over and over again for content that doesn&#8217;t change often.</p>
<p>If there are certain sections of your site&#8217;s markup that change very infrequently &#8212; say the navigation, footer or sidebar &#8212; then that HTML should be cached somewhere and reused between requests.</p>
<p>Pay special attention to high-traffic pages. Sometimes you&#8217;ll be able to cache most of the page except for a few more dynamic or &#8220;real time&#8221; sections.</p>
<h3>Putting Work Into Queues</h3>
<p>We talked about using queues and workers for caching output that takes a long time to generate. You can also use workers for processing large amount of input asynchronously.</p>
<p>This has the effect of taking large, slow chunks of work and breaking them out from the main request-response cycle and taking it completely off your web servers.</p>
<p>Say you have a way for someone to import a CSV of their contacts and several people upload 50MB files. Instead of sending all of that data to a web server and having it take up memory and block the CPU while it&#8217;s being processed &#8212; put it on a static file host like s3 and have a worker that periodically checks for new file uploads and processes them offline.</p>
<p>You do have to be careful when you start putting lots of business logic into workers. You have to make sure you&#8217;re keeping track of what still needs to be processed, what is currently being processed, and what failed and needs to be processed again.</p>
<p>You also <a href="http://ferd.ca/queues-don-t-fix-overload.html" target="_blank">need to make sure you have enough workers running</a>, otherwise the work queue will grow longer and longer, leading to silent delays that are easy to miss.</p>
<h3>Client Side Improvements</h3>
<p>Of course, another great way to decrease the load on your web servers is to decrease the number of requests they have to deal with.</p>
<p>Even with the same number of users in your app, there are a number of client-side improvements that can lower the number of requests your web stack has to deal with.</p>
<p><strong>HTTP Caching</strong><br />
Just like you want to cache database queries to avoid regenerating answers you already know, you should avoid having the browser ask for content that it has already downloaded.</p>
<p>You should use HTTP caching headers for all of your static files &#8212; CSS, javascript and images.</p>
<p><a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en" target="_blank">Google</a> and <a href="http://www.mobify.com/blog/beginners-guide-to-http-cache-headers/" target="_blank">Mobify</a> provide great overviews on how to use the headers, and your web framework will likely have some helpers to make it even easier.</p>
<p><strong>Content Delivery Network</strong><br />
Ideally, your web servers wouldn&#8217;t serve any static content at all. You don&#8217;t need the overhead of loading your entire web framework or language runtime in order to serve a static file off of disk.</p>
<p>You should host your static content on a static file host that&#8217;s purpose built for sending files over the network. You can setup a <a href="https://www.nginx.com/resources/admin-guide/serving-static-content/" target="_blank">simple one with nginx</a> or use a dedicated service like Amazon&#8217;s S3.</p>
<p>When you&#8217;re splitting out your static content, it&#8217;s good to give the static file host a different CNAME or subdomain.</p>
<p>Once you&#8217;ve gotten that setup, it&#8217;s usually pretty straightforward to add a Content Delivery Network in front of your static file host.</p>
<p>This distributes your static content even faster &#8212; often without the requests ever reaching your web stack.</p>
<p>The CDN is essentially a geographically-distributed file cache that serves up copies of your static files that are often geographically closer to the end-user than your server.</p>
<p>The CDN will often have options to minify and gzip your static content to make the files even smaller and faster to send to the client.</p>
<h3>When All Else Fails</h3>
<p>If you&#8217;re still having issues with high load and you&#8217;ve cached as much as you can and your server budget is maxed out, there are still some less-than-ideal options you have to handle excess load.</p>
<p><strong>Back Pressure</strong><br />
Back pressure is just a way of telling people they have to wait because the system is slow. If you&#8217;ve ever gone tried going to a cafe, saw a line out the door and decided to go elsewhere &#8212; that&#8217;s a great example of back pressure.</p>
<p>Even without much work on your end, back pressure can be implicit. The site will be slow for users, which will discourage them from clicking around as much.</p>
<p>They also might see increased error rates when they try to load things &#8212; think Twitter&#8217;s Fail Whale.</p>
<p>You can also make back pressure explicit by adding messaging to the UI telling people that parts of your applications are temporarily disabled due to high demand.</p>
<p><strong>Shed Load</strong><br />
The other option is to shed load. You&#8217;re acknowledging that you&#8217;re not able to respond to everyone&#8217;s requests, so you&#8217;re not even going to try.</p>
<p>This is the nuclear option.  Set aggressive timeout in your web server and let requests hang and return blank pages. Some people&#8217;s data will get lost in cyberspace.</p>
<p>Try to add some temporary messaging to let people know that you&#8217;ll be back soon, but be prepared for a PR fallout.</p>
<p>&#8212;</p>
<p>Did you know I do consulting? If you need help scaling your web application, <a href="http://www.hartleybrody.com">drop me a line!</a></p>
<p><!--
----------
Guide to AWS: https://www.airpair.com/aws/posts/building-a-scalable-web-app-on-amazon-web-services-p1

    http://www.slideshare.net/brendangregg/performance-tuning-ec2-instances
  https://www.quora.com/How-do-you-make-a-website-run-fast
    https://twitter.com/billkarwin/status/487022360373895169

Changes to best practices in HTTP2: https://docs.google.com/presentation/d/1r7QXGYOLCh4fcUq0jDdDwKJWNqWK1o4xMtYpKZCJYjM/present?slide=id.g40fbe7d8c_051
 - don't domain shard (for more concurrent downloads)
 - don't concatenate
 - don't inline resources (ie CSS, JS)


In any high-volume application with an extremely large concurrent
user load, the database will usually be the final limiting factor in
how many transactions you can process concurrently. While various
caching technologies and database scaling products help to address
these issues, the fact remains that scaling out a normal application
for extreme loads is a very difficult proposition.
 - http://www.oreilly.com/programming/free/files/software-architecture-patterns.pdf


Prerender pages in their browser when you can predict what a user is about to do
  sends a GET request, so only for reading information, not performing actions
  https://developers.google.com/chrome/whitepapers/prerender


Third party APIs?
  make requests in parallel
  might need to negotiate higher rate limit (biz dev) or create multiple accounts (hack)

--></p>
]]></content:encoded>
			</item>
		<item>
		<title>Focus on the Product, Not the Code: How I Build Software for Clients</title>
		<link>https://blog.hartleybrody.com/building-products/</link>
		<pubDate>Wed, 22 Jul 2015 02:29:33 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2612</guid>
		<description><![CDATA[While there are tons of resources designed to help people learn to code, there aren&#8217;t as many resources for helping people learn to build software products, at a higher level. &#8220;Writing code&#8221; is largely a vocational skill, just like swinging a hammer is &#8212; but presumably you&#8217;re using that skill to actually build something. In [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>While there are tons of resources designed to help people <a href="https://blog.hartleybrody.com/learning-to-code/">learn to code</a>, there aren&#8217;t as many resources for helping people learn to build software products, at a higher level. </p>
<p>&#8220;Writing code&#8221; is largely a vocational skill, just like swinging a hammer is &#8212; but presumably you&#8217;re using that skill to actually <em>build</em> something.</p>
<p>In my experience, the reasons software projects fail &#8212; take too long, go over budget, are too complex &#8212; isn&#8217;t necessarily because of bad coding practices. It&#8217;s because there was too much focus on writing code, and not enough on <em>building a product</em>.</p>
<p>It&#8217;s deceptively simple (and all too common) for a non-technical person to come up with a few sentences describing an idea, shoot it to someone with coding chops and say &#8220;code this for me.&#8221;</p>
<p>It&#8217;s essentially the modern-day equivalent of someone sketching a building on a napkin, handing it to a carpenter and telling them to start swinging their hammer.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/07/shutterstock_152551241.jpg" alt="shutterstock_152551241" width="500" height="334" class="aligncenter size-full wp-image-2622" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/07/shutterstock_152551241.jpg 500w, https://blog.hartleybrody.com/wp-content/uploads/2015/07/shutterstock_152551241-300x200.jpg 300w" sizes="(max-width: 500px) 100vw, 500px" /></p>
<p>There are often huge structural decisions &#8212; as well as a million tiny implementation details &#8212; that need to be fleshed out before you even start writing a line of code. </p>
<p><strong>If the first thing you do with a product idea is start coding, your project is almost certainly doomed.</strong></p>
<p><span id="more-2612"></span><br />
<h3>Why You Need a Detailed Specification</h3>
<p>If you don&#8217;t have a detailed plan for how you&#8217;re going to build your product, then your engineers will inevitably make all sorts of seemingly small decisions that might not be in line with the original product vision, or what the business stakeholders need.</p>
<p>Those decisions will then have to be rolled back once the business stakeholder discover them, wasting a lot of time and energy, and also undermining the entire codebase.</p>
<p><strong>Engineers:</strong> What color should we make the carpets? Oh, they didn&#8217;t specify? Okay, well uh, red then?<br />
<strong>Business (after walking in and seeing the red carpets):</strong> Red is our main competitor&#8217;s color! How could you have chose this? Tear them up and recarpet the office with blue!</p>
<p>If you don&#8217;t have enough detail, then you&#8217;ll end up spending a ton of time writing code that ends up getting thrown out or refactored very quickly. This is the main source of delays in projects that have taken too long or gone over-budget.</p>
<p>If you had specified the carpet color from the beginning, then you wouldn&#8217;t have to lay it down twice, and spend the time and effort ripping it up in between.</p>
<p>But in a software project, sometimes these last-minute refactors are even more problematic than simply rewriting sections of code. Instead, they&#8217;re more akin to trying to change the foundation of a building from cement to wood pylons after several stories have already been built.</p>
<p>It&#8217;s not just that you have to change one or two pieces of the code &#8212; even small changes can have big ripple effects across the codebase. There are tons of abstractions and relationships in even seemingly simple pieces of software. Those all get created based on assumptions about how the finished product should look.</p>
<p>A real-world example of a seemingly minute detail that could have a huge implications on a project is deciding if a user is allowed to have multiple email addresses or just one. </p>
<p>Adding support for multiple email addresses &#8212; after the assumption was that there would only be one &#8212; isn&#8217;t simply a matter of adding a new field to the user table, it can have implications on the login system, notification and emailing systems, billing and admin, profiles, sharing and lots of other interconnected systems.</p>
<p><strong>It&#8217;s extremely important to get as many things right as you can in your first pass of writing code.</strong></p>
<p>The best way to avoid ambiguity and the problems and delays it creates is to come up with a plan. This should be done with all of the stakeholders &#8212; business and technical &#8212; working together, to explicitly lay out how the most important pieces of the product will look and function.</p>
<h3>How this Process Developed</h3>
<p>Before I was a freelancer, I was employee #1 at an ad tech startup. We weren&#8217;t a traditional single-product company. Instead, we built dozens of products, some of which were user facing, while many were internal ad- or analytics-related products just for us or our partners.</p>
<p>We had lots of product ideas that we wanted to test, but we couldn&#8217;t afford to spend months bringing them to market. We had to ship quickly, experiment and iterate, so our product development process had to be very efficient.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/07/fruitfly1-150x150.jpg" alt="fruitfly1" width="150" height="150" class="alignright size-thumbnail wp-image-2625" />Genetics researchers study fruit flies because their lifespans are so short, meaning researchers can observe many generations very quickly.</p>
<p>We built (and threw away) so many products in such short time periods, it proved to be a similarly effective laboratory for testing product development strategies.</p>
<p>We experimented with several different iterations of product development processes and were ruthlessly honest about what was working and what wasn&#8217;t. I learned a lot about building products in my time there. </p>
<p>I&#8217;ve since taken what we learned and the general processes we developed and adapted them for various clients across a dozen different projects.</p>
<h3 id="product-spec">The Product Spec</h3>
<p>The first step is to produce the Product Spec. This is a non-technical document and should usually be written by the client or product owner, with assistance where needed.</p>
<p>I have a Google Doc template which is essentially a structured list of questions designed to to help the client brain dump their ideas about the product.</p>
<p>The exact questions change from product to product, but there&#8217;s usually sections about the following:</p>
<ul>
<li><strong>Users:</strong> Who are they, what are their goals, why are they using the product?</li>
<li><strong>Features:</strong> What features are required, what are nice to have, and what are backlogged for later?</li>
<li><strong>Components and Screens</strong>: What are the pages or URLs the product will have, and are there non-user facing parts?</li>
<li><strong>User Experience (UX):</strong> Taking what we know about users and what we want to build, what are their main flows and experiences within the product? How would a user perform the core actions in the product?</li>
<li><strong>Open Questions:</strong> What are the things we don&#8217;t yet know or made assumptions about that should be tested to make sure everything is viable and will work like we expect it to? We&#8217;ll list open questions and then try to answer them within the document, to have a record of potential problems and the solutions we came up with.</li>
</ul>
<p>After the Product Spec is complete, the client will have a thorough document that describes the Minimum Viable Product (MVP) product as well as a backlog of potential features to be added down the line. </p>
<p>This can be used to guide a product road map, to help with a pitch to investors, to find an outside development agency, or just generally to help the client wrap their mind around what they&#8217;re building.</p>
<h3 id="technical-spec">The Technical Spec</h3>
<p>The next step is the Technical Spec. This is a technical document that lays out the high-level structural and architectural decisions that need to be made before you can start writing software.</p>
<p>While the Product Spec describes <em>what</em> we&#8217;re building, the Technical Spec describes <em>how</em> we&#8217;re building it.</p>
<p>It&#8217;s important that the Product Spec is finished and agreed upon before beginning work on the Tech Spec, so that time isn&#8217;t needlessly spent designing a system on top of changing requirements.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/07/architectural-rendering.jpg" alt="architectural rendering" width="500" class="aligncenter size-full wp-image-2634" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/07/architectural-rendering.jpg 700w, https://blog.hartleybrody.com/wp-content/uploads/2015/07/architectural-rendering-300x140.jpg 300w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>While the Product Spec might be similar to an architectural rendering, showing the glassy facade of a building from 1000 feet away, the Technical Spec is more like the blueprint, working out some of the important structural details at a lower level.</p>
<p>For the Technical Spec, I&#8217;ll often do the bulk of the writing. If the client has in-house technical resources, then I&#8217;ll work with them to ensure their approval.</p>
<p>Common sections include:</p>
<ul>
<li><strong>Core Technology:</strong> Programming languages, frameworks, open sourced libraries, public data sets, important third-party APIs. What are the core pieces the product will be built with?</li>
<li><strong>Data Models</strong>: What are the main objects that this product deals with? What are their properties and methods? What are the relationships between them?</li>
<li><strong>User Flows:</strong> As users follow the key flows from the Product Spec, what will happen at a tech level? How and when will things be processed? When and where will data be saved?</li>
<li><strong>Technical Diagram:</strong> How will systems communicate? How will 3rd-party services be integrated?</li>
<li><strong>Infrastructure &amp; Ops:</strong> Hosting? Deploying? Logging? Testing? Monitoring? Analytics?</li>
<li><strong>Open Questions:</strong> Are there technical feasibility issues? Do we need to hack together quick prototypes to make sure something is possible? Just like with the Product Spec, we&#8217;ll enumerate these and then try to go through and answer them before moving on to the next steps.</li>
</ul>
<p>Once the Technical Spec is complete, the client will have a very detailed picture of the complexity and scope of their product. </p>
<p>If there were questions of technical feasibility, those will hopefully be answered. If they want a quote for how much time it will take to build, or at what cost, this document will make those answers very clear.</p>
<h3>Next Steps</h3>
<p>Once we&#8217;ve gotten to this point &#8212; both a Product and Technical Spec, signed off by the necessary stakeholders &#8212; now we&#8217;ve got a <em>much</em> clearer sense of what needs to be built and our plan of attack.</p>
<p>We&#8217;ve taken the back of the napkin sketch of the office building and turned it into an architectural rendering as well as a clear, detailed blueprint for what needs to be built and how it&#8217;ll all fit together.</p>
<p>At this point, we&#8217;ve laid everything on the table and can decide how we&#8217;d like to proceed. </p>
<p>I&#8217;ve had clients who looked at the Product Spec and realized they could actually just build their product using an off-the-shelf survey tool for $10/month instead of paying thousands for something custom, like they had planned.</p>
<p>Sometimes clients will take the detailed Tech Spec and look for cheap overseas coders to build it on eLance and oDesk. We actually did this for some projects at my last startup with great success.</p>
<p>Sometimes the process of writing these documents is so informative that the client decides to take it in a completely new direction, and that&#8217;s okay. There&#8217;s no commitment that we <em>have</em> to work together moving forward &#8212; although I&#8217;d usually love to!</p>
<p>If they decide to move forward, we can come up with a quote for the full product or break it down into smaller deliverables.</p>
<p>There should be very few surprises at this point, so it&#8217;s much more reasonable to set deadlines and time estimates than it is when you just have a few aspirational sentences about a product.</p>
<h3>Just Enough Process</h3>
<p>Now some of you might be thinking, &#8220;Top down, waterfall-style approaches to building software are bad! The market changes, issues crop up, you can&#8217;t possible enumerate everything up front! You need to be agile.&#8221;</p>
<p>Surfacing technical issues to clients &#8212; as well as frequent, clear communication &#8212; is definitely part of the process. But setting out without a plan other than &#8220;being agile&#8221; is a great way to waste a lot of time chasing dead ends and writing code that you have to throw away or constantly refactor.</p>
<p>I also only try to employ these steps for building Minimum Viable Products (MVP), or adding features to existing products, so we&#8217;re just fleshing out the minimum feature set to start testing and learning about user behavior. The documents never describe more than a few weeks of actual development work.</p>
<p>The Product Spec includes a backlog section for features the client would like to add eventually, but this can change once we start leaning more about how customers are using the product.</p>
<h3>Don&#8217;t be Dogmatic</h3>
<p>As with many things in life, it&#8217;s important not to be too dogmatic about always doing things a certain way. For really small features, these steps might be overkill, while some of the questions might not make sense for certain kinds of products.</p>
<p>I generally think of these steps as guidelines, to help guide the product development conversation, and ensure all stakeholders are on the same page about where we are in the process and what problems we&#8217;re focused on solving.</p>
<p>If you think you could use my help on your product, <a href="http://www.hartleybrody.com">drop me a line!</a> <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
			</item>
		<item>
		<title>How I Learned to Code in Only 6 Years: And You Can Too!</title>
		<link>https://blog.hartleybrody.com/learning-to-code/</link>
		<pubDate>Wed, 29 Apr 2015 18:59:03 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2443</guid>
		<description><![CDATA[A few weeks ago, a friend texted me asking for advice. She was interested in learning how to code and wanted to know how I had done it. While I did take a handful of Computer Science classes in college, I consider most of my relevant, day-to-day software development skills to be things I picked [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>A few weeks ago, a friend texted me asking for advice. She was interested in learning how to code and wanted to know how I had done it. </p>
<p>While I did take a handful of Computer Science classes in college, I consider most of my relevant, day-to-day software development skills to be things I picked up through self-guided learning.</p>
<p>My initial advice for her was going to be pretty banal &#8212; sign up for Codecademy or Treehouse or one of the many &#8220;learn to code in 12 weeks&#8221; bootcamps. </p>
<p>But before I could send her that text, I realized that my own path to becoming a full-time, freelance software developer didn&#8217;t really look anything like that.</p>
<p>While there are a growing number of programs, classes and websites that purport to teach you coding skills in a short amount of time &#8212; and I&#8217;ve played with a few of them myself &#8212; I don&#8217;t really see them as an effective path to learning the kinds of skills one needs to be a competent software developer.</p>
<p>And so, to answer her question, I decided to take some time to look back on what I actually did, and what got me to the point I&#8217;m at today, earning a living writing code for people.</p>
<h3>Text files ending in .html</h3>
<p>It all really got started for me out of sheer boredom over winter break in 2008, during my freshman year of college. Having refreshed my Facebook News Feed for the millionth time that day and not found anything interesting, I decided to click the magic &#8220;view source&#8221; option in the browser and see if I could understand any of the HTML. Of course, it was all completely indecipherable to me, but I did notice the &#8220;.php&#8221; extension in the <code>facebook.com/home.php</code> URL. </p>
<p>That piqued my interest and after a bit of googling I discovered that PHP was some kind of language that would produce HTML for a browser to read. It all sounded really complicated so I figured I&#8217;d just start with the HTML part.</p>
<p>I opened up Notepad on my Windows laptop and saved a file to the desktop, making sure to change the extension from &#8220;homepage.txt&#8221; to &#8220;homepage.html&#8221;. From there, I read through the w3schools tutorials on HTML and built a page using table elements for layouts.</p>
<p>I&#8217;ll always remember the first time I opened a new tab in my browser and opened the HTML file on my desktop and saw a freaking web page that I had just freaking made. I mean look at it! It looks like a web page, and <em>I</em> made it!</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/04/i_have_made_fire.gif" alt="I have made fire!" width="500" height="288" class="aligncenter size-full wp-image-2528" /><br />
<meta property="og:image" content="https://blog.hartleybrody.com/wp-content/uploads/2015/04/i_have_made_fire.gif"/> </p>
<p>It was probably the first big &#8220;AHAHAHA!&#8221; moment that got me hooked on building stuff with code. I felt like a superhuman. Maybe <em>I</em> could build a site like Facebook! But not quite yet&#8230;</p>
<p>I bought a domain, picked a $5 webhost and figured out how to upload my shiny new HTML file so that the world could see it. I proudly emailed my site to some of the guys that worked on the campus life blog. </p>
<p><span id="more-2443"></span>After a few days, I hadn&#8217;t heard back from them, but I bumped into one of them on the quad. &#8220;Yah&#8230; your site is&#8230; umm&#8230; you should really learn CSS,&#8221; he told me, shuffling his feet and avoiding eye-contact. &#8220;Using tables for your layout is a bad idea, and using inline styles is&#8230; you should learn CSS.&#8221;</p>
<p>I felt so ashamed. Rather than being a beautiful work of art, someone who knew what they were talking about told me, ever-so-politely, that my code was a steaming pile of turds. Maybe this coding thing was going to be a lot harder than I thought.</p>
<p>I went to the campus library and found a book on CSS that was probably a thousand pages long. &#8220;Nope, not reading that,&#8221; I thought. I&#8217;ll stick with using tables for layouts, thank you very much.</p>
<h3>Getting started with PHP</h3>
<p>Fast forward a few months and I had added several HTML files to my website. But it felt lacking, it didn&#8217;t &#8220;do&#8221; anything, just showed the same text to every visitor, over and over again.</p>
<p>I started looking into PHP again. At this point, I had learned a thing or two about if-statements and for-loops from my Computer Science 101 class, so it was a bit less intimidating.</p>
<p>My first project was adding a &#8220;guestbook&#8221; to my website, that would email me whenever someone left a note. This was super exciting because now my website actually <em>did</em> something! People could interact with it and change it so it wasn&#8217;t always the same!</p>
<p>You might think that I had to setup a database and &#8220;learn&#8221; SQL in order to be able to insert people&#8217;s comments into said database, and then read those comments back out when the page was loaded. </p>
<p>What actually happened was that I spent many hours googling around for &#8220;PHP guestbook script&#8221;, copy/pasting the parts of other people&#8217;s code that seemed to be working until it did what I wanted. <a href="https://blog.hartleybrody.com/hacker-developer-engineer/" title="Are You A Hacker, Developer or Engineer? (And Why it Matters)">I was a hacker, not a developer.</a></p>
<p>I got a few &#8220;nice job&#8221; comments from my friends over the next few days, and each email notification I received made me so proud that I had built something that worked on the internet. </p>
<p>But it only took a few more days before the spambots found my lonely little website and proceeded to fill my guestbook with ads for enlargement supplements. My wonderful little guestbook was being vandalized by strangers on the internet whom I didn&#8217;t even know! </p>
<p>&#8220;The internet must be a scary place.&#8221;</p>
<h3>Building a Blog</h3>
<p>By the fall of 2009, blogging was starting to be something that average-joe people did. It didn&#8217;t occur to me that there&#8217;d already be software built to make this process easy, so I set out to build my own little blogging engine so that I could participate.</p>
<p>I created a folder for all the blog entries, and would add HTML files whenever I wanted to add a new article. I gave them datestamp file names like “2009-10-04.html” and wrote a simple loop in PHP to iterate over files in the directory, concatenate them together, add a header and footer and build my HTML homepage.</p>
<p>There was no way to view a single article by itself, there was only one page with every article strung together. Wanting to give my &#8220;audience&#8221; (aka my parents and college roommate) more control over their browsing experience, I began learning AJAX and added some buttons that let a visitor choose which month&#8217;s articles they wanted to see. Then the for-loop that strung together articles would filter out ones that didn&#8217;t have the right numbers in the filename. Brilliant! It felt so simple and elegant and <em>look at me making a freaking blog as if I know what I&#8217;m doing. People might actually think I know how to do this stuff.</em></p>
<p>At some point, as a prank, one of my friends on the swim team started going into the school library and setting the browsers&#8217; homepage to be my new blog. I didn&#8217;t have any analytics setup so I had no idea I was getting all of this traffic until an acquaintance from one of my classes mentioned he had seen my blog on the library&#8217;s computer.</p>
<p>A bit ashamed of the new-found attention, and worried that people might think <em>I</em> was the one who was setting my site as the homepage, I hunted down the perpetrator and asked him to stop. His response was to laugh maniacally and basically say, &#8220;make me.&#8221;</p>
<p>Realizing that diplomacy had failed, I knew that I needed to resort to bigger guns &#8212; code. So I hatched a plan: if a visitor was coming to my website from an IP address on campus, I&#8217;d redirect them to an embarrassing picture I dug up on Facebook of said friend drunkenly at a party, with a note about how he had been messing with the school computers, and offering a link to Google, a site the unsuspecting visitor might actually wanted to go to.</p>
<p>I visited the &#8220;what is my IP address&#8221; websites from a few different spots on campus to get a sense of the IP address ranges an on-campus visitor might have. Then it took a few hours of googling around for how to find a visitor&#8217;s IP addresses in the request and how read and write HTTP headers and how redirect users to a different page, but eventually, my plan was complete. I called a few friends at other schools and had them visit my site to make sure they weren&#8217;t seeing the image, and then I tried it from the library computers to make sure they were.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/04/mad-scientist-laugh.gif" alt="mad-scientist-laugh" width="400" height="224" class="aligncenter size-full wp-image-2541" /></p>
<p>I felt like a mad scientist. Look at how much power I wielded with my simple website! Someone was trying to use it to embarrass me, but I was able to come up with a clever solution and a few lines of code to turn it around on him!</p>
<h3>Learning More About Media &amp; Content on the Web</h3>
<p>In the spring of 2010, I started a college music blog with a friend and former roommate. This time, instead of building my own blogging engine, I did a bit more research and discovered blogger and wordpress and found them to be infinitely more powerful and flexible than anything I had written.</p>
<p>Since I didn&#8217;t know about version control, I just threw all of my old code away. Won&#8217;t need this anymore!</p>
<p>By the fall of 2010, the music blog was having fairly moderate success &#8212; thousands of daily visitors and climbing. I remember the first time I walked by someone I didn&#8217;t know who was on their computer, browsing the site.</p>
<p>Hell yah, baby! The internet has so much potential for building cool stuff and reaching new people!</p>
<p>That fall, I came up with the idea of creating a site that would aggregate content from the top music blogs. Basically an RSS reader for people who didn&#8217;t know what that was or want to use one.</p>
<p>I did a bit of googling about how to read RSS feeds and found a lot of people recommended using a particular library. I didn&#8217;t know what a &#8220;library&#8221; was, but I looked at some example code that used it and it seemed pretty cool. </p>
<p>You mean I don&#8217;t have to fetch the URLs and parse the different XML formats myself? I can just tell this library the sites that I care about and then simply read out their content? And I can use this code for free? Wow, open source code is great! Thanks, whoever wrote this. </p>
<p>I put the site together in about a week and coordinated a big, splashy launch with the sites it featured. I pulled in 14,000 visitors that first week.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/04/success-kid-300x199.jpg" alt="success-kid" width="300" height="199" class="aligncenter size-medium wp-image-2543" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/04/success-kid-300x199.jpg 300w, https://blog.hartleybrody.com/wp-content/uploads/2015/04/success-kid-1024x681.jpg 1024w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<h3>Learning a Second Language, Properly This Time</h3>
<p>By the summer of 2011, I was an intern on the marketing team at a mid-sized software company. The company had open seating where all the teams were mixed, so I was sitting among <em>real</em> programmers and tried to overhear their conversations to find out what that was like.</p>
<p>I heard that you could now buy servers from amazon.com and that Twitter released some CSS that everyone could use. Javascript was getting more popular, but Python was the way to go if you want to have code running on the server.</p>
<p>I offered to build some internal tools for the marketing team. I had never built something that wasn&#8217;t my idea before, and certainly never anything that a real business relied on, so I was really nervous.</p>
<p>I decided I needed to level-up and start writing code that was written cleanly and that executed efficiently. No more copy/pasting other random code snippets from the internet, I needed to Know What I Was Doing&trade;.</p>
<p>The code I wrote wasn&#8217;t just going to be hidden on my web server &#8212; other, real developers might actually <em>see</em> it, so it needed to be in ship-shape.</p>
<p>I decided I had to learn Python, so I read the 20 chapter introduction on python.org and got all sorts of confused about all sorts of stuff. What&#8217;s a tuple for? I don&#8217;t understand how default parameters work. What the heck is a splat?</p>
<p>I learned about object-oriented programming and how to write files of code that didn’t just execute from top to bottom (&#8220;scripting&#8221;, I learned that was called).</p>
<p>Eventually I put together a data pipeline that took data from one system, changed its formatting, and inserted it into another system. I had to learn about SOAP and APIs and these reverse-API things called &#8220;webhooks&#8221;.</p>
<p>The pipeline helped save a coworker hours each week of manual data processing. She was elated that I had automated this work for her, and she was super encouraging about it. &#8220;Thank you <em>so</em> much! This is amazing!&#8221;</p>
<p>A few months later though, she was singing a different tune. For some unknown reason, my code was no longer working and everything was getting out of sync. &#8220;Where is all my data?? It needs to be there! Everything is getting backed up! What&#8217;s going on?&#8221;</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/04/i-have-no-idea.jpeg" alt="i-have-no-idea" width="400" height="254" class="aligncenter size-full wp-image-2547" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/04/i-have-no-idea.jpeg 400w, https://blog.hartleybrody.com/wp-content/uploads/2015/04/i-have-no-idea-300x191.jpeg 300w" sizes="(max-width: 400px) 100vw, 400px" /></p>
<p>Holy shit. I had no idea what to do or what had happened. My code didn&#8217;t change, and the server seems to still be up. &#8220;Uhhh&#8230;.&#8221; was all I could muster.</p>
<p>Here I was, thinking I was a programmer and building things that a large company trusted to move important, timely data around. When it broke, I had no idea what to do.</p>
<p>I recruited a few friends on the engineering team to help me figure out what was going on and one of them quickly suggested one of the APIs I was using had changed. &#8220;Of course! That made so much sense, why couldn&#8217;t I have thought of that&#8230;&#8221;</p>
<p>I was disappointed in myself and I felt embarrassingly incompetent. Maybe I should stick to marketing. This coding things seems really hard. I don&#8217;t know if I&#8217;m cut out for it.</p>
<h3>A Fragile &#8220;Web Developer&#8221; Complex</h3>
<p>Several months after that incident I was asked to work on a public web app we were building to help generate leads for the business.</p>
<p>It was going to be written in Python but it would also use this thing called a &#8220;web framework&#8221; that helped you organize your code and did a lot of things for you like handling requests and talking to databases and stuff. </p>
<p>&#8220;Django,&#8221; it was called. The difficulty I had pronouncing its name was foreshadowing for the massive struggle I would soon encounter when I tried to actually build things with it.</p>
<p>This time, there were a few engineers from the core product team assigned to work with me and a few other interns on the project. All I really remember from those next few weeks was struggling for hours and hours just trying to get the code to run on my Windows laptop, and feeling like a complete failure.</p>
<p>Nothing was working and I was too embarrassed to ask for help, but I also couldn&#8217;t make heads or tails of the errors I was getting by myself.</p>
<p>Fortunately, the real engineers I was working with were very patient and kind. &#8220;Yah, Windows is tough, its not your fault,&#8221; they&#8217;d say, reassuringly. &#8220;Believe it or not, I used to struggle with this kind of stuff too.&#8221; I assumed he was lying to help me save face, but I appreciated the sentiment.</p>
<p>Eventually, I started to get more comfortable working with Django and Python. I hung out in the Computer Science department on campus and started reading books about Python. I remember the first time I successfully used a list comprehension and a lambda function. Fuck yah, this is like real programming!</p>
<p>I decided to rebuild my college music blog aggregator in Python and planned to add a bunch of features. One of which was the ability to learn your preferences based on the articles you clicked on and somehow highlight other articles you might like. </p>
<p>I started reading a bit about machine learning and, to my surprise, it wasn&#8217;t totally over my head. I could follow along and build a few of the toy projects in the book that I checked out from the library. But eventually it was finals week and the book was due back and I never implemented anything. Maybe some day.</p>
<p>By this time, I had gotten a bit of a <a href="https://blog.hartleybrody.com/find-a-coder/" title="So You Want to Find a Coder…">reputation as a &#8220;coder&#8221;</a> on campus and I was approached by a fellow senior who had an idea for a startup. The idea was born out of the struggle his younger sister was having sharing and discussing prom dress ideas. He had a cool name for it and it seemed like something I could reasonably build. And so, the social network for fashion was born. </p>
<p>The server-side Python stuff was pretty straightforward, the hard part was making the website look and feel like a social network. Facebook had set the bar really high &#8212; people expected everything to happen magically with no page reloads. If someone posted a comment with a URL, that comment needed to show up in the discussion thread immediately, the URL needed to be detected and turned into a clickable link, and we needed to try to pull in a preview of the page they&#8217;d linked to. All of that just to support URLs in comments!</p>
<p>I wove a tangled web of jQuery with tons of nested callbacks stuffed inside <code>$(document).ready() </code>. Things were getting unwieldy, fast. At one point I decided it would be a good idea to upgrade the version of bootstrap we were using and I noticed a bunch of tiny things broke. I had no comprehensive way to test everything or manage other people&#8217;s code that I was depending on. I got very little sleep that week, staying up to odd hours playing whack-a-mole with these bugs.</p>
<p>But despite how embarrassingly ugly the code was, the site looked alright and functioned decently. Smart people that I trusted to be honest told me the site looked “cool”. <em>Man, look at me tricking people into thinking I can build quality software</em>.</p>
<p>I started reading more books and blogs about building software for the web at scale. I started learning about best practices and why they were important. It wasn&#8217;t just that your code needed to barely function, it should be easy to read, <a href="https://blog.hartleybrody.com/scale-load/">scale and maintain in the future too</a>.</p>
<p>By the time graduation rolled around in the spring of 2012, the site ended up petering out, as most startups do, but I was really proud of what we built.</p>
<h3>Sneaking onto a Software Engineering Team</h3>
<p>The job offer I had after graduation was to join the marketing team at the same company where I had screwed up the pipeline and taken forever on the web app.</p>
<p>I was supposed to join a group within marketing known as the &#8220;Marketeers&#8221; who built stuff to support marketing. But a few weeks before my start date, that group was moved from being within marketing to being a part of the product team, where it would have better engineering support and management.</p>
<p>I was given the option &#8212; I could either stay in marketing and join a different group, or I could move over to the product team and be an engineer. I&#8217;d have a quick interview to make sure I wouldn&#8217;t be over my head, but if I got the green light, I&#8217;d officially become a &#8220;product engineer&#8221;.</p>
<p>The interview was with a senior engineering manager who had a reputation for being curt and ruthless. To say I was nervous was a tremendous understatement. He asked me to show him something I had worked on and I tried pulling up the homepage of the social network I had built. It took 30 excruciating seconds to load.</p>
<p>He glanced at me sideways. &#8220;Why is this so slow?&#8221; I rambled something about lots of database queries and shuffling data around and maybe one of the servers is down. &#8220;How would you debug this?&#8221; I had heard of the Django Debug Toolbar which makes it easy to see where your slow queries are in an application, so I mentioned that.</p>
<p>He scrolled around and clicked on a few things. &#8220;Alright&#8221; he said. I was in.</p>
<p>I guess I had built a few pieces of software and had definitely learned a lot in the past year or so. And now, here I was, on an actual software engineering team. </p>
<p>I was working with other real engineers who followed best practices. I was using a proper IDE and a well-tuned development environment that I setup in a single morning. </p>
<p>I got to hang out with Javascript developers and ops gurus and ask them a million questions. I had an opportunity to see what real-life, production, high-quality code for thousands of paying customers looks like.</p>
<p>Things were going great until suddenly, they weren&#8217;t. On a Friday afternoon, I accidentally hard-coded some admin configuration data, shipped them to production, and then packed up and went home. Within a few minutes, part of the product was broken for all customers, and I had taken down the homepage of the company I worked for. A coworker was able to roll back my commit and someone else had to restore the homepage from a backup.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/04/were-not-worthy.gif" alt="we&#039;re-not-worthy" width="400" height="240" class="aligncenter size-full wp-image-2549" /></p>
<p>&#8220;What am I doing here? I don&#8217;t deserve to be here.&#8221;</p>
<h3>Gaining Confidence</h3>
<p>By the middle of 2013, I had started working on a few more independent side projects. I tried to do <a href="https://blog.hartleybrody.com/two-startups/" title="Two Startups in 9 Months: Lessons Learned as a Technical Co-Founder">another startup</a>, building a marketing platform for musical artists and learned the hard way why real-time analytics at scale is such a rare feature in big products (hint: it&#8217;s really hard).</p>
<p>I started working with the Flask web framework for Python, instead of Django. I could see differences and similarities in how things are done, and started to recognize high-level design patterns. I also started learning more advanced web topics like caching and database optimizations and service-oriented architectures.</p>
<p>That summer, I got a job as employee #1 at an ad-tech startup. In my interview, I remember being able to answer most of their questions about load balancing algorithms and their tradeoffs, and what HTTP, TCP and UDP were and how they differed. I struggled a bit doing some joins in SQL but I went home and watched some coursera classes and was <a href="https://blog.hartleybrody.com/databases-intro/" title="Peeling Back the ORM: Demystifying Relational Databases For New Web Developers">teaching the topic to some junior developers we hired a few months later</a>.</p>
<p>I told them in my interview that I didn&#8217;t know much about lua or nginx or high performance computing or &#8220;big data&#8221; or any of the other technologies they were using, but I was told not to worry. I&#8217;d figure it out. </p>
<p>And eventually, I did.</p>
<p>I started working more independently and designing systems with decreasing oversight. I still managed to ship code on a Friday afternoon that broke everything, but this time I realized right away, fixed it, and wrote up a post-mortem to share what went wrong with the team.</p>
<p>I was able to keep track of &#8220;code smells&#8221; &#8212; small symptoms of some larger issues &#8212; and got better at spotting them in my own code. I kept an eye on the things we were doing as a team and looked for patterns of behavior we could improve.</p>
<p>I lead the charge to come up with our own <a href="https://blog.hartleybrody.com/git-small-teams/" title="Minimum Viable Git Best Practices for Small Teams">internal git best practices</a> and organized a weekly tech talk to help people share what they&#8217;d learned with the team. I no longer felt like an impostor when I told people I was a software developer. </p>
<p>It only took me six years.</p>
<h3 id="advice">Lessons &amp; Advice</h3>
<p>I realize this story is already pretty long, so I&#8217;ll try to summarize some takeaways for people thinking about starting this journey.</p>
<p><u><strong>Don&#8217;t just read and watch other people code, do it yourself</strong></u><br />
There are a lot of well-meaning people who will tell you to watch these videos or follow this tutorial and you&#8217;ll be able to code in no time. </p>
<p>In my experience, this method of learning &#8220;feels&#8221; fast cause look at what you just built! But when you have to step away from the lesson and build your own thing, you often haven&#8217;t actually learned much about how to solve problems with the technology. Just do whatever feels natural to you and get started.</p>
<p><u><strong>Start with projects you want to work on</strong></u><br />
It doesn&#8217;t matter if what you&#8217;re doing has already been done. Just build a version of something you&#8217;d use yourself and iterate on it.</p>
<p>Having a personal interest in the problem will help you come up with creative solutions and will keep you interested when you inevitably get stuck on something.</p>
<p><u><strong>There will be lows</strong></u><br />
You&#8217;re going to get frustrated and screw things up and be embarrassed and want to quit. That never stops happening, no matter what level you get to (as far as I can tell).</p>
<p><u><strong>Err on the side of making the mistakes yourself, not getting it &#8220;right&#8221;</strong></u><br />
There are a million different blog posts containing conflicting information about the &#8220;proper&#8221; ways to do everything. If you feel stuck, just keep on pushing forward with your original idea and make it work. You <em>will</em> eventually figure it out and will be so much prouder of your solution because you stuck it out. Plus, you may pick up a battle scar or two which helps guide you next time you&#8217;re solving a similar problem.</p>
<p><u><strong>Learn only as much as you need to know, just when you need to know it</strong></u><br />
Start with a problem you&#8217;re trying to solve &#8212; like getting information from RSS feeds or sending email &#8212; and learn just enough so that your program does that. Then move on to solving the next problem.</p>
<p>It&#8217;s going to be difficult enough to cram a new technology into your brain and make sense of it all, don&#8217;t try to pull in superfluous information with it.</p>
<p>As you get more experience, <a href="https://blog.hartleybrody.com/hacker-developer-engineer/" title="Are You A Hacker, Developer or Engineer? (And Why it Matters)">your learning style will change</a>. But don&#8217;t try to learn everything right out of the gates. Just what you need to solve the next problem.</p>
<p><u><strong>Learning is about solving problems, not memorizing syntax</strong></u><br />
Even though all of those weird symbols and rules for writing things feel like some esoteric mumbo-jumbo, you&#8217;ll get past that relatively quickly. </p>
<p>No one gets good at programming by memorizing all of the weird little rules and bits of the language. Instead, focus on using code to solve problems. You can build tons of stuff only knowing arrays, hashes/dicts, if-statements and for-loops. In fact, I got by for years only knowing those 4 things.</p>
<p><u><strong>It&#8217;s an ongoing learning process</strong></u><br />
There&#8217;s always more to know, and the state-of-the-art and &#8220;best practices&#8221; are constantly evolving over time. </p>
<p>If you&#8217;re expecting it to be like riding a bike, where once you get over the hump of figuring it out for the first time, you can stay competent and relevant forever, you might get overwhelmed. But if you love learning &#8212; from others and from your own mistakes &#8212; it&#8217;s a great place to be. </p>
<p>They say that if you aren&#8217;t embarrassed by the quality of the code you wrote 6 months ago, you&#8217;re not learning fast enough.</p>
<p><u><strong>You probably know more than you realize</strong></u><br />
There&#8217;s something called <a href="http://codon.com/i-have-no-idea-what-im-doing" target="_blank">impostor syndrome</a> which the astute reader might have noticed I was exhibiting at several points in this article. </p>
<p>It&#8217;s a psychological condition that&#8217;s fairly common in amongst people who write code, where you don&#8217;t really recognize all that you&#8217;ve learned and accomplished. You chalk successes up to luck and good timing, whereas failures feel like something you really deserved.</p>
<p>I&#8217;m not really sure why it&#8217;s so common in this business, but I see it everywhere when people downplay their successes and accomplishments. You might end up doing it too, so be sure to give a hearty fist pump when you finally fix that bug or solve that problem. You earned it.</p>
<p>&#8212;</p>
<p><a href="https://twitter.com/hartleybrody/status/593584827447779329" target="_blank">Send me a note on Twitter</a> if you enjoyed the post.</p>
<p>Thanks for reading this far! If I sound like someone you might want to work with, I&#8217;m currently accepting new clients. <a href="http://www.hartleybrody.com/">Get in touch <img src="https://s.w.org/images/core/emoji/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></a></p>
]]></content:encoded>
			</item>
		<item>
		<title>Look Ma, No Servers! How Javascript is Changing the Modern Web Stack</title>
		<link>https://blog.hartleybrody.com/serverless-stack/</link>
		<pubDate>Wed, 18 Mar 2015 16:22:10 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://blog.hartleybrody.com/?p=2479</guid>
		<description><![CDATA[Formerly titled &#8220;The Rise of the Server-less Web Stack&#8221; Javascript has lots of cool stuff built on top of it now. These days, there are tons of well-worn frameworks that bring all sorts of powerful programming paradigms into the browser. Want easy object-orientation? Use backbone. More of a functional programmer? There&#8217;s underscore, lodash and many [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><small><em>Formerly titled &#8220;The Rise of the Server-less Web Stack&#8221;</em></small></p>
<p>Javascript has lots of cool stuff built on top of it now. These days, there are tons of well-worn frameworks that bring all sorts of powerful programming paradigms into the browser.</p>
<p>Want easy object-orientation? Use backbone. More of a functional programmer? There&#8217;s underscore, lodash and <a href="http://scott.sauyet.com/Javascript/Talk/2014/01/FuncProgTalk/#slide-53" target="_blank">many others</a>. And I can&#8217;t keep up with the latest template rendering libraries, but there are dozens.</p>
<p>Plus ECMAscript 6 is rolling out quickly and with it, some long-awaited <a href="https://github.com/lukehoban/es6features#ecmascript-6-features" target="_blank">language features, syntactic sugar and new APIs</a>.</p>
<p>Additionally, there are a lot of JS SDKs and simple integrations for things like accepting payments (stripe), analytics (mixpanel, customer.io, etc) if you don’t want to write the code or support the infrastructure to do those things yourself.</p>
<p>With all of these features, one can build an entire, bonafide web application in pure javascript. This certainly isn&#8217;t a new idea &#8212; single-page javascript applications have been around for years.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/03/serverless-web-stack.jpg" alt="serverless-web-stack" width="128" height="128" class="alignright size-full wp-image-2490" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/03/serverless-web-stack.jpg 256w, https://blog.hartleybrody.com/wp-content/uploads/2015/03/serverless-web-stack-150x150.jpg 150w" sizes="(max-width: 128px) 100vw, 128px" />But what if we take the power of javascript to its logical conclusion &#8212; making the entire app live in the user&#8217;s browser.</p>
<p>Do we even need to deal with setting up servers and maintaing a separate codebase for a server-side backend at all?</p>
<p><span id="more-2479"></span><br />
<h3>Hosting Benefits</h3>
<p>I read a <a href="https://venturefizz.com/blog/stack-dive-appcues-serverless-stack" target="_blank">great piece recently</a> on my friend Jonathan’s startup’s “stack” and how they have built their application to live on a simple static hosting service. </p>
<p>I myself just shipped a project that will be entirely hosted on s3, and have collected email addresses from statically-hosted landing pages.</p>
<p>It’s a pretty great selling point to tell your client that their web app can have <a href="http://aws.amazon.com/s3/#Available" target="_blank">99.99% availability</a> and no servers that need to be patched or updated or maintained. Nothing to crash or get hacked or set off someone&#8217;s pager at 2 in the morning.</p>
<p>Having an entirely static app means you won&#8217;t have to worry about many of the traditional scaling issues and performance bottlenecks that most web apps have to consider if (when!) usage takes off.</p>
<p>Serving static files off disk is trivial to scale compared to CPU- or memory-bound applications. Each client is running their own version of the app on their desktop, laptop or phone, using their own CPU, memory and IO resources, not yours.</p>
<p>Plus it&#8217;s fast &#8212; your entire application can live on a globally-distributed CDN so it’s physically close to users around the globe, without needing to have servers scattered across various data centers.</p>
<p>Granted, this is all because there are already some pretty great abstractions on top of static file hosting that do the “heavy lifting” to deliver the SLA with that many nines. But those abstractions are so cheap and simple that they’re basically a commodity at this point.</p>
<p>All of these benefits mean that <strong>a single developer or small team can get pretty far without needing to have any devops skills at all</strong>. Just push your code to a static file host and make sure your domain is pointed to the right place.</p>
<h3>Remaining Problems</h3>
<p>Okay so building a web app for a static hosting environment has some awesome benefits. But there are definitely some drawbacks to consider — depending on your application’s needs.</p>
<p><strong>Data Persistence</strong><br />
If you need any sort of centralized datastore across multiple clients (ie Users, Accounts, etc) you’re probably going to need a database server and some application logic that lives on top of it.</p>
<p>But you might also be able to use the API of an existing third-party system like Firebase or Parse. </p>
<p>You could leverage the existing API of your company’s CRM or other existing internal datastore. I was able to use a Marketing SaaS app as the “database backend” for my recent client project, by simply sending data from the app directly to their marketing software’s API.</p>
<p>It&#8217;s also a good idea to consider whether your app really needs a database at all. Is it really a requirement that users need an account before they can use your product? Don’t collect and store data needlessly.</p>
<p><strong>3<sup>rd</sup>-Party Integrations</strong><br />
If your app needs to integrate with a third party for storing data, sending emails, tracking user analytics or other tasks, you might need to keep that integration on the server-side if it requires authentication &#8212; you don&#8217;t want to send API keys or other credentials to the client. But if the API doesn&#8217;t require auth or has a client-side integration option, you may not have to worry.</p>
<p>Another problem you might run into is CORS support &#8212; if the vendor&#8217;s API doesn&#8217;t return the right headers, then the client will refuse to send requests to it. But if an API endpoint expects GET or POST requests, a potential workaround is to just use form submissions in a hidden iFrame to send requests without reloading the page. Hack-y, but doable.</p>
<p>Some APIs are specifically designed to accept form submissions, like MailChimp for managing email lists or the the Google Forms to collect arbitrary data in a spreadsheet. </p>
<p><strong>Private Business Logic</strong><br />
This one admittedly has no really good answer. You could run your javascript through obfuscation (renaming variables and functions to meaningless letters) and minification tools, but the instructions and logic are still there if anyone wants to take the time to piece them together.</p>
<p>Having had to read through obfuscated and minifed javascript in a previous job at an ad-tech company, I can tell you that it’s certainly not easy or pleasant to reverse engineer code that has been run through these steps, but it is possible.</p>
<p>So if your app uses any sensitive, valuable or proprietary business logic, it’s best you let that run on the server-side.</p>
<p><strong>Crashes and Bug Reporting</strong><br />
When a 503 happens on a web server, most web frameworks send you a pretty stack trace in your inbox by default. But when building a javascript app, things fail on the client’s machine, out of sight of your web server&#8217;s logging features.</p>
<p>It’s important to consider how things might fail — network being unavailable, unexpected input or result of computation, etc — and figure out if or how the exceptional condition should be reported back to your system, and also how to communicate about the exception to the user.</p>
<p><strong>Heavy &#8220;Offline&#8221; Processing</strong><br />
If your app processes a ton of data, you probably don’t want that happening synchonrously on a web server during the request-response cycle anyways. </p>
<p>With javascript, the risk is that you’ll hang the user’s browser if you’re doing expensive calculations on the main thread.</p>
<p>On the server, you might do something like kick off some offline job to do the processing and store the output or notify the client when it&#8217;s done. </p>
<p>In javascript, there is a pretty simple <a href="http://www.html5rocks.com/en/tutorials/workers/basics/" target="_blank">Web Worker API</a> that’s <a href="http://caniuse.com/#feat=webworkers" target="_blank">widely supported</a>. If you need to do heavy rendering or data crunching, it’s worth taking a look at Web Workers.</p>
<p>&#8212;</p>
<p>There obviously still some drawbacks to the “<strong>server-less web stack</strong>” and servers certainly aren&#8217;t going away any time soon. But building a server-less application has some really cool benefits.</p>
<p>You should consider if it&#8217;d be a good fit for your next project.</p>
]]></content:encoded>
			</item>
		<item>
		<title>Minimum Viable Git Best Practices for Small Teams</title>
		<link>https://blog.hartleybrody.com/git-small-teams/</link>
		<comments>https://blog.hartleybrody.com/git-small-teams/#respond</comments>
		<pubDate>Wed, 21 Jan 2015 01:01:58 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.hartleybrody.com/?p=2405</guid>
		<description><![CDATA[When I started as the first employee at Burstworks, the cofounders and I could easily hold the information about who was working on what at any given moment in our brains. But as we worked on new projects and the scope and size of the engineering team grew, all of our code mostly stayed organized [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/01/logomark-orange@2x.png" alt="logomark-orange@2x" width="200" height="200" class="alignright size-full wp-image-2434" srcset="https://blog.hartleybrody.com/wp-content/uploads/2015/01/logomark-orange@2x.png 200w, https://blog.hartleybrody.com/wp-content/uploads/2015/01/logomark-orange@2x-150x150.png 150w" sizes="(max-width: 200px) 100vw, 200px" />When I started as the first employee at Burstworks, the cofounders and I could easily hold the information about who was working on what at any given moment in our brains.</p>
<p>But as we worked on new projects and the scope and size of the engineering team grew, all of our code mostly stayed organized in one central repository:</p>
<ul>
<li>Our high-performance ad server</li>
<li>Data Pipeline</li>
<li>One-off scripts</li>
<li>Nightly jobs</li>
<li>Everything&#8230;</li>
</ul>
<p>While we generally weren&#8217;t working on the exact same files at the same time, there was still lots of stepping on toes. Having your <code>git push</code> rejected was a common occurrence.</p>
<p><img src="https://blog.hartleybrody.com/wp-content/uploads/2015/01/Screen-Shot-2014-12-02-at-8.04.18-PM.png" class="aligncenter" width="500px" /></p>
<p>Inevitably we had issues with merge conflicts, which lead me to send this tweet from our company account:</p>
<blockquote class="twitter-tweet" lang="en"><p>When multiple people are committing to the same repo and trying to push at the same time <a href="https://twitter.com/hashtag/git?src=hash">#git</a> <a href="http://t.co/m7KP19KdP4">pic.twitter.com/m7KP19KdP4</a></p>
<p>&mdash; Burstworks (@burstworks) <a href="https://twitter.com/burstworks/status/484347775149428737">July 2, 2014</a></p></blockquote>
<p><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>And so I decided to take a step back and think about how we managed our version control system at Burstworks.</p>
<p>I definitely didn&#8217;t want to come up with something heavy handed or overly-proscriptive. The goal was to come up with just enough process to grease the wheels, and not slow things down.</p>
<p>I did some reading, came up with some initial ideas and pitched them to the team. We iterated a bit and here&#8217;s what we came up with.</p>
<p>I should start out by saying that it&#8217;s nothing revolutionary or new. It&#8217;s what I would consider the Minimum Viable Git Best Practices&#8482; for a small engineering organization.</p>
<p><span id="more-2405"></span></p>
<h3>Diff Everything</h3>
<p>You should review every single change before you stage or commit something. Whenever <code>print</code> statements or “<code># don’t commit this</code>” make it to production, it’s almost always because someone blindly ran </p>
<pre class="brush: bash; title: ; notranslate">
git add .
git commit -m &quot;my git is bad and i should feel bad&quot;
</pre>
<p>without <code>diff</code>ing their changes.</p>
<p>If you&#8217;ve already added a bunch of changes to staging and want to confirm them before you commit, you can run</p>
<pre class="brush: bash; title: ; notranslate">
git diff --staged
</pre>
<p>or alternatively, run</p>
<pre class="brush: bash; title: ; notranslate">
git commit -v
</pre>
<p>to bring up a vim editor to edit your commit message, while also viewing the diff you&#8217;re about to commit.</p>
<p><strong>Pro tip:</strong><br />
If that seems like typing a lot of commands to remember, make some <a href="https://github.com/hartleybrody/.dotfiles/blob/master/git/aliases.src" target="_blank">aliases in your shell&#8217;s profile</a>.</p>
<h3>Commits Should be Small and Frequent</h3>
<p>You should be committing code whenever you have made a single logical change. This allows you to write concise but descriptive commit messages, which offers great context for others who might be reading through your code.</p>
<p>Committing small things, frequently make it much easier to handle bugs or other bad situations:</p>
<blockquote><p>
When did we push this bug? Oh I see the commit&#8230; but a bunch of other things changed too. What was being worked on here?
</p></blockquote>
<blockquote><p>
I need to roll back that commit but what else might break if I do that?
</p></blockquote>
<p>Here are some code smells or signs that usually mean you&#8217;re not committing frequently enough:</p>
<ul>
<li>A 100+ line file is being committed for the first time</li>
<li>You’re changing more than 20 lines of a file in one commit</li>
<li>You’re only committing when you take breaks (i.e. lunch, end of day, etc)</li>
<li>You have trouble succinctly describing what has changed (see below section)</li>
</ul>
<p><strong>Pro tip:</strong><br />
Sometimes when you&#8217;re in the zone, you end up making a bunch of different logical changes to the code base without stopping to commit each one. That’s okay: <code>git add -p</code> to the rescue!</p>
<p>Running <a href="http://stackoverflow.com/q/1085162/625840" target="_blank"><code>git add</code> in patch mode</a> (sometimes called &#8220;partial&#8221; mode) lets you stage a few lines out of a file for a commit, leaving the rest of the changes to a file unstaged.</p>
<p>Git will automatically show you chunks of changes from the file, and ask if you want to stage them or skip them. There&#8217;s also an option to break down the current chunk into smaller ones for really fine-grained control.</p>
<p>Now you can take the huge refactor you just cranked through and break it down into smaller, logical commits.</p>
<h3>Commit Messages Should be Semantic</h3>
<p>Every commit message should describe <em>why</em> the code was changed &#8212; or what a change <em>accomplished</em> &#8212; at an appropriate level of detail. </p>
<p>You shouldn&#8217;t just use words to describe what parts of the code have changed &#8212; anyone can see that from reading the diff.</p>
<p>If someone wonders why a line of code was created or edited, the commit message should make it clear.</p>
<p>Here are some code smells or signs that you’ve writing a bad commit message:</p>
<ul>
<li>The message is less than 3 words</li>
<li>The message is more than 10 words</li>
<li>Your message is too high-level (it’s hard to be too low level)</li>
<li>You don’t know what changes are being committed (see above section)</li>
</ul>
<p><strong>Pro tip:</strong><br />
Did you just make a commit with a bad message like &#8220;refactor&#8221; or &#8220;business logic&#8221;? </p>
<p>It happens to the best of us. Just use:</p>
<pre class="brush: bash; title: ; notranslate">
git commit —amend
</pre>
<p>which gives you a vim editor to change the last commit&#8217;s message.</p>
<h3>Use Feature Branches</h3>
<p>If you’ll be making multiple commits that are related to each other, they belong on a separate branch. One of the nicest things about using branches is that both Github and Bitbucket support Pull Requests which allow for a discussion about a collection of commits, before they&#8217;re merged back into master.</p>
<p>Using branches makes the merge into master feel very concrete and important. It gives you a chance to see all of your final changes while ignoring work-in-progress commits. It also means that the master branch is always ready to deploy, with no half-ready changes mixed into the code.</p>
<p>Signs you should be using a branch:</p>
<ul>
<li>You will be committing “work in progress” changes to save progress that leave your application in a broken state and shouldn’t go to production</li>
<li>There will take multiple logical changes to the codebase that are part of a larger project</li>
<li>There will be several commits in a row that all depend on each other and should be in order</li>
</ul>
<p>Signs you don’t need a feature branch &#8212; that is, it’s okay to commit to master:</p>
<ul>
<li>You’re making a small change that fits nicely inside one commit</li>
<li>Bug fixes/hot fixes for fixing typos, etc</li>
<li>Previous/future commits won’t affect this commit</li>
</ul>
<p>When you&#8217;re working on a branch, make sure you run <code>git pull origin master</code> frequently, (at least once a day) so that your branch doesn’t get left behind, and to decrease the likelihood of merge conflicts.</p>
<p>Once we switched to using branches, we found that we spent a lot more time reading each others&#8217; code. This helped us learn from each other and gave us all a chance to recognize new or potentially troubling idioms and have a discussion around them, &#8220;in the code&#8221;.</p>
<p>It also allowed us to catch mistakes sooner and keep problematic code from being merged into master and shipped to production.</p>
<h3>More Git Resources</h3>
<p>If you want to learn more, here are some of the resources I used when coming up with these tips.</p>
<ul>
<li><a href="http://git-scm.com/book/en/Git-Tools-Interactive-Staging" target="_blank">Git Tools &#8211; Interactive Staging</a></li>
<li><a href="https://guides.github.com/introduction/flow/index.html" target="_blank">Understanding the GitHub Flow</a></li>
<li><a href="http://scottchacon.com/2011/08/31/github-flow.html" target="_blank">Issues with git-flow</a></li>
</ul>
<p>I&#8217;m hoping to avoid starting a flame war between different workflow models, but if you have constructive suggestions or more git power tips, feel free to leave a comment or <a href="https://twitter.com/hartleybrody" target="_blank">drop me a note on Twitter</a>!</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.hartleybrody.com/git-small-teams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lightning Fast Data Serialization in Python</title>
		<link>https://blog.hartleybrody.com/python-serialize/</link>
		<comments>https://blog.hartleybrody.com/python-serialize/#respond</comments>
		<pubDate>Tue, 09 Dec 2014 03:55:26 +0000</pubDate>
		<dc:creator><![CDATA[Hartley Brody]]></dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.hartleybrody.com/?p=2406</guid>
		<description><![CDATA[A few months ago, I got a chance to dive into some Python code that was performing slower than expected. The code in question was taking tiny bits of data off of a queue, translating some values from strings to primary keys, and then saving the data back to another queue for another worker to [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>A few months ago, I got a chance to dive into some Python code that was performing slower than expected.</p>
<p><img src="//blog.hartleybrody.com/wp-content/uploads/2014/12/lightning-fast-serialization-python-150x150.png" alt="lightning-fast-serialization-python" width="150" height="150" class="alignright size-thumbnail wp-image-2407" />The code in question was taking tiny bits of data off of a queue, translating some values from strings to primary keys, and then saving the data back to another queue for another worker to process.</p>
<p>The translation step should have been fast. We were loading the data into memory from a MySQL database during initialization, and had organized the data structure so that the id -> string lookups were constant time.</p>
<h3>Finding the Problem</h3>
<p>In order to figure out where the bottleneck(s) were, I used Python&#8217;s <a href="http://stackoverflow.com/a/582337/625840" target="_blank">builtin CProfile package</a>, and combed through the results using the <a href="http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html" target="_blank">awesome CProfileV package</a>, written by a former Quora intern.</p>
<p>After letting the script run for awhile, the bottleneck jumped out right away &#8212; the workers were spending about 40% of their time <a href="http://en.wikipedia.org/wiki/Serialization">serializing and deserializing data</a>.</p>
<p>In order to keep messages on the queue for other workers to pick up, we were translating the Python dicts into JSON objects using the standard library&#8217;s <code>json</code> package.</p>
<p>Our worker was reading the text data from the queue, deserializing it into a Python dict, changing a few values and then serializing it back into text data to save onto a new queue.</p>
<p>The translation steps were taking up about 40% of the total runtime.</p>
<p>So I set out to see if there was a faster way to serialize a Python dict.</p>
<p><span id="more-2406"></span><br />
<h3>Our Concerns</h3>
<p>When you&#8217;re optimizing code, it&#8217;s helpful to think about what sort of gains you&#8217;re looking for.</p>
<ul>
<li>Gaining a few percentage points faster isn&#8217;t usually too challenging</li>
<li>Gaining several times faster (ie 200-800%) requires more strategic thinking</li>
<li>Gaining orders of magnitude in speed often requires rearchitecture or starting over</li>
</ul>
<p>Since we were already using Python&#8217;s builtin <code>json</code> module, we knew it&#8217;d be hard to eek out an order of magnitude improvement. But a few percentage points wasn&#8217;t going to cut it. It had to be a meaningful speedup in order to take a big chunk out of that 40% of time spent doing serialization/deserialization.</p>
<p>Each message of data was small &#8212; 5 keys with small values tipped the scales at a few dozen bytes  each &#8212; so we weren&#8217;t worried about saturating the network card. Bandwidth and latency also weren&#8217;t a huge factor since the queue and all the workers were in the same availability zone on EC2.</p>
<p>I should note that all of the workers that&#8217;d be touching this data were in-house, so interoperability with common data serialization standards wasn&#8217;t a huge concern.</p>
<p>If the fastest way to encode data was to string it together with pipes <code>|</code> and backslashes <code></code>, that was fine. We could update all of the workers to accommodate it.</p>
<p>I tried searching for as many Python data serialization libraries as I could find &#8212; as well as coming up with my own serialization schemes.</p>
<h3>The Code</h3>
<p>I learn a bunch about the performance of different string building functions while building my own <code>home_brew</code>&#8216;d serialization process. If you have any more ideas, let me know and I&#8217;ll be sure to add them!</p>
<p>Note that some packages require a file handle in order to write the serialized data, while others just dumped it to a string in-memory.</p>
<p>The overhead of opening and closing the file was undetectable on the order of time I was examining, but I commented the file-handling code out for the packages that didn&#8217;t need it, to simulate the actual cost of using each package in production.</p>
<p><script src="https://gist.github.com/hartleybrody/9164c1b1d28842255e4b.js"></script></p>
<h3>Results &#038; Observations</h3>
<p>To get the times for each of the different serialization functions, I ran the script with the <a href="http://en.wikipedia.org/wiki/Time_(Unix)" target="_blank">unix <code>time</code> command</a> and summed <a href="http://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1" target="_blank">the <code>user</code> and <code>system</code> time</a>.</p>
<p>I ran the script 10 times for each package and made a mental average. That&#8217;s the number you see listed in the comments next to each function.</p>
<p><img src="//blog.hartleybrody.com/wp-content/uploads/2014/12/avg-time-json-serilization-packages.png" alt="Average time per Python package" width="500" class="aligncenter size-full wp-image-2408" /></p>
<p><img src="//blog.hartleybrody.com/wp-content/uploads/2014/12/pyth-data-serialization-rate-speed.png" alt="Millions of messages serialized per second" width="500" class="aligncenter size-full wp-image-2409" /></p>
<p>If speed is your primary concern, I&#8217;d recommend checking out <a href="https://github.com/esnme/ultrajson" target="_blank">&#8220;Ultra JSON&#8221; aka <code>ujson</code></a> from <a href="http://pushingtheweb.com/2011/03/ultra-fast-json-encoding-decoding-python/" target="_blank">these fine folks</a>.</p>
<p>We switched to using ujson and saw a roughly 1/3rd overall increase in our pipeline processing speed, which was inline with our expectations from the test results.</p>
<p>Any packages I missed? Different ideas for home brewed serialization? Shoot me a <a href="https://twitter.com/hartleybrody">note on Twitter</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.hartleybrody.com/python-serialize/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.688 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2016-08-18 12:39:45 -->
