<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-281503025845848341</atom:id><lastBuildDate>Sun, 20 Jun 2010 12:30:01 +0000</lastBuildDate><title>Brian.OnCode()</title><description>Thoughts on software development from a work-a-day software engineer</description><link>http://www.brian-driscoll.com/</link><managingEditor>noreply@blogger.com (Driscoll Web Development)</managingEditor><generator>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/brian-on-code" /><feedburner:info uri="brian-on-code" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>brian-on-code</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-1387605850353244904</guid><pubDate>Thu, 18 Feb 2010 01:22:00 +0000</pubDate><atom:updated>2010-02-17T20:24:05.334-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">9-to-5</category><category domain="http://www.blogger.com/atom/ns#">productivity</category><title>How To Be Productive In An Open Office</title><description>I work in an open office environment, which just means that there are many people and few walls. As a result, it's sometimes easy to become distracted or be interrupted by co-workers and often difficult to get as much work done as I'd planned.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;&lt;/div&gt;I've been trying to come up with some ways to make it easier to get work done at work rather than doing it when I come home at night, and here are some of the ideas I've generated. I can't promise they'll work for anyone else, but they seem to be working well for me so far.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;1. Take Time to Make Time&lt;/h2&gt;When planning your day or week, set aside a block of time that you will dedicate to getting your work done without any interruptions. Setting this time aside now will help you later... like when you get that meeting planner at 10:00 for the meeting at 10:30. If that falls during your productive time, you can politely decline the request or suggest an alternative time.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;2. Let Others Know You're Unavailable&lt;/h2&gt;Following Step&amp;nbsp;3&amp;nbsp;below will help to keep your co-workers from interrupting your productive time, but in an open office it's difficult to avoid some interruptions from people stopping at your desk for one reason or another. Before you begin working send out an email to your co-workers requesting that they not interrupt you during the time you've set aside for yourself. If you need to, tape a sign to the outside of your cubicle with the same request.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;3. Disconnect and Shutdown&lt;/h2&gt;If the work you need to do doesn't require a computer, shut it down. No, really, I mean it. Turn the computer off. If you need your computer to do your work, here's what to do:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Sign out of all your IM/Twitter/etc. apps and close all&amp;nbsp;browser windows that don't pertain to the task at hand (Looking at you, Mr. MySpace Creeper).&lt;/li&gt;
&lt;li&gt;Close your&amp;nbsp;email application. Really, it's okay, you won't miss anything more important than your third cousin's self-loathing status updates.&lt;/li&gt;
&lt;li&gt;Turn off your cell phone. See above if you're worried about missing something important.&lt;/li&gt;
&lt;li&gt;Put your office phone in Do-Not-Disturb mode.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h2&gt;4a. Relocate If You Can&lt;/h2&gt;Sometimes we all need a little peace and quiet, and that can be hard to come by in an open office. If you can take your work elsewhere and there is a quiet area available to you (a meeting room or vacant office, perhaps?), then head over that way to do your work. If you're lucky enough to get a room with a door, close the door.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;4b. Build a Cocoon&lt;/h2&gt;If you just can't get away, do whatever you can to block out extraneous stimuli that will distract you. I find generally that putting some headphones on and shuffling through my classical or jazz playlist works well. You'll have to find what works best for you.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;5. Do Your Work (!)&lt;/h2&gt;It's all too easy to distract ourselves sometimes. In order to be productive you need to have the focus and discipline necessary to do the work that's ahead of you and nothing else.&lt;br /&gt;
&lt;br /&gt;
Hopefully these tips will help others to be more productive in an open office like mine, or just be more productive in general. If you have other tips to share about how to be more productive at work, please feel free to leave them in the comments section below.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-1387605850353244904?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=VMgQizoB0dM:zvxozjoU3Bc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=VMgQizoB0dM:zvxozjoU3Bc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=VMgQizoB0dM:zvxozjoU3Bc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=VMgQizoB0dM:zvxozjoU3Bc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=VMgQizoB0dM:zvxozjoU3Bc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=VMgQizoB0dM:zvxozjoU3Bc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=VMgQizoB0dM:zvxozjoU3Bc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=VMgQizoB0dM:zvxozjoU3Bc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/VMgQizoB0dM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/VMgQizoB0dM/how-to-be-productive-in-open-office.html</link><author>noreply@blogger.com (Driscoll Web Development)</author><thr:total>1</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2010/02/how-to-be-productive-in-open-office.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-8158976920133021225</guid><pubDate>Mon, 21 Dec 2009 18:41:00 +0000</pubDate><atom:updated>2009-12-21T13:41:22.908-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">mobile development</category><category domain="http://www.blogger.com/atom/ns#">iPhone</category><category domain="http://www.blogger.com/atom/ns#">Adobe</category><category domain="http://www.blogger.com/atom/ns#">Flash</category><category domain="http://www.blogger.com/atom/ns#">Apple</category><title>The Apple of My Eye</title><description>This weekend I joined the great unwashed mobile masses by purchasing an&lt;a href="http://www.apple.com/iphone/iphone-3gs/"&gt; iPhone 3GS&lt;/a&gt;. Okay, I can't lie: I was really excited to get the phone; I've been wanting an iPhone 3GS since it came out this summer and have felt like the only kid on the block without one, so I finally feel like part of the in-crowd.&lt;br /&gt;
&lt;br /&gt;
Of course, the first thing I did once I got it home was start downloading apps: Facebook, Rotten Tomatoes, etc...&lt;br /&gt;
&lt;br /&gt;
...which got me to thinking about the &lt;a href="http://developer.apple.com/iphone/program/"&gt;IPhone Developer Program&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A Standard account in the Developer Program is $99, which gives you access to app development tools, testing tools, and the App Store - where you can sell your app or give it away for free.&lt;br /&gt;
&lt;br /&gt;
Sounds great, right? One catch.&lt;br /&gt;
&lt;br /&gt;
As of right now, only Mac users can use the iPhone SDK and related development tools. Well, I'm not a Mac user, nor do I intend to be anytime soon. So, what's out there for me?&lt;br /&gt;
&lt;br /&gt;
Nothing. Yet.&lt;br /&gt;
&lt;br /&gt;
However, Adobe announced at the MAX 2009 conference that Flash CS5 will contain a Packager for iPhone that will allow Flash developers to target their apps to the iPhone platform. According to Adobe's announcement, the Packager will compile Flash movies down to native iPhone code, and developers on any of Flash's supported authoring platforms will be able to distribute their apps in the Apple App Store (after they've joined the iPhone Developer Program, of course).&lt;br /&gt;
&lt;br /&gt;
So when do we get to see Flash CS5? Well, unfortunately &lt;a href="http://blogs.adobe.com/flashplatform/2009/12/there_will_not_be_a_beta_for_f.html"&gt;there will be no public beta of Flash CS5&lt;/a&gt;, so we'll have to wait until the retail release sometime in 2010.&lt;br /&gt;
&lt;br /&gt;
Until then, I'll be waiting...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-8158976920133021225?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o7DQusOhyTQ:igHal-dN7PE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o7DQusOhyTQ:igHal-dN7PE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o7DQusOhyTQ:igHal-dN7PE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o7DQusOhyTQ:igHal-dN7PE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o7DQusOhyTQ:igHal-dN7PE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o7DQusOhyTQ:igHal-dN7PE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o7DQusOhyTQ:igHal-dN7PE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o7DQusOhyTQ:igHal-dN7PE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/o7DQusOhyTQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/o7DQusOhyTQ/apple-of-my-eye.html</link><author>noreply@blogger.com (Brian Driscoll)</author><thr:total>0</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/apple-of-my-eye.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-2323015598901208568</guid><pubDate>Thu, 10 Dec 2009 18:15:00 +0000</pubDate><atom:updated>2009-12-10T13:15:33.437-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">IT management</category><category domain="http://www.blogger.com/atom/ns#">opinion</category><category domain="http://www.blogger.com/atom/ns#">business of software development</category><title>The Patent Office Called... The Wheel's Been Invented Already</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_3Jt5kuKQMcQ/Sx79ybf9U3I/AAAAAAAAAAw/tfVTSj9h5BA/s1600-h/bebop-radiator.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_3Jt5kuKQMcQ/Sx79ybf9U3I/AAAAAAAAAAw/tfVTSj9h5BA/s320/bebop-radiator.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;blockquote style="color: #7f6000; font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;&lt;b&gt;&lt;i&gt;&lt;span style="font-size: large;"&gt;When it comes to developing software of all kinds, I feel like sometimes - more often than not maybe - we'll never learn.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
I hear from purist software knobs everyday who tell me, maybe in not so many words, that when it comes to software components, in order to do something right you have to do it yourself. That is to say, even if there are perfectly good components already out there ready to be bought and implemented, it's better to just build it yourself.&lt;br /&gt;
&lt;br /&gt;
To which I ask:&lt;br /&gt;
&lt;br /&gt;
If you need an alternator for your car, do you go into your garage and construct one for yourself, or do you simply go to the auto supply store and buy one?&lt;br /&gt;
&lt;br /&gt;
Of course, you buy an alternator for your car. But why? Well, you do it for several reasons:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;You do not know, nor do you care to know, how to build an alternator.&lt;/li&gt;
&lt;li&gt;You do not know, nor do you care to know, how an alternator works. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;It requires less time and effort (remember time*effort=money) to buy an alternator than it does to build one.&lt;/li&gt;
&lt;li&gt;Alternators are a commodity in the auto supply market, so they're fairly cheap.&lt;/li&gt;
&lt;/ol&gt;I could go on with the list, but I think you get my point.&lt;br /&gt;
&lt;br /&gt;
Many of the aforementioned software knobs would agree with me about the alternator, and compare it to a text input box, a radio button, a check box, etc. And, of course, in these instances their comparisons are entirely valid. However, my peers will often throw up their hands when I say that more complex components, like API wrappers for well-known web services such as Amazon S3, also belong in software's alternator bin.&lt;br /&gt;
&lt;br /&gt;
The fact is that there are really very few reasons to build a new software component these days, and whether you're a software developer, a project manager, or an IT manager, you'll want to pay close attention to this list.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-large;"&gt;&lt;b&gt;Business Justifications for Building, Rather than Buying, Software Components:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;There does not exist a stable and mature component that meets the functional and/or technical requirements of your project (not likely, but possible).&lt;/li&gt;
&lt;li&gt;Licensing agreements prevent you from using a purchased component in a commercial application (also unlikely, but possible).&lt;/li&gt;
&lt;li&gt;Building the component adds greater business value than buying the component (ie: your component will have features that currently available ones do not have, thereby giving your company competitive advantage).&lt;/li&gt;
&lt;li&gt;The cost (economic and opportunity) of building the component is less than the cost of buying the component (&lt;b&gt;&lt;i style="text-decoration: underline;"&gt;very&lt;/i&gt;&amp;nbsp;unlikely&lt;/b&gt;).&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;These are not the only 4 reasons, but they're probably the 4 biggest reasons. Regardless, unless the component you're planning to build can be justified by one of the four reasons above, then you probably should not be building it.&lt;br /&gt;
&lt;br /&gt;
That said, I'm open to counter-arguments, further suggestions, questions, etc. Feel free to drop a line in the comments section below, or email me at brian (at) brian-driscoll (dot) com.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Image above courtesy of &lt;a href="http://thereifixedit.com/"&gt;http://thereifixedit.com&lt;/a&gt;. Used without permission.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-2323015598901208568?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=QHznNiCP3bM:ed8WMaAot_Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=QHznNiCP3bM:ed8WMaAot_Y:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=QHznNiCP3bM:ed8WMaAot_Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=QHznNiCP3bM:ed8WMaAot_Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=QHznNiCP3bM:ed8WMaAot_Y:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=QHznNiCP3bM:ed8WMaAot_Y:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=QHznNiCP3bM:ed8WMaAot_Y:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=QHznNiCP3bM:ed8WMaAot_Y:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/QHznNiCP3bM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/QHznNiCP3bM/patent-office-called-wheels-been.html</link><author>noreply@blogger.com (Brian Driscoll)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_3Jt5kuKQMcQ/Sx79ybf9U3I/AAAAAAAAAAw/tfVTSj9h5BA/s72-c/bebop-radiator.jpg" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/patent-office-called-wheels-been.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-1489042901694920480</guid><pubDate>Mon, 07 Dec 2009 18:44:00 +0000</pubDate><atom:updated>2009-12-07T13:44:03.048-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">PHP</category><category domain="http://www.blogger.com/atom/ns#">LAMP</category><category domain="http://www.blogger.com/atom/ns#">tutorials</category><category domain="http://www.blogger.com/atom/ns#">REST</category><category domain="http://www.blogger.com/atom/ns#">object-oriented programming</category><category domain="http://www.blogger.com/atom/ns#">web services</category><title>Building a REST (or REST-like) LAMP Web Service - Part 1</title><description>Last week a colleague asked me about web services. Specifically, he wanted to know what a web service was, and why one would deploy a web service. I answered his questions to the best of my abilities; I told him that a web service is an API that allows two applications to share data in an agreed upon format, such as XML or JSON. As for the why part, I told him that web services are deployed in situations where two or more decoupled applications want (or need) to share information.&lt;br /&gt;
&lt;br /&gt;
Since he'd taken such a keen interest in web services, and since I know he's familiar with web services, I figured I'd post a brief tutorial on how to create and deploy a REST (or REST-like) web service on a LAMP platform. For the purpose of this tutorial, the P in LAMP will be PHP. I will assume that you have a strong working knowledge of XML and PHP.&lt;br /&gt;
&lt;br /&gt;
Before we get started, it's worth mentioning that there is no single way to set up and run a REST web service on the LAMP platform, so in reality the method I'm going to show you today is just one way of doing it. There are plenty of other equally valid ways of setting up and running web services on the LAMP platform.&lt;br /&gt;
&lt;br /&gt;
We will need at least 3 files to get started:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;.htaccess &lt;/b&gt;- This file will redirect URIs to our web service endpoint.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;index.php &lt;/b&gt;- This file will be our web service endpoint. It will parse URIs and pass requests to an instance of our web service.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;webservice.php&lt;/b&gt;&amp;nbsp;- This class will be the workhorse of our application - it will handle data retrieval, formatting, etc.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;h2&gt;Designing the Web Service&lt;/h2&gt;&lt;div&gt;I'm not going to get too deep into REST theory and practice here. If you want a more in-depth (but accessible) treatment of REST principles, I recommend checking out Ryan Tomayko's excellent article, &lt;a href="http://tomayko.com/writings/rest-to-my-wife"&gt;"How I Explained REST to My Wife."&lt;/a&gt;&amp;nbsp;The basic gist of RESTful web services is that they use a combination of URIs and request methods (GET, POST, PUT, DELETE) to execute a function and return a response. For this tutorial, we're going to create a web service that stores and retrieves information about a set of books.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;When designing a RESTful web service one needs to consider both the URI scheme that will be used, as well as the data scheme that will be used. Let's start by figuring out our data schemes. For simplicity's sake, let's say that our web service will provide information about &lt;b&gt;books &lt;/b&gt;and their &lt;b&gt;authors&lt;/b&gt;.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;For books, we want to store and retrieve the following information:&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Book ID&lt;/li&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Author's Name (in Last, First format)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;For authors, we want to store and retrieve the following information:&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Author ID&lt;/li&gt;
&lt;li&gt;Last Name&lt;/li&gt;
&lt;li&gt;First Name&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Obviously we could have a lot more information on both books and authors, but for this example what we have now will suffice. So, now, let's take a look at what we want our XML entities for both book and author to look like:&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;book&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;id&amp;gt;12345&amp;lt;/id&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;bookTitle&amp;gt;Learning XML, Second Edition&amp;lt;/bookTitle&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;author&amp;gt;Ray, Erik&amp;lt;/author&amp;gt;&lt;br /&gt;
&amp;lt;/book&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;author&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;id&amp;gt;321&amp;lt;/id&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;lastName&amp;gt;Ray&amp;lt;/lastName&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;firstName&amp;gt;Erik&amp;lt;/firstName&amp;gt;&lt;br /&gt;
&amp;lt;/author&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;If we have multiple books or authors, we'll just wrap them in plural tags, like this:&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;books&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;nbsp;&amp;nbsp;&amp;lt;book&amp;gt;...&amp;lt;/book&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;nbsp;&amp;nbsp;&amp;lt;book&amp;gt;...&amp;lt;/book&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;/books&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;authors&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;nbsp;&amp;nbsp;&amp;lt;author&amp;gt;...&amp;lt;/author&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;nbsp;&amp;nbsp;&amp;lt;author&amp;gt;...&amp;lt;/author&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;&amp;lt;/authors&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;Now that we've figured out our data structures, we need to think about our URI schemes. Remember that we need to consider both the URI and the request method...&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;style&gt;
table { border: 1px solid black; }
td { border: 1px solid black; }
th { font-weight: bold; text-align: left; }
&lt;/style&gt;&lt;br /&gt;
&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;URI&lt;br /&gt;
&lt;/th&gt; &lt;th&gt;Method&lt;br /&gt;
&lt;/th&gt; &lt;th&gt;Description&lt;br /&gt;
&lt;/th&gt; &lt;/tr&gt;
&lt;/thead&gt; &lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;/books/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;GET&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Gets a list of all books&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/book/{id}/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;GET&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Gets the book specified by {id}&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/book/new/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;POST&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Creates a new book&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/authors/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;GET&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Gets a list of all authors&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/author/{id}/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;GET&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Gets the author referenced by {id}&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/author/new/&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;POST&lt;br /&gt;
&lt;/td&gt;&lt;td&gt;Creates a new author.&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt; &lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;We have both our data structures and our URIs defined; now it's time to take a look at our web service implementation.&lt;br /&gt;
&lt;/div&gt;&lt;h2&gt;Implementing the Service: .htaccess and index.php&lt;/h2&gt;&lt;div&gt;We'll start the web service implementation process by setting up our .htaccess and index.php files. We'll cover the web service class implementation in Part 2 of the article.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;.htaccess &lt;/b&gt;is a file that is used by the Apache HTTP server to determine how files on your server are accessed on a per-directory basis. I won't explain it fully here, but if you want to know more about .htaccess and how you can use it, feel free to check out &lt;a href="http://httpd.apache.org/docs/2.0/howto/htaccess.html"&gt;Apache's .htaccess file tutorial&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;For our purposes, we're going to take advantage of Apache's URI rewriting engine to redirect requests to specific URIs to our index.php file. Open up a plain text editor, such as notepad, and let's begin:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The first two lines in our .htaccess file are the following:&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;RewriteEngine on&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;RewriteBase /&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;The first line is fairly self explanatory. The second line simply tells the web server that the base virtual path to our web service is "/" (for more information on how RewriteBase works, read &lt;a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#RewriteBase"&gt;this Apache doc&lt;/a&gt;).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The next line in our .htaccess file is this:&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;RewriteCond %{REQUEST_FILENAME} !-s&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;It may look crazy, but the line above is simply telling the server that it should only re-direct requests to our index.php file if the requested file does not already exist in this directory. This is useful in the case that we want to store other resources in this directory, such as documentation files.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Finally, the last line in our .htaccess file handles the redirection to index.php:&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;RewriteRule ^(.*)$ /index.php/$1 [L]&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;Once again, it looks like we have a lot of stuff here, and in truth we do. In practice, here's what the .htaccess file does:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;In your browser, you type the following: &lt;b&gt;http://www.some-domain.com/authors/&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The .htaccess file at http://www.some-domain.com/ intercepts your request and checks the directory to see if a resource named /authors/&amp;nbsp;&lt;i&gt;actually exists&lt;/i&gt;. If it does not exist, your request is rewritten as &lt;b&gt;http://www.some-domain.com/index.php/authors/&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This redirection happens on the server, however, not in your browser. So, the URI that you see in your browser is still &lt;b&gt;http://www.some-domain.com/authors/&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Let's move on and implement &lt;b&gt;index.php. &lt;/b&gt;We'll start by getting the request method and path information.&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;$method = $_SERVER['REQUEST_METHOD']; //e.g. GET, POST&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span style="color: #990000;"&gt;$path_info = $_SERVER['ORIG_PATH_INFO']; //e.g. index.php/authors/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;$uri_parts = parse_uri($path_info);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;$resource_type = $uri_parts['resource_type']; //e.g. "authors"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;$request = $uri_parts['request']; //anything after the resource type&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;$service = new BookService($method,$resource_type,$request);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;$service.execute();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;function parse_uri($path_string)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;// $path_string is something like&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;// 'index.php/authors/'&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;$path_parts = explode("/",$path_string);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;$restype = $path_parts[1];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="white-space: pre;"&gt;&amp;nbsp; &lt;/span&gt;$req = $path_parts[2];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;$ret_array = array();&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;$ret_array['resource_type'] = $restype;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;$ret_array['request'] = $req;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&amp;nbsp;&amp;nbsp;return $ret_array;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #990000; font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span style="font-family: inherit;"&gt;That's all you need for your index.php file. In the next installment we'll define the BookService class and provide the functionality needed to get the service up and running. In the meantime, if you have questions or comments feel free to post them here or email brian (at) brian-driscoll (dot) com.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-1489042901694920480?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=RbqHeA6CsFo:pCdL4_9wqEo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=RbqHeA6CsFo:pCdL4_9wqEo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=RbqHeA6CsFo:pCdL4_9wqEo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=RbqHeA6CsFo:pCdL4_9wqEo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=RbqHeA6CsFo:pCdL4_9wqEo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=RbqHeA6CsFo:pCdL4_9wqEo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=RbqHeA6CsFo:pCdL4_9wqEo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=RbqHeA6CsFo:pCdL4_9wqEo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/RbqHeA6CsFo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/RbqHeA6CsFo/building-rest-or-rest-like-lamp-web.html</link><author>noreply@blogger.com (Brian Driscoll)</author><thr:total>1</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/building-rest-or-rest-like-lamp-web.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-6310237428595856285</guid><pubDate>Thu, 03 Dec 2009 16:48:00 +0000</pubDate><atom:updated>2009-12-03T11:48:31.392-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">QA</category><category domain="http://www.blogger.com/atom/ns#">testing</category><category domain="http://www.blogger.com/atom/ns#">UI/UX</category><title>Why External UI Testing Matters</title><description>I'm not a UI/UX person, nor do I have a degree in human-computer interaction. I'm a programmer. And today, a client is going to yell at me.&lt;br /&gt;
&lt;br /&gt;
Long story short: a&amp;nbsp;web application&amp;nbsp;I created a while back was supposed to automatically save user-entered data, which it did - but only if the user followed a specific interaction sequence. Of course, this specific interaction sequence made perfect sense to me, our QA group, and our client's beta test group, as not a single person reported having a problem with saving data prior to the application's commercial release.&lt;br /&gt;
&lt;br /&gt;
Now, almost a year after release, complaints are pouring in from our client's customers about issues with data saving. After looking at all of the potential causes of such a failure I found the cause: user interaction sequences that were not captured at any point during the design and development application, and thus do not trigger data saving.&lt;br /&gt;
&lt;br /&gt;
Of course, since these alternative sequences were discovered we've&amp;nbsp;added the appropriate code to save data,&amp;nbsp;and the application is working well. But, that isn't going to keep me from getting yelled at by our client. &lt;br /&gt;
&lt;br /&gt;
So, what have I learned from this experience?&lt;br /&gt;
&lt;br /&gt;
I've learned that sometimes, no matter how thorough an internal QA team might be, they're just &lt;em&gt;too close&lt;/em&gt;&amp;nbsp;to the project to be able to see all of the potential problems that might occur on the end-user side of the application. Thus, I've concluded that on applications such as this one it is important to conduct black-box testing with users who have at most minimal familiarity with the project's deliverables. I'm confident that if we'd had someone external to the project sit down and go through the application without any prompting or coaching, the problematic UI sequences would have been captured and addressed long before the application was released.&lt;br /&gt;
&lt;br /&gt;
...and I wouldn't be getting yelled at.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-6310237428595856285?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=oufPkTlxH54:4Fl6S8qv5qU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=oufPkTlxH54:4Fl6S8qv5qU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=oufPkTlxH54:4Fl6S8qv5qU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=oufPkTlxH54:4Fl6S8qv5qU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=oufPkTlxH54:4Fl6S8qv5qU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=oufPkTlxH54:4Fl6S8qv5qU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=oufPkTlxH54:4Fl6S8qv5qU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=oufPkTlxH54:4Fl6S8qv5qU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/oufPkTlxH54" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/oufPkTlxH54/why-external-ui-testing-matters.html</link><author>noreply@blogger.com (Driscoll Web Development)</author><thr:total>0</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/why-external-ui-testing-matters.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-851694985685459021</guid><pubDate>Wed, 02 Dec 2009 18:47:00 +0000</pubDate><atom:updated>2009-12-02T19:06:24.549-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutorials</category><category domain="http://www.blogger.com/atom/ns#">object-oriented analysis and design</category><category domain="http://www.blogger.com/atom/ns#">object-oriented programming</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">refactoring</category><title>The Interface Will Set You Free</title><description>All too often I see object-oriented programmers jump into coding a project with both feet first, without thinking much about the design of the project. This post is sort of a cautionary tale / exercise to get you thinking about what you should consider &lt;i&gt;before&lt;/i&gt; you start to write code. The purpose of this article is to show you how using interfaces can make your code both more reliable and more scalable, as well as easier to maintain.&lt;br /&gt;
&lt;br /&gt;
Imagine that we're creating a new end-to-end POS system for a grocery store called BD Market. Let's assume for the time being that you know (or at least you &lt;b&gt;think&lt;/b&gt; you know) everything you need to about the domain. So, like any eager programmer who doesn't want to waste his client's time and money you start creating classes - and here's what you have so far:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;class PerishableItem
    {
        public string Name { get; set; }
        public double Price { get; set; }
        public double UnitPrice { get; set; }
        public uint SKU { get; set; }
        public DateTime SellByDate { get; set; }
        public DateTime ExpirationDate { get; set; }
        protected delegate void ExpiredItemHandler(object sender,ExpiredItemEventArgs e);
        public event ExpiredItemHandler Expired;

        protected void OnExpired(object item, ExpiredItemEventArgs eArgs)
        {
            if (this.Expired != null)
            {
                Expired(item, eArgs);
            }
        }

    }

    class NonPerishableItem
    {
        string Name { get; set; }
        double Price { get; set; }
        double UnitPrice { get; set; }
        uint SKU { get; set; }
    }

    class Scanner
    {
        public void Scan(PerishableItem item)
        {
            ///TODO: Update the inventory database using the product's SKU
            ///TODO: Add the price of this item to the order subtotal
        }

        public void Scan(NonPerishableItem item)
        {
            ///TODO: Update the inventory database using the product's SKU
            ///TODO: Add the price of this item to the order subtotal
        }

        public void CancelScan(PerishableItem item)
        {
            ///TODO: Update the inventory database using the product's SKU
            ///TODO: Subtract the price of this item from the order subtotal
        }

        public void CancelScan(NonPerishableItem item)
        {
            ///TODO: Update the inventory database using the product's SKU
            ///TODO: Subtract the price of this item from the order subtotal
        }
    }
&lt;/pre&gt;&lt;br /&gt;
Notice any problems? If not, then it's a good thing you're reading this. Take another look at the code above and note the following:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Both PerishableItem and NonPerishableItem have the data members Name, SKU, RetailPrice, and UnitPrice in common.&lt;/li&gt;
&lt;li&gt;Each implementation of the Scanner class's Scan and CancelScan methods does the exact same thing.&lt;/li&gt;
&lt;/ol&gt;Let's face it: a real-world grocery store scanner can't tell the difference between a perishable food item and a non-perishable one, so why does your Scanner class need to know the difference? The answer is: it doesn't. Furthermore, what will happen if you create a third item class and forget to add a Scan() and CancelScan() method to your Scanner class for that item type? As you can imagine, the situation gets uglier and uglier the more you think about it.&lt;br /&gt;
&lt;br /&gt;
So, what can we do to avoid this mess now, and make it such that adding additional item types in the future won't break our Scanner class? We're going to create an interface called IProduct, that's what:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;interface IProduct
    {
        string Name { get; set; }
        double Price { get; set; }
        double UnitPrice { get; set; }
        uint SKU { get; set; }
    }
&lt;/pre&gt;&lt;br /&gt;
The IProduct interface defines signatures for the public properties that we want to expose in the classes that implement this interface. We can then refactor our Scanner class so that only one Scan() and one CancelScan() implementation is needed. See the updated code below:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;class PerishableItem : IProduct
    {
        #region IProduct Interface Data Members
        public string Name { get; set; }
        public double Price { get; set; }
        public double UnitPrice { get; set; }
        public uint SKU { get; set; }
        #endregion

        //Omitted Code... it's the same as above
    }

    class NonPerishableItem : IProduct
    {
        #region IProduct Interface Data Members
        string Name { get; set; }
        double Price { get; set; }
        double UnitPrice { get; set; }
        uint SKU { get; set; }
        #endregion
    }

    class Scanner
    {
        public void Scan(IProduct item)
        {
            ///TODO: Update the inventory database
            ///TODO: Add the price of this item to the order subtotal
        }

        public void CancelScan(IProduct item)
        {
            ///TODO: Update the inventory database
            ///TODO: Subtract the price of this item from the order subtotal
        }
    }
&lt;/pre&gt;&lt;br /&gt;
The biggest (and most helpful) difference you can see is that now we only need one implementation of the Scan() and CancelScan() methods in our Scanner class. This has a future benefit as well, because as long as item types we create in the future implement the IProduct interface we do not have to concern ourselves with updating the Scanner class.&lt;br /&gt;
&lt;br /&gt;
I hope that the brief example above has shown you how using interfaces can help you to write more robust code in your object-oriented projects. Please feel free to send any questions my way at brian (at) brian-driscoll (dot) com, or leave a comment below.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-851694985685459021?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o3_Z5x440dM:Zm0t4rM2Hw0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o3_Z5x440dM:Zm0t4rM2Hw0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o3_Z5x440dM:Zm0t4rM2Hw0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o3_Z5x440dM:Zm0t4rM2Hw0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o3_Z5x440dM:Zm0t4rM2Hw0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o3_Z5x440dM:Zm0t4rM2Hw0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=o3_Z5x440dM:Zm0t4rM2Hw0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=o3_Z5x440dM:Zm0t4rM2Hw0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/o3_Z5x440dM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/o3_Z5x440dM/interface-will-set-you-free.html</link><author>noreply@blogger.com (Brian Driscoll)</author><thr:total>0</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/interface-will-set-you-free.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-281503025845848341.post-5995215138456593505</guid><pubDate>Tue, 01 Dec 2009 18:21:00 +0000</pubDate><atom:updated>2009-12-01T13:21:28.881-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET 4</category><category domain="http://www.blogger.com/atom/ns#">Silverlight 4</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><title>The Problem with Silverlight Right Now</title><description>I've been working with Silverlight in its various forms over the last 9 months to develop LOB apps for my employer. I've seen the framework come along from a very lightweight presentation framework to a relatively robust RIA development platform, and I can say that I'm very happy about it and impressed with the Silverlight team for their diligence. Recently, I caught a glimpse of some of the &lt;a href="http://www.silverlight.net/getstarted/silverlight-4-beta/#whatsnew"&gt;new APIs&lt;/a&gt; that will be available in the Silverlight 4 release, and as a business app developer I'm both excited about and impressed with the new features that will be available.&lt;br /&gt;
&lt;br /&gt;
Of course, this excitement is somewhat bittersweet.&lt;br /&gt;
&lt;br /&gt;
As excited as I am about Silverlight 4, I'm really dreading the process of porting my existing Silverlight 3 apps to Silverlight 4, as I'm sure some of the SL3 APIs will no longer work when SL4 is released. I'm also not too thrilled with the fact that I'll have to shell out $$$ to buy VS 2010 and yet another version of Expression Blend just to be able to build SL4 apps and/or port my existing SL3 apps.&lt;br /&gt;
&lt;br /&gt;
TCO is a big issue for businesses right now, and I honestly have to say that Adobe has Microsoft beat in this department. I really like .NET development more than AS3 development for various reasons, but when it comes down to dollars and sense I'm just not sure I can keep paying for the IDE upgrades every time there's a new Silverlight release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/281503025845848341-5995215138456593505?l=www.brian-driscoll.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=GaPkX8e22UI:D0GkS0eAGUo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=GaPkX8e22UI:D0GkS0eAGUo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=GaPkX8e22UI:D0GkS0eAGUo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=GaPkX8e22UI:D0GkS0eAGUo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=GaPkX8e22UI:D0GkS0eAGUo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=GaPkX8e22UI:D0GkS0eAGUo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/brian-on-code?a=GaPkX8e22UI:D0GkS0eAGUo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/brian-on-code?i=GaPkX8e22UI:D0GkS0eAGUo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/brian-on-code/~4/GaPkX8e22UI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/brian-on-code/~3/GaPkX8e22UI/problem-with-silverlight-right-now.html</link><author>noreply@blogger.com (Brian Driscoll)</author><thr:total>1</thr:total><feedburner:origLink>http://www.brian-driscoll.com/2009/12/problem-with-silverlight-right-now.html</feedburner:origLink></item></channel></rss>
