<?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>Chasen Le Hara</title>
	<atom:link href="http://chasenlehara.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://chasenlehara.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 01 Dec 2010 00:35:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>The Unwritten Human Interface Guidelines for iOS 4.2</title>
		<link>http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/</link>
		<comments>http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 23:55:17 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=147</guid>
		<description><![CDATA[Apple’s iOS Human Interface Guidelines (HIG) (PDF) provides great advice for creating an app for iOS. However, for an app to really fit in with iOS, it should embrace the unwritten conventions that Apple follows in their apps. To help myself and other developers stay on the right track, I’ve assembled a guide with lots [...]]]></description>
			<content:encoded><![CDATA[<p>Apple’s iOS Human Interface Guidelines (HIG) (<a href="http://developer.apple.com/library/ios/documentation/userexperience/conceptual/mobilehig/MobileHIG.pdf">PDF</a>) provides great advice for creating an app for iOS. However, for an app to really fit in with iOS, it should embrace the unwritten conventions that Apple follows in their apps. To help myself and other developers stay on the right track, I’ve assembled a guide with lots of the things that should probably be in the HIG but are not. I’ll continue to update this guide as I see apps with “incorrect” user interfaces. I’ve included screenshots of the right way to do things (usually from Apple’s apps or <a href="https://ironmoney.com/mobile/ios/">Iron Money for iOS</a>).</p>
<h3>Button placement</h3>
<p>Buttons should almost always go on the right first, then the left. Additionally, add buttons should go on the right, and edit buttons should go on the left; there are very few circumstances in which this rule should be broken.</p>
<p><a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/add-edit-buttons/" rel="attachment wp-att-187"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/add-edit-buttons.png" alt="" title="World Clock navigation bar" width="320" height="44" class="alignnone size-full wp-image-187" /></a></p>
<p>Use “Done” buttons for adding or editing data from a list; use “Save” to save a value to an editing table. In general, if you have a list of objects, a user should be able to select an object, then tap “Edit” to edit it, and tap “Done” to save their changes. If an object has an attribute, it is permissible to let them tap the attribute and then tap “Save” to save the change to that one attribute (because they’re not “done” with the entire editing process).</p>
<p><a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/done-button/" rel="attachment wp-att-196"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/done-button.png" alt="" title="Done button" width="320" height="44" class="alignnone size-full wp-image-196" /></a> <a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/save-button/" rel="attachment wp-att-197"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/save-button.png" alt="" title="Save button" width="320" height="44" class="alignnone size-full wp-image-197" /></a></p>
<p>Settings screens should have a “Done” button in the upper right.</p>
<p><a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/settings-done-button/" rel="attachment wp-att-198"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/settings-done-button.png" alt="" title="Settings done button" width="320" height="44" class="alignnone size-full wp-image-198" /></a></p>
<h3>Table views</h3>
<p>When making a custom UITableViewCell, follow the other UITableViewCell’s styles as much as possible.</p>
<p>When a user selects something from a table view with checkmarks, the checkmarked cell’s text should not be in black, but in blue.</p>
<p>On iPhone/iPod touch, a search feature should usually be hidden underneath the navigation bar until it’s pulled down by the user. Then, above the status bar, there should be a solid color.</p>
<p>Don’t use the detail disclosure icon unless you actually have details to disclose when the icon is tapped.</p>
<h3>Keyboard</h3>
<p>Almost all keyboard types have some sort of “done” button. When developing an app, it’s important to change the done button to whatever makes the most sense in that particular view. For example, if you have multiple text fields that the user might want to move between, changing the done button to “Next” on the keyboard (and moving the user to the next text field when they tap the next button) will make your app easier to use.</p>
<div id="attachment_199" class="wp-caption alignnone" style="width: 330px"><a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/keyboard-next-button/" rel="attachment wp-att-199"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/keyboard-next-button.png" alt="" title="Keyboard next button" width="320" height="460" class="size-full wp-image-199" /></a><p class="wp-caption-text">The keyboard uses a “Next” button in the bottom right because the user has multiple text fields to complete.</p></div>
<h3>iPad popovers</h3>
<p>Many iPad apps use popovers to display additional views once a button is pressed. Some apps use popovers to allow users to choose between different things; the App Store allows you to choose between different categories, the iTunes app allows you to choose different genres of music, etc. When a user selects one of the options provided in the popover, the button should update to include their selection.</p>
<p><a href="http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/popover-button-selection/" rel="attachment wp-att-206"><img src="http://chasenlehara.com/blog/wp-content/uploads/2010/11/popover-button-selection.png" alt="" title="Popover button" width="156" height="44" class="alignnone size-full wp-image-206" /></a></p>
<h3>Language</h3>
<p>Staying consistent with the text that Apple uses is a great way to have an interface users might already be familiar with and helps with localization.</p>
<p>Many apps provide in-app passcode protection. Apple’s Settings app is a great resource for deciding how to title all of the buttons and views associated with passcode protection.</p>
<p>If your app allows users to sign in and out of a service, you probably provide buttons for signing in and out of the service. The Find iPhone and MobileMe Gallery apps both include this functionality. Their sign out buttons read “Sign Out” and display an alert view with the text “Are you sure you want to sign out?” and the buttons “Cancel” and “Sign Out”. If you include text with the username, it should read: “Signed in as: %@” (replacing %@ with the username).</p>
<h3>The Devil is in the Details</h3>
<p>iOS is a great platform for creating amazing user experiences. Apple’s apps provide a great foundation for designing user interfaces for iOS. Breaking the rules is okay, but be wary of unintentionally breaking the unwritten rules of designing apps for iOS.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/the-unwritten-human-interface-guidelines-for-ios-4-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using a Queue to Fake Fast UUID Creation</title>
		<link>http://chasenlehara.com/blog/using-a-queue-to-fake-fast-uuid-creation/</link>
		<comments>http://chasenlehara.com/blog/using-a-queue-to-fake-fast-uuid-creation/#comments</comments>
		<pubDate>Sun, 31 Oct 2010 23:57:18 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=143</guid>
		<description><![CDATA[Today I released an update to Iron Money that made uploading 60% faster. A significant part of that speedup was related to changes in how UUIDs are created; this post outlines the problems the old version had and the solutions in the most recent version of Iron Money. When a transaction is added to Iron [...]]]></description>
			<content:encoded><![CDATA[<p>Today I released <a href="http://blog.ironmoney.com/2010/10/31/october-2010-updates/">an update to Iron Money</a> that made uploading 60% faster. A significant part of that speedup was related to changes in how UUIDs are created; this post outlines the problems the old version had and the solutions in the most recent version of <a href="https://ironmoney.com/">Iron Money</a>.</p>
<p>When a transaction is added to Iron Money, it’s assigned a UUID. A UUID typically takes about 10ms to generate; that might seem fast, but compared to everything else, it’s really slow. When a user uploads account data to Iron Money, a UUID is generated for the upload and all of the transactions in the upload; so if an upload contains 100 transactions, it’ll take an entire second just to generate the UUIDs for the transactions. This is terrible, and for an action as frequent as uploading account data, fairly unacceptable.</p>
<p>As with all programs, the easiest way to make something go faster is to make it do less. In Iron Money’s case, the goal was to move UUID creation out of the uploading process. The easiest way to do this is to pre-generate the UUIDs before they’re needed, then get the pre-generated UUIDs as they are needed.</p>
<p>I decided to create a new table in MySQL that had two columns: one for an ID, and another with a UUID. Every few minutes, Iron Money fills this table with new UUIDs (actually, it fills it until it has 1000 UUIDs, which is more than enough for any given few minutes). The ID column is filled with zeroes by default.</p>
<p>When a UUID is required, Iron Money creates a random ID to use with the table. It then updates a row in the table with this random ID, selects the row that was updated, and then deletes the row that was updated. This makes it possible for the same table to be used by different processes; since there are billions of possible random IDs, the chances of two processes creating the same random ID near the same moment in time is very unlikely. If you’re really concerned about the chances of collision, you can store the random ID in memcached and check memcached before using a random ID.</p>
<p>This works well, but there is one last part to this system that makes it perform very well. In an upload situation, I typically know about how many transactions are going to be created by the upload. Thus, instead of doing the update-select-delete dance for every UUID needed, I do this dance once before any UUIDs are needed and simply store the UUIDs in an array. When a UUID is needed, I can simply pop one off the array instead of going to the database; of course, if there aren’t any in the array, I can always fall back to the database, or fall back to creating a new UUID from scratch.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/using-a-queue-to-fake-fast-uuid-creation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Far-Future Expires for Static Resources</title>
		<link>http://chasenlehara.com/blog/using-far-future-expires-for-static-resources/</link>
		<comments>http://chasenlehara.com/blog/using-far-future-expires-for-static-resources/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 21:16:04 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=117</guid>
		<description><![CDATA[Creating a high-performance website can be tough, especially if you have a lot of resources (CSS, images, and JS) on your site. Seller’s Market’s home page weighs in at a hefty 992.56KB right now, but if the page is refreshed, only the HTML document needs to be downloaded again (at 17.60KB); 98% of the resources [...]]]></description>
			<content:encoded><![CDATA[<p>Creating a high-performance website can be tough, especially if you have a lot of resources (CSS, images, and JS) on your site. <a href="http://sellersmarket.biz/">Seller’s Market’s home page</a> weighs in at a hefty 992.56KB right now, but if the page is refreshed, only the HTML document needs to be downloaded again (at 17.60KB); 98% of the resources used to make up the home page are kept in the browser’s cache. In this post, I’ll dive into the implementation details behind what makes this possible.</p>
<p>Yahoo’s <a href="http://developer.yahoo.com/performance/rules.html#expires">“Add Expires or Cache-Control Header”</a> recommendation is the driving force behind what makes this possible. The recommendation suggests adding an Expires or Cache-Control header to responses to tell the browser how long a resource can be cached. If you tell a browser that it can cache a resource for ten years, it probably won’t need to download the resource again if it’s in the cache. This is exactly what’s happening on Seller’s Market; each resource can be cached for up to ten years, so subsequent reloads or going to a different page can reuse items in the cache (and since multiple resources are used across pages, this means less needs to be loaded for subsequent page loads).</p>
<p>The big catch to this is invalidating the browser’s cache; if it has a cached version of “/home.css” that it can use, it’ll use it. If you update home.css, you’ll need to make sure the browser downloads the new version.</p>
<p>In the interest of keeping things simple, the easiest way to do this is to change the URL of a resource when the resource changes. For example, the “/home.css” file might be called “/home-1.css” and change to “/home-2.css” when it’s updated. Since the URL changed, the browser won’t have a copy in cache and will download the updated resource.</p>
<p>I went through a few ways of doing this, but I settled on the following method: whenever a resource changes, a script is run to minify any changed resources (with <a href="https://groups.google.com/group/minify">Minify</a>), the minified resources are then saved to disk with a hash of the resource’s contents appended to the filename, and a manifest is created that contains all of the original URLs and all of the versioned URLs. I’ve found this solution optimal because it allows each resource to be versioned separately, it lowers the dependencies for serving the files (a simple HTTP server is all that’s required), and the manifest file allows the original URLs to be used in code.</p>
<p>The manifest file is used in any code that needs the URL to a resource. I can simply look up the current versioned URL (e.g. “/home-3.css”) by supplying the original URL (e.g. “/home.css”), so I don’t have to change any URLs when the resources are updated.</p>
<p>The end result is that each resource gets served with an Expires header with a long time and the browser can hold onto the resource for as long as its cache can handle it. If there’s a change, a simple recompile will update all of the appropriate resources, and only the changed files will be downloaded by the browser, creating a better experience for your users.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/using-far-future-expires-for-static-resources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conducting Usability Tests for Websites</title>
		<link>http://chasenlehara.com/blog/conducting-usability-tests-for-websites/</link>
		<comments>http://chasenlehara.com/blog/conducting-usability-tests-for-websites/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 05:07:02 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=114</guid>
		<description><![CDATA[I conducted a usability test for Seller’s Market last week and a friend asked me about my method. The following post is a look at how I conduct usability tests for websites. Why? Usability testing is useful for determining three things: what captures users’ attention on your site, your website’s effectiveness, and your website’s usability. [...]]]></description>
			<content:encoded><![CDATA[<p>I conducted a usability test for <a href="http://sellersmarket.biz/">Seller’s Market</a> last week and a friend asked me about my method. The following post is a look at how I conduct usability tests for websites.</p>
<h3>Why?</h3>
<p>Usability testing is useful for determining three things: what captures users’ attention on your site, your website’s effectiveness, and your website’s usability. The first is important because you’ll want to learn what the user looks at on your site; you have a problem if your message isn’t being delivered immediately or your users never end up looking at your call-to-action. The second item, your website’s effectiveness, is important because if your message isn’t being quickly and efficiently conveyed to your users, they might leave the site with no memory of what you actually do for them. Third, it’s important to determine whether or not your website’s design and forms are easy to use—if users have a difficult time completing your call-to-action, then your website isn’t converting as many users as it could.</p>
<p>[I’ve mentioned call-to-action twice now; presumably, you want your users to do something (sign up, call you, buy something, etc.)—your call-to-action is whatever is asking/telling them what to do next. In the case of <a href="http://sellersmarket.biz/">Seller’s Market</a>, we want them to either call a broker or fill out our <a href="http://sellersmarket.biz/thinking-about-listing/get-started-now/">Get Started Now form</a>.]</p>
<h3>What to test and how to test it</h3>
<p>Before you conduct your usability test, you’ll need to sit down and determine what you want to test and how you want to test it. For determining what captures a user’s attention, I suggest having them look at the page for about ten seconds and then asking them what they remember looking at and what they remember from the page. This should help you determine what captures their attention and whether or not you’re conveying your message quickly enough.</p>
<p>I also suggest testing your website’s effectiveness by giving them a few minutes to use your site. A user should have a good idea about what your business offers them within the first ten seconds of using your site, but giving them a few minutes to soak up the rest of the information will allow you to determine whether or not the rest of the text properly conveys what you what them to understand.</p>
<p>To test your call-to-action(s), you can ask your user about where they would go if they wanted to take advantage of what your business offers. Additionally, be sure to actually go through the pages that your user would use; have them fill out your contact form or have them sign up and start using the website. It’s really important to determine whether or not your website is actually usable, so this is where you should probably spend most of your time.</p>
<h3>Getting yourself and your user ready for the test</h3>
<p>Now that you’ve determined what you should test, I highly recommend writing down a full script of what you’ll say to your user. This helps you repeat tests in the future and phrase your questions appropriately—if you ask leading questions during the usability test, it’s probable that your user will hear the words you’re using and look for them on the site. For example, Seller’s Market has a listing search feature called <a href="http://sellersmarket.biz/search-actives/">Search Actives</a>; it’d be leading to ask a user to search for active listings, but asking them to “find properties for purchase” will make them think on their own once they don’t see a “Properties for Purchase” link.</p>
<p>I suggest keeping the user in as familiar of an environment as possible—if you can conduct the test in their home, or at least on their computer, you’ll keep them more comfortable. While I’ve never had an issue with a user testing on a computer that wasn’t theirs, it does make the situation a little bit more stressful.</p>
<p>I do recommend staying side-by-side with your user and recording audio of the entire usability test. If you can record the screen, fantastic (it’s great for reference), but it’d recommend against recording video of the user’s face while testing (recording from behind is probably okay, although I can’t say I’ve ever done this). It’s okay to have another person in the room during the test, but be sure to explain to them that they’re only there for observation.</p>
<p>I’ve used the word “test” throughout this post, but it’s very important to convey to your user that it is not a test of their ability or comprehension, but a test of the website‘s effectiveness and usability. Every user I’ve had has felt a bit pressured because it feels like the test is testing them, so do as much as possible to make the user comfortable.</p>
<p>Before you start the test, you’ll want to ask the user to speak their thoughts. You’ll need to prompt them to do this throughout the test (since most of us don’t constantly talk about what we’re reading or doing when we’re using websites), but it’s helpful to know more about their thought process.</p>
<h3>Test time</h3>
<p>Hurray! You’ve written your script, have a user that’s in your website’s target demographic, and have everything setup for a smooth usability test. Hopefully everything will be perfect and the user won’t run into any issues, but when they do, you’ll want to be prepared.</p>
<p>First, if they ever run into an issue that is not their fault, immediately intervene and help them out; I’ve conducted usability tests early enough in the testing process that bugs have cropped up—simply tell your user that it’s not their fault and walk them through whatever is necessary to get around the bug. The only other time to step in is when they become visible/audible frustrated and are unable to complete a task; you’ll want to show them what you were expecting them to do and phrase it like that (e.g. “we were expecting you to do this, but obviously we didn’t think that over well enough”).</p>
<p>Otherwise, you’ll want to stay as hands-off as is possible. This includes when they ask you questions about what happens if they were to do a certain action (e.g. “what would happen if I clicked this link?”); when users ask questions, I recommend giving them as much of a non-answer as possible (e.g. “you’re free to click on that link to find out”).</p>
<p>Your user might suggest things as well, especially if they don’t think something makes sense. While it’s great to hear what they would have done, you’ll probably need to stay as non-committal as possible and simply say that “that’s something [we’ll] definitely consider.”</p>
<p>I don’t encourage you to mislead people, but when they suggest features or say how things are, don’t bother disagreeing or stating how things are in reality. I still haven’t figured out how to smoothly deal with this: just saying “okay” can leave a bit of a bad taste.</p>
<p>Above all, you’ll need to continually give your user positive encouragement, even when they don’t complete a task or give a wrong answer. Telling them that they’re doing something “totally wrong” is really inappropriate feedback, even if they are doing something “totally wrong.” Likewise, the use of sarcasm is typically inappropriate, especially if you’re not close friends with your user.</p>
<h3>The results</h3>
<p>Before concluding the usability test, you might want to tell them that the testing is over and ask for any other comments they might have. Also, I suggest providing them a little bit of feedback regarding what you learned from the test; users can find it satisfying to complete a usability test and be of assistance.</p>
<p>After the test, I always go back through the audio I recorded during the test and write up as many notes as possible about the test. I write my notes after the test for two reasons: first, I want to be focused on what the user is doing while they’re sitting in front of me; second, you’ll probably pick up on things you didn’t catch during the test.</p>
<p>After conducting a few usability tests, you’ll have a good feel for the kinds of questions you should ask and how to handle users throughout the test. I’m hoping that this gives you a good foundation for your first usability test!</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/conducting-usability-tests-for-websites/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting Up an Apache and PHP server on Slicehost with CentOS 5.4</title>
		<link>http://chasenlehara.com/blog/setting-up-an-apache-and-php-server-on-slicehost-with-centos-5-4/</link>
		<comments>http://chasenlehara.com/blog/setting-up-an-apache-and-php-server-on-slicehost-with-centos-5-4/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 20:21:18 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=112</guid>
		<description><![CDATA[I recently set up a new slice at Slicehost for serving Seller’s Market, Frugal Me, and California Bungalow. The following post describes what was required for setting up a new CentOS 5.4 slice for serving a few PHP websites with Apache. First, I changed the DNS records at my registrar to point to Slicehost’s name [...]]]></description>
			<content:encoded><![CDATA[<p>I recently set up a new slice at <a href="http://www.slicehost.com/">Slicehost</a> for serving <a href="http://sellersmarket.biz/">Seller’s Market</a>, <a href="http://frugalme.com/">Frugal Me</a>, and <a href="http://californiabungalow.org/">California Bungalow</a>. The following post describes what was required for setting up a new CentOS 5.4 slice for serving a few PHP websites with Apache.</p>
<p>First, I changed the DNS records at my registrar to point to Slicehost’s name servers. Then, I followed <a href="http://articles.slicehost.com/2007/10/24/creating-dns-records">Slicehost’s article on creating DNS records</a>.</p>
<p>Slicehost has a great <a href="http://articles.slicehost.com/2010/4/23/centos-5-4-setup-part-1">intro to CentOS 5.4</a>; their guide will show you how to securely set up your new slice.</p>
<p>To install Apache, I followed <a href="http://articles.slicehost.com/2010/5/19/installing-apache-on-centos">Slicehost’s guide to installing Apache on CentOS</a>. Then, I followed <a href="http://articles.slicehost.com/2008/12/12/centos-apache-virtual-hosts-1">their guide to setting up the virtual hosts</a> (for the multiple domains I plan to run on a single slice); I diverged from their directory layout without any problems.</p>
<p>Earlier, I mentioned that I decided to use CentOS 5.4; this is because I wanted to run a newer version of PHP with as little hassle as possible. I used <a href="http://www.webtatic.com/blog/2009/06/php-530-on-centos-5/">this guide to installing PHP 5.3 on CentOS 5</a>.</p>
<p>After PHP was installed, I still needed a few application-specific items: Memcached, MCrypt, and MySQL. These were easy to install with the repository from the above article:</p>
<ul>
<li>Memcached: sudo yum install &#8211;enablerepo=webtatic php-pecl-memcached</li>
<li>MCrypt: sudo yum install &#8211;enablerepo=webtatic php-mcrypt</li>
<li>MySQL: sudo yum install &#8211;enablerepo=webtatic php-mysql</li>
</ul>
<p>And that’s it! Hopefully this post is a helpful guide in getting started with Slicehost. While I haven’t actually had any sites live with Slicehost yet, the experience has been great thus far and I’d recommend them to anyone looking for more advanced hosting. If you haven’t signed up with them yet, I’d appreciate your use of <a href="https://manage.slicehost.com/customers/new?referrer=6766bd8e48267076c719b606f0c94492">this referral url</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/setting-up-an-apache-and-php-server-on-slicehost-with-centos-5-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More on Using ETags and UUIDs for Internal Caching</title>
		<link>http://chasenlehara.com/blog/more-on-using-etags-and-uuids-for-internal-caching/</link>
		<comments>http://chasenlehara.com/blog/more-on-using-etags-and-uuids-for-internal-caching/#comments</comments>
		<pubDate>Mon, 31 May 2010 22:25:14 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=91</guid>
		<description><![CDATA[A while back, I wrote about ETags and how they could be used within a web application for caching. Since then, I’ve had some time to work with using ETags and UUIDs in two applications—Iron Money and a yet-to-be-launched site. Both of these sites use ETags and UUIDs for their resources; when a resource is [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, <a href="http://chasenlehara.com/blog/more-on-etags/ ">I wrote about ETags</a> and how they could be used within a web application for caching. Since then, I’ve had some time to work with using ETags and UUIDs in two applications—<a href="https://ironmoney.com/">Iron Money</a> and a yet-to-be-launched site.</p>
<p>Both of these sites use ETags and UUIDs for their resources; when a resource is created, it’s given a UUID and an ETag; when it’s updated, the ETag is changed. They also use Memcached for caching resources; when a resource is created, the Memcached key is the UUID and ETag; when the resource is updated, the resource is simply stored again. Memcached already throws out objects that haven’t been fetched recently, so the old resources eventually fall out of the cache.</p>
<p>When a resource is requested, both sites simply look up the ETag in the database and then check the cache to see if the resource is already stored. If it’s not, then they go through the regular process of fetching the resource from the database. This is particularly efficient because the database can easily have an index on the UUID and ETag, making it very cheap (less than a millisecond) to look up the most recent ETag before fetching from the cache.</p>
<p>For resources that are compromised of other resources (say, a list of accounts), the process is the same; the ETag for the main resource is fetched (the /accounts/ ETag), and Memcached stores a list of UUIDs for the resource (all of the account UUIDs). Then, each resource is fetched individually with the same process (get the ETag, check Memcached for the resource). This means that the resources are not stored multiple times in the cache, but the entire list of resources can still be cached.</p>
<p>Overall, this system works very well; most resources stay in cache and there are no concerns regarding ACID compliance. However, one issue that I have run into is with the aforementioned lists of resources. For small lists of resources, the system works very well; it takes about a millisecond to get the ETag for the list of resources, and then takes about a millisecond for each resource.</p>
<p>This, however, does not work well with very large lists of resources. Even with everything in cache, a millisecond for each resource in a list can take too long if there are 100 or more resources to fetch from the cache.</p>
<p>So what’s the solution? If you’re willing to trade memory for speed, then there’s a rather simply solution: simply store the ETags for each of the resources in a list. By storing the UUIDs and ETags for each resource in a list, you can avoid looking up each resource’s ETag, which will make everything faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/more-on-using-etags-and-uuids-for-internal-caching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing Basic Text Search</title>
		<link>http://chasenlehara.com/blog/implementing-basic-text-search/</link>
		<comments>http://chasenlehara.com/blog/implementing-basic-text-search/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 23:54:02 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=82</guid>
		<description><![CDATA[I added text search to Iron Money in early March and had a few requirements: I wanted to implement the AND and OR operators, I wanted to support quotes for exact matches, I wanted to support a “not” operator (“-”), I didn’t want any stop words, and I needed to be able to search encrypted [...]]]></description>
			<content:encoded><![CDATA[<p>I <a href="http://blog.ironmoney.com/2010/03/03/introducing-transaction-search/">added text search to Iron Money</a> in early March and had a few requirements: I wanted to implement the AND and OR operators, I wanted to support quotes for exact matches, I wanted to support a “not” operator (“-”), I didn’t want any <a href="http://en.wikipedia.org/wiki/Stop_words">stop words</a>, and I needed to be able to search encrypted text. Here are some examples of queries I wanted to support:</p>
<ul>
<li><b>a b</b> [both a and b]</li>
<li><b>a or b</b> [a or b]</li>
<li><b>“a b”</b> [the string “a b”]</li>
<li><b>-a b</b> [strings that contain b but not a]</li>
</ul>
<p>I decided that implementing my own text search would be my best option with those requirements. I wasn’t able to find any good articles about implementing text search, thus I’ve decided to write up my thoughts here. I can’t guarantee that this is the best solution for you, but given the above contraints it was the best option for <a href="https://ironmoney.com/">Iron Money</a>.</p>
<p>The first thing I do is parse the string like a CSV with PHP’s str_getcsv(). str_getcsv() is a function for parsing CSV strings; I set the delimiter to the space character and leave the enclosure to the default &#8216;&#8221;&#8216;. If you’re writing this in another language, any CSV parser should do the trick; just make sure it splits the search text by spaces and respects quote values.</p>
<p>After I get an array of strings with str_getcsv(), I run through that array and add it to a brand new array (we’ll call it $parts). As I run through the strings, I check to see if the string starts with &#8216;-&#8221;&#8216;; this indicates that the next string in the array is going to be a NOT value. Once I get to the next string, I append the rest of the NOT value to the previous string that was added to the $parts array and continue with the rest of the array. We end up with an array of $parts that has an array of strings.</p>
<p>With $parts in hand, I check each string in $parts to find if any of the strings are the word “or”. If the string is “or”, then I know that the string before and after the “or” belong to that “or”; thus, both of them are added to a special $or_conditions array, and I remove the three strings from the $parts array.</p>
<p>At this point we have two arrays: $parts has all of our AND conditions, while $or_conditions has all of our OR conditions. My goal, however, is to have an array of all of the conditions that a string must meet; this includes values that it needs to contain, values that it should not contain, and a list of OR conditions which the string must meet. Thus, I create a $conditions array which will contain all of the conditions a string must meet to match the search.</p>
<p>We continue along by creating a new array ($condition) with two values: a $contains array and a $does_not_contain array. We run through all of the strings in $parts; remember, all of the strings in the $parts array are AND conditions. We check each string in $parts to see if it starts with the “-” character; if it does, we put the string in $does_not_contain; otherwise, we put the string in $contains. After running through all of the strings in $parts, we’ll end up with a single $condition array that we add to the $conditions array; it represents all of the AND conditions.</p>
<p>Now we move on to the $or_conditions array. For each of the $or_conditions, we’ll create a new $condition that has a $contains array, a $does_not_contain array, and a value called “operator” that indicates that this is an OR condition. We use the same process as before to modify the $condition array, and then add it to the $conditions array.</p>
<p>At this point in time, you have a $conditions array that has a list of conditions a string must meet to match the search. Each value of the $conditions array has a $contains and $does_not_contain array, and it might have an “operator” value to indicate if it’s an OR condition.</p>
<p>Now, we get all of the potential candidates to search through. In Iron Money’s case, we have an array of transactions that we need to sift through; if the “name” or “description” attribute matches the text search, then the candidate is returned in the search results.</p>
<p>To determine whether or not a value matches the search conditions, we run through the $conditions array that we created earlier. For each $condition, we check to see if the candidate strings match the $condition—if the strings have the $contains text and don’t have the $does_not_contain text. If the candidate is a match, we add it to the search results.</p>
<p>Manually implementing text search can be a real pain; I think it’s almost always better to use existing, proven solutions for text-matching needs. However, if you’re in a situation like I was with Iron Money, hopefully the above will be useful when implementing a robust text-matching algorithm.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/implementing-basic-text-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More on ETags</title>
		<link>http://chasenlehara.com/blog/more-on-etags/</link>
		<comments>http://chasenlehara.com/blog/more-on-etags/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 03:45:07 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=54</guid>
		<description><![CDATA[In a previous post, I mentioned how including the ETag and Last-Modified headers in an API can be a real benefit to third-party clients. What I didn’t mention is how ETags can provide a large benefit inside your API as well. This post is about implementing ETags in your application and using them to make [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://chasenlehara.com/blog/creating-restful-web-services/">a previous post</a>, I mentioned how including the ETag and Last-Modified headers in an API can be a real benefit to third-party clients. What I didn’t mention is how ETags can provide a large benefit inside your API as well. This post is about implementing ETags in your application and using them to make your application more efficient.</p>
<p>ETags, or entity tags, are identifiers for a resource. In short, they are similar to version identifiers for resources; when a resource changes, its ETag changes. When a client <code>GET</code>s a resource, they can store the associated ETag; then, the next time they <code>GET</code> the resource, they can ask for the resource only if it has changed; or, if they fancy, the client could even make a request that should only be executed if they have the latest ETag for a resource!</p>
<h3>Strong and weak</h3>
<p>One thing I didn’t mention in my original post is that there are two different kinds of ETags: strong and weak ETags. A strong ETag changes whenever a resource changes <em>at all</em>; if any bit in the resource changes, a new ETag is required. Weak ETags, on the other hand, change whenever the resource semantically changes; a resource won’t necessarily have a new ETag if it means the same thing as its previous version.</p>
<p>So how should you generate your ETags? Strong ETags would probably best be generated right after the message body is generated or if entire message bodies are stored by the API; alternatively, for a more effective use of ETags, you could regenerate them whenever the resource changes, although that might be an expensive solution. [In practice, what <a href="https://ironmoney.com/">Iron Money</a> does is create a hash from the data and then stores the hash with the data in MySQL. Your mileage may vary.]</p>
<p>Weak ETags, on the other hand, could be generated from the internal representation of resources in your API. Whenever the resource is changed, simply generate the weak ETag and store it along with the resource’s data.</p>
<p>If you provide a resource that lists a bunch of child resources (e.g. a <code>/books/</code> resource that lists all of the book resources), I highly recommend creating an ETag for the resource from all of the ETags of the child resources; this way, you don’t need to generate the entire list when one of the child resources changes.</p>
<p>Generating ETags for resources that are searchable can be problematic. You could generate the list of child resource ETags and create the ETag from that; however, this requires you to perform the search even when the request is conditional. Another way of handling the problem is to use the same ETag for the search as you would use for the entire resource (e.g. the ETags for <code>/books/</code> and <code>/books/?author=Steinbeck</code> would be the same). I recommend doing the latter; it saves you time and shouldn’t hinder clients’ use of your API.</p>
<h3>Using ETags internally for caching</h3>
<p>The benefits of ETags to third-party clients is rather obvious, but how can ETags be used within your application?</p>
<p>If you’re using a caching system (like <a href="http://memcached.org/">Memcached</a>), you’re probably storing your resources by their <a href="https://www.ietf.org/rfc/rfc4122.txt">UUID</a> or by some sort of resource and primary key identifier. Whenever a resource is created, you put it in the cache; whenever a resource is updated, you delete it from the cache or update the cache, and whenever a resource is deleted, you delete it from the cache.</p>
<p>This might work well for your application. However, cache invalidation can be difficult, especially if your application requires <a href="http://en.wikipedia.org/wiki/ACID">ACID</a> capabilities.</p>
<p>ETags can help your application with both of these issues. If you store each resource by its primary identifier and its ETag, you can always be sure that each cache lookup will only return the version of the resource you want. For example, if you’re simply getting a resource, you can look up its ETag in your database, then retrieve the entire resource from the cache and be sure that, if it’s in the cache, then it’s the correct version that you want. Additionally, you don’t have to worry about cache invalidation, because there is no invalidation—you simply let your cache system remove the old versions of resources as the cache fills up.</p>
<h3>ETags: because its good for the Internet</h3>
<p>ETags are surprisingly powerful once you start to make the most of them. They help HTTP clients cache resources and make conditional requests, and they can help your application with its caching needs as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/more-on-etags/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Iron Money Public Beta</title>
		<link>http://chasenlehara.com/blog/iron-money-public-beta/</link>
		<comments>http://chasenlehara.com/blog/iron-money-public-beta/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 23:10:00 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Iron Money]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=52</guid>
		<description><![CDATA[I’ve been working on a personal finance web app called Iron Money for the past couple of years. In September 2008 I released it as a private beta; you could sign up and use the API, but to actually use the web app you’d need my approval. Last week, I made the Public Beta available [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on a personal finance web app called <a href="https://ironmoney.com/">Iron Money</a> for the past couple of years. In September 2008 I released it as a private beta; you could sign up and use the API, but to actually use the web app you’d need my approval. Last week, I made the <a href="http://blog.ironmoney.com/2010/02/10/iron-money-public-beta/">Public Beta</a> available for everyone to use—no special approval, just <a href="https://ironmoney.com/sign-up/">sign up</a> and go.</p>
<p>This post is an in-depth look at the kind of decisions that went into making the current version of Iron Money.</p>
<h3>Simplify</h3>
<p>I focused on making this release as simple as possible. I wanted a simple, well-tested foundation for future versions of Iron Money; thus, I actually cut features from the private beta. I wasn’t happy about cutting some features: I think the undo/redo feature was great from a usability perspective and the budgeting feature was something that was very useful. By the end of September, however, I knew that if I was going to get the public beta out the door, I’d need to cut down on things for the initial release and focus on the features that were core to Iron Money’s purpose: keep users up to date on their finances.</p>
<p>The simplification theme extended to the features that were kept as well. For example, I changed how categories worked so that they were easier to use (Iron Money used to have four default categories, two of which could have children categories; now, it has three default categories, all of which can have children categories).</p>
<h3>Everything has a UUID</h3>
<p>One of the things that changed fairly early on was my move from using MySQL’s auto-incrementing primary keys as IDs to using UUIDs for IDs. The primary reason for this change was my desire to make sharding user’s data easy. With UUIDs, I don’t need a central table dictating the IDs for everything and I don’t need a complicated auto-increment scheme; instead, I can add as many shards as I want to as Iron Money’s user-base grows.</p>
<h3>Everything has an ETag</h3>
<p>Iron Money now keeps track of an ETag for every resource. In a future post I’ll talk more about how Etags are used by Iron Money, but creating an ETag for each resource allows Iron Money to support better caching through the API. Whenever something is added, edited, or deleted from Iron Money, at least one resource’s ETag is updated.</p>
<h3>api.ironmoney.com</h3>
<p>Iron Money now uses a new domain exclusively for <a href="https://ironmoney.com/api/">the API</a>. This was mainly brought on for security reasons: I didn’t want any cookies set on ironmoney.com to be available on api.ironmoney.com. Furthermore, I think it’ll make it easier to run the API on a separate server in the future.</p>
<h3>OAuth permissions</h3>
<p>Iron Money’s API now supports a <a href="https://ironmoney.com/api/permissions/">permission system</a> that is fairly flexible: instead of authorizing an application to access all of your Iron Money data, the application can limit itself to just what it needs to access. For example, an application can ask for read permission to your accounts if it wants to show you your latest balances, without requiring read or write access to anything else.</p>
<p>The permissions system is a win for both third-party applications and users. Users have a clearer understanding of exactly what they’re authorizing an application to do, while apps can prove that they are only reading your information (instead of making it just a trust issue).</p>
<h3>Almost everything is cached</h3>
<p>a href=&#8221;http://memcached.org/&#8221;>Memcached</a> is an amazing caching system; if you’re not using it in your web app or API right now, you’re missing out on faster reads. Basically, whenever data is written to Iron Money, it updates its cache and almost every subsequent read is from memory.</p>
<h3>Simple can be difficult</h3>
<p>Rewriting Iron Money over the past few months has been a lot of work, but I think the changes above will pay off in the long run with a faster, easier to use Iron Money.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/iron-money-public-beta/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>API First and Only Features</title>
		<link>http://chasenlehara.com/blog/api-first-and-only-features/</link>
		<comments>http://chasenlehara.com/blog/api-first-and-only-features/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 21:48:02 +0000</pubDate>
		<dc:creator>Chasen Le Hara</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://chasenlehara.com/blog/?p=48</guid>
		<description><![CDATA[A few days ago, Kellan Elliott-McCrea asked: Anyone have thoughts/experiences with API first, or API only features? Yes. I initially worked on the API for Iron Money while working on the iPhone app. While I never finished the iPhone app (it’s currently sitting in a Subversion repository while I work on Iron Money’s Public Beta), [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, <a href="http://laughingmeme.org/">Kellan Elliott-McCrea</a> asked: <a href="https://twitter.com/kellan/status/7924630962"><q cite="https://twitter.com/kellan/status/7924630962">Anyone have thoughts/experiences with API first, or API only features?</q></a></p>
<p>Yes. I initially worked on the API for <a href="https://ironmoney.com/">Iron Money</a> while working on the iPhone app. While I never finished the iPhone app (it’s currently sitting in a Subversion repository while I work on Iron Money’s Public Beta), Iron Money’s API has had API-first and API-only features (and will continue to in future versions).</p>
<h3>API-first</h3>
<p>API-first features, or features that come to a web service’s API before making it to the web app, can be useful for “testing” new features. For features that can be thoroughly thought through, adding the feature to an API first can be an easy way of letting third-party developers start working with the feature and see what kind of issues and functionality should be added before adding the feature to the web app.</p>
<p>An example of an API-first feature in Iron Money’s private beta was the multi-transaction editing functionality. Editing multiple transactions at the same time was too-complex of a task to add into the initial interface, but adding it to the API was trivial; eventually, the web app “caught up” with the API with regard to this functionality.</p>
<h3>API-only</h3>
<p>API-only features, or features that are only exposed through an API (and not through the web app), are similar to API-first features; neither are exposed in the web app first. However, API-only features might serve two additional purposes: to provide advanced, potentially more complex functionality, and to make more things possible for third-party apps.</p>
<p>An example of an API-only feature in Iron Money is its notification functionality. It doesn’t make sense for a user to be able to write and send themselves a notification, but it does make sense to allow third-party developers to send their users a notification.</p>
<p>While a feature is API-only, I highly recommend making sure that it doesn’t break the web app (or any other apps for that matter). One way an API might break a web app is if the functionality in the API is more advanced than in the web app; the web app might need to support displaying what can be done through the API.</p>
<p>Let’s say, for example, you’re building a calendar API and web app. You might initially build the web app to support very simple event repetition (say, every day, week, month, and year). However, you might allow the API to do more complex repeats (say, every three days or every January of every other year).</p>
<p>What you want to avoid is having a user set up their events in another calendar app (which does support the API’s more advanced event repetition) and viewing it in your simplified web app. The web app should not break because the event was created through the API; your web app should still display the event correctly.</p>
<h3>An API before a web app</h3>
<p>There’s one more concept I’d like to discuss: building your API before building your web app. <a href="http://inessential.com/">Brent Simmons</a> mentioned this idea in <a href="http://inessential.com/2008/03/18/the_coming_gold_rush">a post about the iPhone App Store Gold Rush</a>, in which he theorized that APIs and iPhone apps might be built together (instead of building the web app, API, and client apps in tandem).</p>
<p>As I mentioned earlier, I built Iron Money’s first public API while writing an iPhone app for it, all of which came before writing the web app. I would avoid doing this again because, as <a href="http://metaatem.net/">Erik F. Kastner</a> brought up on Twitter, <a href="https://twitter.com/kastner/status/7926961290"><q cite="https://twitter.com/kastner/status/7926961290">it can limit your ability to make the right thing</q></a>. I’ve found that engineering the perfect solution ahead of time can result in suboptimal solutions—even if it looks really good in theory.</p>
<p>Here’s an example of this problem in action. In Iron Money’s private beta, transactions could be categorized into three different types of categories: Income, Spending, Transfer, and Uncategorized. Everything would go into Uncategorized by default so that users could have a quick overview of what still needed to be categorized. The Uncategorized category was a sensible default category for all transactions.</p>
<p>However, as I found out while writing the web app, this is an inefficient way of solving the problem of tracking a user’s money. Categorization, as a feature, is mainly useful for searching and reporting. For reporting things such as a person’s income and spending, the web app needed to figure out what was income and what was spending. For transactions in the Uncategorized category, it would guess that positive amounts were income and negative amounts were spending.</p>
<p>This guessing didn’t make things any easier on the web app or any other app built on top of the API; everyone would have to implement their own guessing algorithm. Furthermore, the default graphs for categories weren’t very helpful to users because everything was lumped together by default. At the end of the day, what seemed like the best idea while writing the API turned out to be a suboptimal decision.</p>
<p>I think that building an API as a foundation for your web app and client apps is a good idea; building an API with third-party applications in mind is also a good idea, even if you don’t expect to make it public in the near future. However, I don’t believe that making a brand new API available to the public is a good idea until you’ve had enough time to ensure that your API promotes the best experience for both your users and API consumers.</p>
]]></content:encoded>
			<wfw:commentRss>http://chasenlehara.com/blog/api-first-and-only-features/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.352 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-05 06:30:54 -->
<!-- Compression = gzip -->
