<?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>Grant&#039;s Space</title>
	<atom:link href="http://www.grantgrueninger.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grantgrueninger.com</link>
	<description>Life, The Universe, and Funny Stuff</description>
	<lastBuildDate>Thu, 05 Jan 2012 23:58:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Apple, why did you kill my Siri?</title>
		<link>http://www.grantgrueninger.com/2011/11/21/apple-why-did-you-kill-my-siri/</link>
		<comments>http://www.grantgrueninger.com/2011/11/21/apple-why-did-you-kill-my-siri/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 03:12:38 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Theories and Observations]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[computers]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPhone 4s]]></category>
		<category><![CDATA[Siri]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/2011/11/21/apple-why-did-you-kill-my-siri/</guid>
		<description><![CDATA[Do you think Siri is cool? Then you probably didn&#8217;t use the original app, and you probably also never heard of the 60&#8242;s program &#8220;Eliza&#8221;. I used to be able to ask Siri for actual information, and get real answers. I could ask it to reserve a table for two at Beausejour at 8 o&#8217;clock, [...]]]></description>
			<content:encoded><![CDATA[<p>Do you think Siri is cool? Then you probably didn&#8217;t use the original app, and you probably also never heard of the 60&#8242;s program &#8220;Eliza&#8221;.</p>
<p>I used to be able to ask Siri for actual information, and get real answers. I could ask it to reserve a table for two at Beausejour at 8 o&#8217;clock, and it would place the reservation. I could ask it what good movies were playing nearby, and it would show a list of movies ranked high (on rotten tomatoes) that were playing near me with a list of theaters. I could even tap to buy tickets.</p>
<p>But no more. Siri&#8217;s become stupid. Like tragic car crash stupid. The kids in school make fun of it (literally).  And that&#8217;s all it&#8217;s good for. If I ask it to make a reservation at a restaurant at 8pm, it&#8217;ll respond with &#8220;there&#8217;s a restaurant named Beausejour near you&#8221;. Great, I already knew that. Ask it for movies and it&#8217;ll just display a list of theaters. Ask it almost anything else and it&#8217;ll say &#8220;I don&#8217;t understand&#8221;. It&#8217;s not good at scheduling, texting, or calling; not better than just tapping and typing at least.</p>
<p>Why does it take hackers to try to revive what used to be a great app?</p>
<p>I miss Siri.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/11/21/apple-why-did-you-kill-my-siri/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to develop excellent websites and web applications easily</title>
		<link>http://www.grantgrueninger.com/2011/10/23/how-to-develop-excellent-websites-and-web-applications-easily/</link>
		<comments>http://www.grantgrueninger.com/2011/10/23/how-to-develop-excellent-websites-and-web-applications-easily/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 10:31:33 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[How To - Advice]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[RESTful]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[URI]]></category>
		<category><![CDATA[w3.org]]></category>
		<category><![CDATA[web design]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[web services]]></category>
		<category><![CDATA[web sites]]></category>
		<category><![CDATA[web standards]]></category>
		<category><![CDATA[www]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=380</guid>
		<description><![CDATA[Developing a great web site or web application is really very easy, but there are many ways to do it badly, and that makes it difficult. Here&#8217;s how to do it &#8220;right&#8221;. A URI identifies each and every resource Gather your content, and code it in straight, standard, valid XHTML Lay out your content using [...]]]></description>
			<content:encoded><![CDATA[<p>Developing a great web site or web application is really very easy, but there are many ways to do it badly, and that makes it difficult.</p>
<p>Here&#8217;s how to do it &#8220;right&#8221;.</p>
<ol>
<li>A URI identifies each and every resource</li>
<li>Gather your content, and code it in straight, standard, valid XHTML</li>
<li>Lay out your content using CSS</li>
<li>Ignore the flashy new technology, stick with well-established basics</li>
</ol>
<p>These 4 simple rules are all you need to design great sites. Companies are constantly trying to push their fancy new technologies, and browser makers put proprietary features into their browsers hoping you&#8217;ll use them, and force people to use their browser. Unfortunately, this just makes your site unusable to people not using that browser.</p>
<h2>A URI identifies each and every resource</h2>
<p>URI means &#8220;Unique Resource Identifier&#8221;. Originally, and sometimes still, this meant that each page on a server was identified by a Unique string. It&#8217;s a great, simple concept: any given set of content should have a unique URI (yes, that&#8217;s redundant). This blog page, for example, has a unique string that identifies it. You can send that string to your friends (hint hint), and if they put it in a web browser, they&#8217;ll see this article. Seems straight forward, but many many web sites break this rule. For example, if I&#8217;m searching for flights on a travel site and have a certain set of flights displayed, I should be able to copy the URI and send it to my friend. Unfortunately, this rarely works. If I load up my shopping cart with stuff at Amazon.com, I should be able to send that cart to my friend. I can&#8217;t.</p>
<p>Make your sites RESTful. That&#8217;s a fancy word meaning &#8220;use the web the way it was designed&#8221;. The O&#8217;Reilly &#8220;RESTful Web Services&#8221; book is excellent extended reading on this subject:</p>
<p><a href="http://www.amazon.com/gp/product/0596529260/ref=as_li_ss_tl?ie=UTF8&#038;tag=cscorpcom-20&#038;linkCode=as2&#038;camp=217145&#038;creative=399369&#038;creativeASIN=0596529260">Restful Web Services</a><img src="http://www.assoc-amazon.com/e/ir?t=cscorpcom-20&#038;l=as2&#038;o=1&#038;a=0596529260&#038;camp=217145&#038;creative=399369" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<p>URIs are fancy things that can include a LOT of information. Let&#8217;s take the examples I gave above and do them right:</p>
<h3>Filtering flights</h3>
<p>I see filters on web sites done wrong all the time, and it drives me nuts. It&#8217;s so easy to do right, and would be so convenient. I apologize, because now you&#8217;re going to be driven nuts too.</p>
<p>Each element of a filter should be included in the URI. Lets say you&#8217;re setting up a travel site. People fill in departing and arriving airport, dates, and preferred time range. They click a &#8220;search&#8221; button. The button should encode that search into a GET request (NOT A POST!), which then displays the result. So it might look like</p>
<p>http://www.mytravelsite.com/flightsearch?dep_loc=lax&amp;arrive_apt=nyc&amp;dep_time=12&amp;dep_date=2011-10-20&amp;ret_date=2011-10-30. (I&#8217;ve left a lot of potential detail out, like return time, for brevity).</p>
<p>Say your result page then has additional filters. It&#8217;s really fancy, and clicking a column header sorts by that column. When a user clicks a filter, say selecting a max price of $500 per flight, the URI should change to, say, include &#8220;max_price=500&#8243;.</p>
<p>http://www.mytravelsite.com/flightsearch?dep_loc=lax&#038;arrive_apt=nyc&#038;dep_time=12&#038;dep_date=2011-10-20&#038;ret_date=2011-10-30&#038;max_price=500</p>
<p>Now we sort by price:</p>
<p>http://www.mytravelsite.com/flightsearch?dep_loc=lax&#038;arrive_apt=nyc&#038;dep_time=12&#038;dep_date=2011-10-20&#038;ret_date=2011-10-30&#038;max_price=500&#038;sort_by=price</p>
<p>Now that&#8217;s a nice URI I can email to my friend and say &#8220;look at the cool flights to New York, let&#8217;s go!&#8221;. It&#8217;ll have the exact filters I selected and even be sorted the same. This URI represents &#8220;Flights from LAX to NYC departing Oct 10, 2011, returning Oct 20, 2011 that cost less than $500 ordered by price&#8221;.</p>
<p>Sadly, you&#8217;ll see similar results on sites that might include the flight info, but once you start clicking on options like price, time windows, and sorts, those don&#8217;t factor into the URI.</p>
<h3>Shopping Cart</h3>
<p>I&#8217;ve never seen this done right, but it&#8217;s so easy to do right.</p>
<p>To be RESTful, (and have unique resources to identify), you shouldn&#8217;t maintain &#8220;state&#8221; on the server. That means no session cookies (although I&#8217;ll concede to an authentication token, but I&#8217;ll get to that later). &#8220;But how do I store my user&#8217;s shopping cart&#8221; you ask? Let&#8217;s follow the rule: A shopping cart with certain items in it is a resource. That resource should have a unique identifier. If I go to that identifier (URI) later, I should see the same cart. If I send the URI to my friend, they should see the same cart.</p>
<p>http://www.myshoppingsite.com/cart/myusername</p>
<p>So as I shop and click &#8220;add to cart&#8221;, my items get POSTed to /cart/myusername. A GET to /cart/myusername returns the items in the cart. Ideally, this would be a basic XML document that gets wrapped with a page layout via an appropriate CSS style sheet (sticking to the content/layout separation rules). That way, you could use it in an API to an iPhone app, or as a mobile web page, or as a normal web page by just using the right style sheet. But we&#8217;re not talking about that yet.</p>
<p>From here you might want to let the user set up multiple shopping carts. You could have:</p>
<p>http://www.myshoppingsite.com/cart/myusername/12345</p>
<p>A POST to http://www.myshoppingsite.com/cart/myusername/ now would create a new cart and return its ID (e.g. in the resulting web page). Subsequent pages would then POST to /cart/myusername/12345. The user could then create carts specifically to email to friends, e.g. &#8220;here&#8217;s a cart of all the stuff you need to build the game PC we were talking about&#8221;.</p>
<p>For details on how to formulate RESTful URIs, read that O&#8217;Reilly book above. And notice that handy URI that takes you to a page on Amazon.com and tells them I sent you. <img src='http://www.grantgrueninger.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>I&#8217;ve mentioned &#8220;GET&#8221; and &#8220;POST&#8221; above. These are HTTP methods. There are four total methods: GET, PUT, DELETE, and POST. These tell a server to GET a resource, PUT (change or replace) it, DELETE it, or add to it (POST). So if we were maintaining a database of products, product number 12345 might be identified by the URI http://www.mysite.com/product/12345. A PUT to this URI would change the product. A DELETE would delete the product. A GET would return the product&#8217;s info. You wouldn&#8217;t POST to this product. However, to create a new product, you would POST to http://www.mysite.com/product/, which could create a new product and return a new product number for it. You can read all about that in the RESTful Web Services book.</p>
<p>I mention HTTP methods because there&#8217;s a sub-rule that&#8217;s frequently broken in web pages: GET should be used to retrieve information, and POST should be used to change it. When you&#8217;re writing a web form in HTML, you can specify the method in the &#8220;form&#8221; tag. If you&#8217;re doing a search form, this method should be &#8220;GET&#8221;. If you&#8217;re changing a user&#8217;s password, it should be &#8220;POST&#8221;. HTML doesn&#8217;t support PUT or DELETE. If you use the wrong method, you&#8217;re hindering your site, and you could end up doing real damage in some cases. For example, if you POST a search form, the user can&#8217;t bookmark it and send the results to his friends. That could be (lots of) lost business. If you use GET in a form that adds a new product, you could accidentally hit &#8220;back&#8221;, and that product would be created again. If you reload the page, it&#8217;d be created again and again. What if you did that with a credit card order form? That could be hard to explain. Stick with good URIs, and use GET to get, POST to change, and you&#8217;ll make great sites.</p>
<h2>Gather your content, and code it in straight, standard, valid XHTML</h2>
<p>People frequently do this step backwards, and it gets confusing. They think they want a site to look cool, so the focus on graphics and/or use a template. That&#8217;s like painting a picture before you know what you want to paint.</p>
<p>One thing is true of every single web site: its sole purpose is to get some information to someone. Someone wants something, and a great site gets whatever that is to the user as easily as possible. If your site is a store, the perfect site would read the customer&#8217;s mind, charge their card, and ship the item they wanted to them. Your job is to get as close to that as possible.</p>
<p>So when you start designing your site, get your content together before ANYTHING else. If you&#8217;re starting a store, gather your inventory and marketing text. If you&#8217;re advertising your company&#8217;s services, get the info about your company together.</p>
<p>Break the information into chunks that are easy to search and navigate. e.g. on most basic company sites, you&#8217;ll have a page of contact/location information, a basic introduction page, a page with more detailed info about the company, and a page about your products or services.</p>
<p>Each chunk becomes a resource, and gets its own URI (for a basic web site, that means each page gets a URI, which is what happens if you put a page on a web server anyway. So you&#8217;ll get http://www.mysite.com/about.html, for example.)</p>
<p>The content goes into straight, boring XML or XHTML. No layout information. If I look at it, it should look like a linear outline. This means any device or browser will be able to display it. Or, an iPhone app could read it.</p>
<p>If you find yourself thinking about layout here, stop it. If you output a navigation menu, it should look like a bullet-point list. Use attributes to give classes and IDs to your elements. Then the CSS can use that information to create any layout you want.</p>
<p>Your page output should look something like this:</p>
<pre>&lt;xhtml&gt;
  &lt;head&gt;
    &lt;title&gt;My Company - About Us&lt;/title&gt;
    &lt;LINK REL=StyleSheet HREF="style.css" TYPE="text/css" MEDIA=screen&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;a href="/index.html"&gt;Home&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;...
    &lt;/ol&gt;

    &lt;h1&gt;About Us&lt;/h1&gt;

    &lt;p&gt;We are a company that does stuff and things ...&lt;/p&gt;
  &lt;/body&gt;
&lt;/xhtml&gt;</pre>
<p>Notice there&#8217;s nothing about layout in there. The navigation information is just in &#8220;li&#8221; tags, and the content of the page, if displayed without a style sheet, will just look like a boring outline.</p>
<p>The navigation menu, in REST parlance, provides information to the client about available resources based on the request for the current resource. In short, it tells you places you could go from here. The client (e.g. the browser) could choose to display that information, turn it into buttons in an app, or hide it completely.</p>
<p>Once you&#8217;ve got your content in XHTML, run it through the validator at w3c.org. If you ever find yourself testing in different browsers, or writing Javascript that checks what browser the user&#8217;s using, slap yourself and stop it. The world wide web works on standards &#8211; write your code to the standards and it should work on all browsers. The browser&#8217;s job is to render a page according to the standards. If it doesn&#8217;t, that&#8217;s its problem. If developers follow the standards, browsers that don&#8217;t follow them will disappear, because users will switch to a browser that works. If you need content in a different format (e.g. XML for your iPhone app), that should appear at a different URL (for example http://api.mysite.com/cart/myusername/). But if you stick to delivering your content straight up in standard XHTML, you won&#8217;t have to go through the trouble of providing different &#8220;views&#8221; for it.</p>
<h2>Lay out your content using CSS</h2>
<p>CSS is magic. It can do incredible things, including making the boring XHTML above look like a full-blown web page. You can add background colors and images. You can place things anywhere on the page you want. You can even have the content resize based on the browser window width. You can specify layouts for different media types, including &#8220;screen&#8221;, &#8220;handheld&#8221;, &#8220;print&#8221;, and &#8220;speech&#8221;. You can change the color of a button when you click on it. You can turn the navigation list above into a tab-like navigation menu that changes colors when you click on each tab. You can anchor the nab bar to the side of the screen while the rest of the page scrolls. Read all about it at <a title="www.w3.org" href="http://www.w3.org/TR/CSS21/">w3.org</a>.</p>
<p>The point here is, use CSS to lay out the content. If you want to support a different layout on a small screen than a big one, do it in CSS.</p>
<p>I&#8217;d like to say a word about mobile content: some sites provide a subset of their main site&#8217;s content for mobile devices. This is stupid. Decide if your information is useful enough to include on your site or not. When you find yourself thinking &#8220;well, this page has too much information for a smaller screen&#8221;, maybe your page just has too much information. Consider breaking it up into smaller resources, or consider just dropping the &#8220;too much&#8221; part of the information. Don&#8217;t clutter the user&#8217;s browser and bandwidth just because it&#8217;s there. Again, this goes back to the &#8220;gather your content first&#8221; rule. If the user just wants to know the time, don&#8217;t give them a map of the world along with it.</p>
<h2>Ignore the flashy new technology, stick with well-established basics</h2>
<p>This is where most developers run into trouble. Which browser should I code for? What technology should I use? Ooh, Cold Fusion looks cool, Javascript is cool, this new programming language is cool, .NET looks like it makes things easy, I can write nifty menus in Flash, etc etc etc&#8230;</p>
<p>There&#8217;s always something new and cool. The problem is that most of it doesn&#8217;t work well, or doesn&#8217;t run on a user&#8217;s browser, or breaks the rules above.</p>
<p>Stick with what works and you&#8217;ll write great sites that won&#8217;t give you headaches: UNIX, Apache, PHP, Python, Perl, MySQL, Postgres, Javascript, Java. For frameworks, Django, Ruby on Rails, and maybe Cake. Stick to those and you&#8217;ll be writing great sites that&#8217;ll actually work. These technologies also let you stick to the rules above easily (well, Cake might not). Try to use MVC design (look that up on Wikipedia). Avoid flash (use Javascript instead), Cold Fusion (breaks rules), and anything by Microsoft (breaks rules, isn&#8217;t reliable).</p>
<h2>A note about REST and sessions</h2>
<p>RESTful services don&#8217;t store &#8220;state&#8221; on the server. That means it doesn&#8217;t matter what browser I use, where I come from, or how long I wait between requests. On a RESTful site, I could start a flight search on one computer, bookmark my URI, go to another computer, click the bookmark, and keep going. Or, I could start a shopping cart order on one system, email my friend the URI, and have him place the order for me. Of course, this isn&#8217;t how sites work. One big issue is &#8220;authentication&#8221;. In a RESTful web service, there are a few extra components to that URI request: Authentication (who are you?) and Permission (are you allowed to perform this method on this resource?).</p>
<p>So for our shopping cart, my friend would first have to prove to the server who he is, and then he&#8217;d have to have Permission to see my cart. It&#8217;s the Authentication step that gets tricky. Ideally, the user would prove who he is (usually using a username and password) with every request. Browsers do support this, but it&#8217;s not very friendly. This is usually worked around by using session cookies, which is difficult, non-RESTful, and causes annoying problems like taking the user to a page they didn&#8217;t request after logging in, forgetting the information in a huge form they entered, etc.</p>
<p>Instead of using cookies, use HTTP Auth Digest.  If you want a pretty login form, you can create one with Javascript.  There&#8217;s a good <a href="http://www.peej.co.uk/articles/http-auth-with-html-forms.html">article with code samples by Paul James</a> that shows you how.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/10/23/how-to-develop-excellent-websites-and-web-applications-easily/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free drinks too expensive for Starbucks to handle</title>
		<link>http://www.grantgrueninger.com/2011/10/22/free-drinks-too-expensive-for-starbucks-to-handle/</link>
		<comments>http://www.grantgrueninger.com/2011/10/22/free-drinks-too-expensive-for-starbucks-to-handle/#comments</comments>
		<pubDate>Sat, 22 Oct 2011 08:59:13 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Humor]]></category>
		<category><![CDATA[Theories and Observations]]></category>
		<category><![CDATA[bad customer service]]></category>
		<category><![CDATA[bad marketing]]></category>
		<category><![CDATA[starbucks]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=376</guid>
		<description><![CDATA[I&#8217;m a Starbucks &#8220;Gold&#8221; customer. Evidently, I still don&#8217;t go frequently enough for them. In a move I can only assume was inspired by Netflix, they sent me a nice email. The whole letter&#8217;s below, but here&#8217;s the bullet points: Free drink on our birthday! Sent as a postcard that you have to bring in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a Starbucks &#8220;Gold&#8221; customer.  Evidently, I still don&#8217;t go frequently enough for them.</p>
<p>In a move I can only assume was inspired by Netflix, they sent me a nice email.  The whole letter&#8217;s below, but here&#8217;s the bullet points:</p>
<p>Free drink on our birthday!  Sent as a postcard that you have to bring in (inconvenient, but what they&#8217;ve always done).  The new part: You have a week to redeem it.  Like I even check my snail mail that frequently.</p>
<p>Free drink every 15 &#8220;stars&#8221; (visits) if you&#8217;re a Gold Card holder (see below for the complex rules that make that happen).  Again, sent as an inconvenient postcard instead of just being automatic like every other loyalty program.  Now you have 30 days to use that card, or it becomes trash.  Hopefully you don&#8217;t go into a Starbucks with it and get the &#8220;Sorry, this expired, look at the date. Feel stupid? No drink for you!&#8221; treatment.</p>
<p>Coffee Bean has better drinks anyway.  Think it&#8217;s time to start going there more.</p>
<p>I&#8217;m waiting for the next email, in which they&#8217;ll say they&#8217;re splitting their drinks and food into two separate stores, and renaming themselves &#8220;drinkster&#8221;.</p>
<p>Here&#8217;s their email (including the paragraph on how to keep your status, which rivals some airlines):</p>
<p>My Starbucks Rewards fans,</p>
<p>We&#8217;re fine-tuning a few program benefits and wanted to make sure you knew what was coming. There&#8217;s a bit more information here than usual, but when it comes to understanding your rewards, we figure more is more. </p>
<p>Starting November 1, 2011: </p>
<p>FREE DRINK ON YOUR BIRTHDAY<br />
Birthdays are special. And we&#8217;re still celebrating yours with a free drink on your birthday. Hooray! As long as you&#8217;re an active member (meaning you&#8217;ve used your Starbucks Card within the last 12 months), you&#8217;ll get a postcard for a free birthday drink. And about a week to use it, in case you need it to be a day-after-your-birthday drink. (Wink.) Check the &#8220;valid through&#8221; date and come on in for a treat. </p>
<p>FREE DRINK EVERY 15 STARS IN GOLD<br />
The &#8220;Sweet 15&#8243; free drink is alive and well. The only change here is that you&#8217;ll now have 30 days to bring in that postcard and enjoy a drink on the house. </p>
<p>KEEP YOUR STARS, KEEP YOUR STATUS<br />
If you&#8217;re a Green or Gold member, the date you achieved that level is your anniversary date. To keep your Stars and your status, you just need to earn 5 Stars for Green or 30 Stars for Gold over the next 12 months (by your anniversary date next year). If you don&#8217;t make it, your Stars will expire and you&#8217;ll drop down a level. But we&#8217;ll help-we&#8217;ll send you email reminders of your anniversary date and encouragement to earn those additional Stars to keep the benefits you love. (Be sure to opt in to email.) </p>
<p>TUNE UP!<br />
Now might be a good time to visit your Account Profile, note your anniversary date, track your Stars, reload a card and opt in to receive emails for special offers and announcements. </p>
<p>Thanks for reading. See the full details here. </p>
<p>Wishing you a year full of Stars,<br />
My Starbucks Rewards </p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/10/22/free-drinks-too-expensive-for-starbucks-to-handle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dear Netflix, have you heard of Amazon Prime?</title>
		<link>http://www.grantgrueninger.com/2011/08/03/dear-netflix-have-you-heard-of-amazon-prime/</link>
		<comments>http://www.grantgrueninger.com/2011/08/03/dear-netflix-have-you-heard-of-amazon-prime/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 07:11:42 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[movies]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[Streaming]]></category>
		<category><![CDATA[Videos]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=374</guid>
		<description><![CDATA[- Online streaming - Supports Linux - $79/yr (cheaper than Netflix streaming). Just sayin&#8217;.]]></description>
			<content:encoded><![CDATA[<p>- Online streaming<br />
- Supports Linux<br />
- $79/yr (cheaper than Netflix streaming).</p>
<p>Just sayin&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/08/03/dear-netflix-have-you-heard-of-amazon-prime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Netflix: Hey we&#8217;re going to raise your rates 50%, just FYI.</title>
		<link>http://www.grantgrueninger.com/2011/07/13/netflix-hey-were-going-to-raise-your-rates-50-just-fyi/</link>
		<comments>http://www.grantgrueninger.com/2011/07/13/netflix-hey-were-going-to-raise-your-rates-50-just-fyi/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 04:47:11 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Theories and Observations]]></category>
		<category><![CDATA[Hulu]]></category>
		<category><![CDATA[movies]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[TV]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=372</guid>
		<description><![CDATA[I just got an email from Netflix: Dear Grant, We are separating unlimited DVDs by mail and unlimited streaming into two separate plans to better reflect the costs of each. Now our members have a choice: a streaming only plan, a DVD only plan, or both. Your current $11.99 a month membership for unlimited streaming [...]]]></description>
			<content:encoded><![CDATA[<p>I just got an email from Netflix:</p>
<blockquote><p>Dear Grant,</p>
<p>We are separating unlimited DVDs by mail and unlimited streaming into two separate plans to better reflect the costs of each. Now our members have a choice: a streaming only plan, a DVD only plan, or both.</p>
<p>Your current $11.99 a month membership for unlimited streaming and unlimited DVDs (including Blu-ray access) will be split into 2 distinct plans:</p>
<p>   Plan 1: Unlimited Streaming (no DVDs) for $7.99 a month<br />
   Plan 2: Unlimited DVDs (including Blu-ray), 1 out at-a-time (no streaming)<br />
              for $9.99 a month</p>
<p>Your price for getting both of these plans will be $17.98 a month ($7.99 + $9.99). You don&#8217;t need to do anything to continue your memberships for both unlimited streaming and unlimited DVDs.
</p></blockquote>
<p>Translated, that means &#8220;we&#8217;re hiking up your rates by 50%&#8221;.  Now that&#8217;s enough to drive customers away in itself, but Netflix decided instead to give us the option of cancelling part or all of our service.  Evidently that&#8217;ll increase their profits.</p>
<p>Evidently Netflix doesn&#8217;t realize a couple things that their customers know:</p>
<ol>
<li>Netflix has competitors, especially for their streaming service.</li>
<li>Netflix&#8217;s &#8220;Watch Instantly&#8221; selection is really crappy.</li>
</ol>
<p>I&#8217;m not sure $9.99/mo for just the delivery service is enough, but it might be.  I&#8217;m sure not paying $7.99/month for the steaming pile of streaming they offer.  I replied suggesting they try this again after adding some real content for streaming.</p>
<p>I won&#8217;t do HULU+ until they stop showing ads during my paid subscription (which doesn&#8217;t sound likely anytime soon), so I guess it&#8217;s time to look into other services again, or just watch less TV&#8230;  Any recommendations?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/07/13/netflix-hey-were-going-to-raise-your-rates-50-just-fyi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Evidence Intuit owns Mint.com (or Min.com&#8230;)</title>
		<link>http://www.grantgrueninger.com/2011/02/18/evidence-intuit-owns-mint-com-or-min-com/</link>
		<comments>http://www.grantgrueninger.com/2011/02/18/evidence-intuit-owns-mint-com-or-min-com/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 08:28:17 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[bad programming]]></category>
		<category><![CDATA[indian programmers]]></category>
		<category><![CDATA[intuit]]></category>
		<category><![CDATA[mint.com]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/2011/02/18/evidence-intuit-owns-mint-com-or-min-com/</guid>
		<description><![CDATA[Sadly, it looks like Intuit&#8217;s programmers have infected the once good Mint.com]]></description>
			<content:encoded><![CDATA[<p>Sadly, it looks like Intuit&#8217;s programmers have infected the once good Mint.com<br/><br/><a href="http://www.grantgrueninger.com/wp-content/uploads/2011/02/20110218-123045.jpg"><img src="http://www.grantgrueninger.com/wp-content/uploads/2011/02/20110218-123045.jpg" alt="" class="alignnone size-full" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2011/02/18/evidence-intuit-owns-mint-com-or-min-com/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>FlightPrep lawsuit against Runwayfinder (or &#8220;why I&#8217;m glad I use ForeFlight&#8221;)</title>
		<link>http://www.grantgrueninger.com/2010/12/22/flightprep-lawsuit-against-runwayfinder-or-why-im-glad-i-use-foreflight/</link>
		<comments>http://www.grantgrueninger.com/2010/12/22/flightprep-lawsuit-against-runwayfinder-or-why-im-glad-i-use-foreflight/#comments</comments>
		<pubDate>Thu, 23 Dec 2010 03:11:30 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Flying]]></category>
		<category><![CDATA[Theories and Observations]]></category>
		<category><![CDATA[flightprep]]></category>
		<category><![CDATA[flying]]></category>
		<category><![CDATA[foreflight]]></category>
		<category><![CDATA[lawsuit]]></category>
		<category><![CDATA[pilot]]></category>
		<category><![CDATA[runwayfinder]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=348</guid>
		<description><![CDATA[When I started this post, I was afraid I used some FlightPrep software. I was ready to delete it. Then I realized I&#8217;d considered their products, but found them inferior to other products out there. I felt they were an outdated company trying to catch up (and failing). FlightPrep is posting on their site logical-sounding [...]]]></description>
			<content:encoded><![CDATA[<p>When I started this post, I was afraid I used some FlightPrep software.  I was ready to delete it.  Then I realized I&#8217;d considered their products, but found them inferior to other products out there.  I felt they were an outdated company trying to catch up (and failing).</p>
<p>FlightPrep is posting <a href="http://www.flightprep.com/">on their site</a> logical-sounding claims regarding a patent they filed and how they&#8217;ve tried to contact the maintainer of runwayfinder.com, grant him a free license during negotiation, etc.<br />
<div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
Here&#8217;s what it really comes down to:</p>
<ol>
<li>Lawyers are expensive and time-consuming.  This is 1 person with a full-time job against a company with 4 full-time employees, and evidently enough capital to pay lawyers.</li>
<li>Sure, it&#8217;s good business practice to sue/buy the competition.  Microsoft is famous for it.  Microsoft is also hated for it.  I won&#8217;t tolerate that tactic from FlightPrep. Delete.</li>
<li>FlightPrep claims that RunwayFinder is infringing on their patent and wants RunwayFinder to pay them to keep running.  I run a couple of web sites &#8211; it&#8217;s not worth my time to deal with legal issues.  I&#8217;m sure Dave doesn&#8217;t have time either (as he <a href="http://blog.runwayfinder.com/2010/12/09/runwayfinder-going-offline/">says</a>).  The mere claim of infringement overruns his resources.</li>
</ol>
<p>I&#8217;m a software developer by profession, and software patent law needs some serious change.  The problem is that people can patent simple ideas that anyone can come up with.  Take Amazon&#8217;s &#8220;one click&#8221; for example.  Store address and credit card information so that the user can use it later &#8211; patent!  Evidently pointing out airports on a chart and letting you route (an existing process taught to every pilot) is patentable if you write a program to do it (by any means).<br />
<div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
So yes, FlightPrep, you <em>might</em> be &#8220;playing by the rules&#8221;, just like the smart bullies did in elementary school.  It doesn&#8217;t mean we want to be your friends any more.</p>
<p>Fire the person who thought that going after one of the most-used pilot tools on the web would be beneficial to anyone (including FlightPrep) and, after enough time to regain your reputation, I&#8217;ll <i>consider</i> using your software. If you&#8217;re still around.</p>
<p>(By the way, I prefer ForeFlight&#8217;s software to FlightPrep&#8217;s.  I assume they&#8217;ll be sued next).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2010/12/22/flightprep-lawsuit-against-runwayfinder-or-why-im-glad-i-use-foreflight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web 2.0 Business Plan</title>
		<link>http://www.grantgrueninger.com/2010/12/21/web-2-0-business-plan/</link>
		<comments>http://www.grantgrueninger.com/2010/12/21/web-2-0-business-plan/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 04:43:07 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Humor]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=343</guid>
		<description><![CDATA[Mission Utilize cross-media e-services to grow revolutionary communities. Point-by-point Plan incubate open-source interfaces target synergistic models matrix front-end schemas morph bricks-and-clicks web services embrace one-to-one niches (profit!) Plan developed with the aid of this tool. If I get a bunch of Google hits from BS keywords, I&#8217;m going to laugh.]]></description>
			<content:encoded><![CDATA[<p><strong>Mission</strong><br />
Utilize cross-media e-services to grow revolutionary communities.<br />
<div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Point-by-point Plan</strong></p>
<ul>
<li>incubate open-source interfaces</li>
<li>target synergistic models</li>
<li>matrix front-end schemas</li>
<li>morph bricks-and-clicks web services</li>
<li>embrace one-to-one niches</li>
<li>(profit!)</li>
</ul>
<p>Plan developed with the aid of <a href="http://www.dack.com/web/bullshit.html">this tool</a>.</p>
<p>If I get a bunch of Google hits from BS keywords, I&#8217;m going to laugh.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2010/12/21/web-2-0-business-plan/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to make Public Transportation work in Los Angeles</title>
		<link>http://www.grantgrueninger.com/2010/12/05/how-to-make-public-transportation-work-in-los-angeles/</link>
		<comments>http://www.grantgrueninger.com/2010/12/05/how-to-make-public-transportation-work-in-los-angeles/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 09:23:21 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[How To - Advice]]></category>
		<category><![CDATA[Theories and Observations]]></category>
		<category><![CDATA[la metro]]></category>
		<category><![CDATA[public transportation]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=339</guid>
		<description><![CDATA[On August 29, 2010, Santa Monica&#8217;s Big Blue Bus took a step backward in fare handling. Ironically, to announce the change, they ran ads implying that you wouldn&#8217;t need to use money on the bus any more. In reality, they were replacing the Little Blue Card (which allowed you to load cash onto the card [...]]]></description>
			<content:encoded><![CDATA[<p><div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div> On August 29, 2010, Santa Monica&#8217;s Big Blue Bus took a step backward in fare handling.  Ironically, to announce the change, they ran ads implying that you wouldn&#8217;t need to use money on the bus any more.  In reality, they were replacing the Little Blue Card (which allowed you to load cash onto the card and pay for your bus fare, transfers, express bus fees, etc) with various trip-based or multi-day-based passes (which don&#8217;t allow you to pay for transfers or express bus fees).</p>
<p>So, Dear Los Angeles Public Transportation providers, here&#8217;s why spewing advertising billboards about saving gas all over the city isn&#8217;t getting people on your busses and trains:</p>
<ul>
<li><b>Make paying simple</b><br />
Seriously, I&#8217;ve lost count of the times I&#8217;ve driven to work instead of figuring out if I have exactly $1.50 for the trip there and $1.85 for the trip back (and calculating that cost in the first place). Heaven forbid I get on the wrong version of the bus I need to get back (see a lower point) and need to pay an extra amount. Take a hint from Hong Kong and London:</p>
<ul>
<li>Make it easy to load <b><i>cash</i></b> on the TAP card (hint: online, in EVERY Metro station, and on EVERY bus)</li>
<li>Make the fares simple!  Seriously, it&#8217;s one rate if you&#8217;re staying local, another if you&#8217;re going into a different &#8220;zone&#8221;, another if you&#8217;re a student, another if you&#8217;re a senior, another if you&#8217;re taking more than one bus. GEEZ! It&#8217;s easier to buy a car than take the damn bus once! Remember the old KISS rule &#8211; Keep It Simple, Stupid</li>
</ul>
</li>
<li><b>Make the busses and trains run more frequently</b><br />
Some are fine, some aren&#8217;t. If a line runs less frequently than every 20 minutes, it&#8217;s basically useless. 5-10 minutes, and you&#8217;re talking about replacing my car. 10-20 minutes, and I&#8217;ll consider it if I don&#8217;t want to drive. 20 minutes, and I&#8217;m just gonna be spending my life at bus stops &#8211; no longer worth it.</li>
<li><b>Make the busses run reliably</b><br />
This one&#8217;s huge.  I was all set to bus to work and cancel my parking until the day I got left on the street for over 40 minutes one cold night because a bus (scheduled every 20 minutes&#8230;) just didn&#8217;t show. The busses sole purpose is to get me somewhere &#8211; if it fails that purpose, I have to find something else to get me there. LA Metro repeatedly fails that purpose.</li>
<li><b>Make all transit lines use the TAP card</b><br />
&#8220;Can&#8217;t we all just get along?&#8221; Really, everyone&#8217;s got to use the same payment system to make the system usable.  LA&#8217;s too big to have to guess at the three systems you might need to use to get somewhere more than a couple miles away (or even less than a couple miles away). The EZ transit pass is ok, but is only affordable if you&#8217;re going to <i>only</i> use public transportation; it loses the occasional rider.</li>
<li><b>Make the bus/train lines simple</b><br />
Sure, it&#8217;s a big city, and the system&#8217;s going to be a bit complicated. But at least try for simplicity: Let&#8217;s take the 108 Metro bus for example. One out of every three trips, the route extends into Marina Del Rey. Same bus number, different destination. Really?  Who thought that would be a good idea? So if you&#8217;re waiting for the 108 and need to go to Marina Del Rey, and don&#8217;t notice that the head sign says &#8220;Fox Hills Mall&#8221; instead of &#8220;Marina Del Rey&#8221;, you just got stuck at the mall, and have to hope you have the extra buck fifty or whatever it is to get the rest of the way (whenever the right <i>version</i> of the 108 comes). Again, the bus just failed to get me where I need to go &#8211; time for another solution.</li>
</ul>
<p><div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>Yeah, I know &#8220;running the bus every 10 minutes is too expensive&#8221;, and &#8220;there aren&#8217;t enough people on the bus to warrant it running more than every 45 minutes through this one section, but there is through this other section, and we don&#8217;t really want to have it be a transfer because the people coming in from Marina Del Rey would have to transfer blah blah blah&#8221;.  And so, we widen the 405, because if you take the 761 into the valley, good luck figuring out how to get back (hint: it&#8217;s not on the 761). Make it easier to pay, faster to get places, and easier to comprehend, and maybe LA can join the list of world cities in which people who <i>can</i> afford a car use public transportation to get around anyway.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2010/12/05/how-to-make-public-transportation-work-in-los-angeles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why I like throwing exceptions</title>
		<link>http://www.grantgrueninger.com/2010/10/29/why-i-like-throwing-exceptions/</link>
		<comments>http://www.grantgrueninger.com/2010/10/29/why-i-like-throwing-exceptions/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 03:26:33 +0000</pubDate>
		<dc:creator>grant</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Error.pm]]></category>
		<category><![CDATA[exceptions]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.grantgrueninger.com/?p=335</guid>
		<description><![CDATA[I program a lot in Perl. I used to be a big fan of &#8220;modules should never die&#8221;. Now I&#8217;m the opposite. I want a method to die any time it can&#8217;t succeed in doing what it&#8217;s been asked to do. Here&#8217;s why: Without exceptions: $module->do_something( %args ) or die "I couldn't do something"; $module->do_something_else( [...]]]></description>
			<content:encoded><![CDATA[<p>I program a lot in Perl.  I used to be a big fan of &#8220;modules should never die&#8221;.  Now I&#8217;m the opposite.  I want a method to die any time it can&#8217;t succeed in doing what it&#8217;s been asked to do.</p>
<p>Here&#8217;s why:</p>
<p><div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p>Without exceptions:<br />
<code><br />
$module->do_something( %args ) or die "I couldn't do something";<br />
$module->do_something_else( %args ) or die "I couldn't do something else";<br />
[...]<br />
</code></p>
<p>With exceptions:<br />
<code><br />
$module->do_something( %args );<br />
$module->do_something_else( %args );<br />
</code></p>
<p>Now imagine that with hundreds of lines of code.  I love having my script or module simply contain a list of commands &#8211; Do this then this then this &#8211; without having to babysit every single line to make sure everything went ok.</p>
<p>It also lets you handle things on a more transactional basis.  Say you want to connect to a database and update some data.  With exceptions you can do this:</p>
<p>use Error.pm qw(:try);</p>
<p>my $dbh = DBI->connect($data_source, $username, $auth, { RaiseError => 1, AutoCommit => 0 } );<br />
# RaiseError turned on exceptions. We&#8217;re free to roam.</p>
<p>try {<br />
    $dbh->do(&#8220;update mytable set myfield=&#8217;gobble&#8217; where myotherfield=&#8217;turkey&#8217;&#8221;);<br />
    $dbh->do(&#8220;update anothertable set anotherfield=&#8217;somevalue&#8217; where yetanother=&#8217;anothervalue&#8217;&#8221;);<br />
    $dbh->commit;<br />
} otherwise {<br />
    $dbh->revert;<br />
};</p>
<p>(Don&#8217;t quote me on syntax here &#8211; this is very perl-like psuedocode. <img src='http://www.grantgrueninger.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )<br />
<div style='float: left; margin: 5px;'><script type="text/javascript"><!--
google_ad_client = "pub-4422752460275104";
/* 250x250, created 1/16/10 */
google_ad_slot = "5256966229";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
I also like building exceptions into my own modules using Error.pm.  This lets me throw specific types of exceptions.  I usually end up with an exception type for data errors, IO errors, and Database errors, just in case I want to catch those.  For example, I may wait and retry IO and Database errors, but a Data error (bad user data) I&#8217;ll let go uncaught up to the UI level so that the UI can complain to the user.</p>
<p>That brings me to the other reason I like exceptions, and the reason I started using them in the first place.  Say you&#8217;re building a complex module, or set of modules, with many layers of subroutine calls.  If your error-trapping mechanism is the ever-popular &#8220;return undef&#8221;, you now have, say, 5 layers of subroutine/method calls to check and pass undef up.  You forget an &#8220;or return undef&#8221; at any level, and you let an error slip by.  Usually something&#8217;ll break later on in your program as a result, and you&#8217;ll have a hard-to-track bug.  I prefer to throw an exception and include a stack trace (see the Error.pm docs for sample code).  Then you can catch the exception at any point, and if you don&#8217;t, you still have a stack trace that shows exactly where the error occurred.</p>
<p>&#8220;But I don&#8217;t want my script killed by a module I&#8217;m using, I want to decide what to do if there&#8217;s a problem&#8221;.  I used to think this.  But the fact is, 99.9% of the time you&#8217;re going to do one of two things:</p>
<ol>
<li>$module->do_something() or die &#8220;Couldn&#8217;t do something: &#8221; . $module->errstr;</li>
<li>$module->do_something();</li>
</ol>
<p>In the first case, if do_something threw an exception, it&#8217;d save you the babysitting code. In the second case, if &#8220;do_something&#8221; didn&#8217;t do what it was supposed to, chances are your program can&#8217;t really continue anyway, right?  And if it can, maybe you don&#8217;t need to &#8220;do_something()&#8221; anyway.  And for that .1% of the time you want to ignore errors, you can &#8220;eval { $module->do_something(); }&#8221;.</p>
<p>So there.  I like throwing exceptions.  Maybe you will too.</p>
<p>Further reading: &#8220;man Error&#8221;, <a href="http://www.perl.com/pub/2002/11/14/exception.html">http://www.perl.com/pub/2002/11/14/exception.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.grantgrueninger.com/2010/10/29/why-i-like-throwing-exceptions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

