<?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>King Kludge &#187; Development</title>
	<atom:link href="http://www.kingkludge.net/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kingkludge.net</link>
	<description>Poking my sausage like fingers into the web since 1997</description>
	<lastBuildDate>Tue, 16 Feb 2010 14:57:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Maker Projects &#8211; Alex&#8217;s Mobile</title>
		<link>http://www.kingkludge.net/2010/01/maker-projects-alexs-mobile/</link>
		<comments>http://www.kingkludge.net/2010/01/maker-projects-alexs-mobile/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 11:49:01 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Maker]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[baby mobile]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/?p=150</guid>
		<description><![CDATA[I've added a new section to my projects pages, and put a page in place for the baby mobile I'm creating for Alex.
I've back dated a load of the updates, as I'd been meaning to post blog entries about the work, but hadn't gotten round to it.
So far I have a 3d design worked out [...]]]></description>
			<content:encoded><![CDATA[<p>I've added a new section to my projects pages, and put a page in place for the <a href="/projects/maker/alexs-mobile/">baby mobile I'm creating for Alex</a>.</p>
<p>I've back dated a load of the updates, as I'd been meaning to post blog entries about the work, but hadn't gotten round to it.</p>
<p>So far I have a 3d design worked out a working prototype circuit and a full breadboard circuit also designed.</p>
<p>I'll try and put up some full photo's soon and maybe even some video of the prototype.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2010/01/maker-projects-alexs-mobile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook performance woes</title>
		<link>http://www.kingkludge.net/2009/12/facebook-performance-woes/</link>
		<comments>http://www.kingkludge.net/2009/12/facebook-performance-woes/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 17:42:15 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Yahoo!]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/12/facebook-performance-woes/</guid>
		<description><![CDATA[Today Facebook launched their new privacy settings and forced all their users to update their settings.
We noticed at Yahoo! that we were started to get lots of timeouts from Facebook's APIs that we use on the Yahoo! homepage.
I've not heard anything official from Facebook yet, so this next part is all speculation.
I suspect that as [...]]]></description>
			<content:encoded><![CDATA[<p>Today Facebook launched their new privacy settings and forced all their users to update their settings.</p>
<p>We noticed at Yahoo! that we were started to get lots of timeouts from Facebook's APIs that we use on the Yahoo! homepage.</p>
<p>I've not heard anything official from Facebook yet, so this next part is all speculation.</p>
<p>I suspect that as a user updates their privacy settings, as forced to the first time they hit facebook.com now, Facebook flags that users account is dirty (something changed) and purges the cache of the users stream data.<br />
Now that the cache is empty for a particular user, when a friend of that user views Facebook, the backend servers must go back to the master data source and confirm permissions on what is visible before it is displayed. </p>
<p>That is fine when you have a few users updating their permissions, if however you force ALL your users to do this, you site rapidly becomes overwhelmed, as you effectively removed your cache. This effect is known as "The Thundering Herd".</p>
<p>As the load increases, due to all extra requests for data that would normally be handled by caches, you start to get race conditions as requests return and try to populate the cache. Also as the load increases, requests start to take longer as connections are kept open while backends are queried. Because connections are being kept open, the server stops handling requests, as there are no more connection slots and you start to get errors as clients can no longer connect.</p>
<p>How do you prevent this. Don't push changes that require you whole userbase to update their records at once. Stage the release, starting with 1% until you can guage how much load it will generate on your servers. Then you can safely ramp up your change safely.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/12/facebook-performance-woes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Junkbots</title>
		<link>http://www.kingkludge.net/2009/09/junkbots/</link>
		<comments>http://www.kingkludge.net/2009/09/junkbots/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 08:11:28 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[ipaq]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[old hardware]]></category>
		<category><![CDATA[Robots]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/?p=91</guid>
		<description><![CDATA[Recently I subscribed to MAKEzine and it has reinvigorated my interest if hardware hacking.
Which is good, as I'm doing a talk at SkillsMatter in December on that very subject.
Since I won an iPhone in a raffle last month I now have a surplus ipaq that used to be my portable brain, randomly I came across [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I subscribed to <a title="take a look at MakeZine" href="http://www.makezine.com/">MAKEzine</a> and it has reinvigorated my interest if hardware hacking.</p>
<p>Which is good, as I'm doing a talk at SkillsMatter in December on that very subject.</p>
<p>Since I won an iPhone in a raffle last month I now have a surplus ipaq that used to be my portable brain, randomly I came across <a title="Familiar Linux for iPAQs" href="http://familiar.handhelds.org/releases/v0.8.4/install/download.html">this site </a><a title="Familiar Linux for iPAQs" href="http://familiar.handhelds.org/releases/v0.8.4/install/download.html"> on running Linux on ipaqs</a>. So this maybe the way to go.</p>
<p>However<a title="go look at Dave Shinsel's Robots" href="http://dshinsel.com/SeekerLaptopSoftware.htm"> this guy </a><a title="go look at Dave Shinsel's Robots" href="http://dshinsel.com/SeekerLaptopSoftware.htm"> also made some really cool bots running windows C++ code</a>. I think certainly with an ipaq as the brains plus computer junk from the loft I probably have the kit for some interesting junkbots.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/09/junkbots/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projects</title>
		<link>http://www.kingkludge.net/projects/</link>
		<comments>http://www.kingkludge.net/projects/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 07:46:46 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Maker]]></category>
		<category><![CDATA[Ramblings]]></category>
		<category><![CDATA[Robots]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/?page_id=90</guid>
		<description><![CDATA[I'm an innate tinkerer, so here I'll be listing the projects I'm working on and their progress (or not).
One other thing you'll notice is that, like my reading habits, I tend to have lots of projects on the go at the same time. I'll come back to them every now and again, and then may [...]]]></description>
			<content:encoded><![CDATA[<p>I'm an innate tinkerer, so here I'll be listing the projects I'm working on and their progress (or not).</p>
<p>One other thing you'll notice is that, like my reading habits, I tend to have lots of projects on the go at the same time. I'll come back to them every now and again, and then may drop them for lengthy periods (sometimes years) which frustrates my wife <img src='http://www.kingkludge.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  who tells me she is a "<a href="http://en.wikipedia.org/wiki/Belbin_Team_Inventory#Completer_Finisher">Completer Finisher</a>" mentality.</p>
<p>That probably makes me a mix of  <a href="http://en.wikipedia.org/wiki/Belbin_Team_Inventory#Plant">Plant</a>/<a href="http://en.wikipedia.org/wiki/Belbin_Team_Inventory#Implementer">Implementer</a>/<a href="http://en.wikipedia.org/wiki/Belbin_Team_Inventory#Specialist">Specialist</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tesco TJam</title>
		<link>http://www.kingkludge.net/2009/08/tesco-tjam/</link>
		<comments>http://www.kingkludge.net/2009/08/tesco-tjam/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 20:11:53 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[tesco]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/08/tesco-tjam/</guid>
		<description><![CDATA[So this evening I attended Tesco's TJam event held at Microsoft's London Customer Centre at Victoria.
Tesco is starting the rollout of it's new backend Grocery application, code named Martini (anytime, anyplace, anywhere).
They have opened up their new APIs from their grocery service to a few select developers. In fact very select, you had to attend [...]]]></description>
			<content:encoded><![CDATA[<p>So this evening I attended Tesco's TJam event held at Microsoft's London Customer Centre at Victoria.</p>
<p>Tesco is starting the rollout of it's new backend Grocery application, code named Martini (anytime, anyplace, anywhere).<br />
They have opened up their new APIs from their grocery service to a few select developers. In fact very select, you had to attend to launch/briefing in person to register for the scheme.</p>
<p>A lot of time had obviously gone into preparing the event. With almost the whole conference room covered in brainstorm sheets and post it notes. These covered 5 main areas for potential developers to concentrate on or consider for their application. This was based on market and socioethnic research (hey that may not be the correct word but I didn't write it down and I'm now on the train).</p>
<p>After an initial introduction, we were all invited to chow down on pizza, lager and wine (actually nice for change to get red and white wine available) and browse the brainstormings, only slightly hindered by Microsoft's insistence that no one take food or drink into their meeting rooms.</p>
<p>The APIs look reasonably well thought out and the new Martini release adds some great new functionality, such as nutrition information and cheaper alternatives to products in your shopping basket.</p>
<p>There were some concerns voiced by some developers present at the briefing, quite rightly, over their security implementation, which requires the API consumer to forward the users login credentials, rather than implementing OAuth or another signature/token based authentication mechanism.<br />
It looks like this will probably be addressed in a future release, once Martini is live and running Tesco's existing shopping site.<br />
Customer basket checkout has yet to) be finalised, due to financial and legal compliance.</p>
<p>Everyone who attended the event and wishes to participate in the affliate scheme will get signed up to TradeDoubler and will earn £5 for each new customer they manage to entice into signing up to Tesco's online shopping service.<br />
The tricky part of this is then the ongoing revenue.<br />
For each basket purchased over the value of £50 the application developer gets a potential £0.10. Potential, as this is the proportional to the number of products added to basket by that particular application versus the total number of products in the basket.<br />
Note also products in basket not items. 10 one penny chews would earn you the same as someone adding an iPhone or flatscreen tv. This is deliberate, to prevent skewing of apps towards higher value goods.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/08/tesco-tjam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>T-JAM and the Tesco Grocery API</title>
		<link>http://www.kingkludge.net/2009/08/t-jam-and-the-tesco-grocery-api/</link>
		<comments>http://www.kingkludge.net/2009/08/t-jam-and-the-tesco-grocery-api/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 22:36:13 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[shopping]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[tesco]]></category>
		<category><![CDATA[tjam]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/08/t-jam-and-the-tesco-grocery-api/</guid>
		<description><![CDATA[Finally found something I can talk about openly.
Having spent so long working on commercially sensitive applications, which is now in the open.
Anyway, apart from helping the Yahoo! OpenHack day, I also signed up to Tesco's T-JAM event which certainly looks like it could be interesting.
Tesco's API is a SOAP API, written in and for C# [...]]]></description>
			<content:encoded><![CDATA[<p>Finally found something I can talk about openly.</p>
<p>Having spent so long working on <a href="http://www.kingkludge.net/2009/08/new-yahoo-homepage/">commercially sensitive applications</a>, which is now in the open.</p>
<p>Anyway, apart from helping the Yahoo! OpenHack day, I also signed up to <a href="http://techfortesco.blogspot.com/2009/08/two-days-until-tjam.html">Tesco's T-JAM event</a> which certainly looks like it could be interesting.</p>
<p>Tesco's API is a SOAP API, written in and for C# primarily, so it seems that some people had some issues getting started in PHP.</p>
<p>There is a revised API in the pipeline and also the addition of a REST API as well.</p>
<p>But here are some handy hints for getting started:</p>
<p>First off, PHP 5+ has a SOAP client (and server) built in, so here's a quick script that generates a valid login to the TESCO dev API.</p>
<pre class="prettyprint">&lt;?php
define('SOAPSERVER', 'http://www.lansley.com/TescoAPI/TescoAPI.svc?wsdl');
define('DEV_KEY', 'your dev key');
define('APP_KEY', 'your app key');

$user  = 'email address of test user';
$pass  = 'password of test user';
$tesco = new SoapClient(SOAPSERVER);

$params = array(
                'email'          =&gt; $user,
                'password'       =&gt; $pass,
                'developerKey'   =&gt; DEV_KEY,
                'applicationKey' =&gt; APP_KEY
              );
$sess = $tesco-&gt;__soapCall('Login', array('parameters' =&gt; $params));
print_r($sess);</pre>
<p>Which generates the following output:</p>
<pre class="commandline">stdClass Object
(
    [LoginResult] =&gt; stdClass Object
        (
            [StatusCode] =&gt; 0
            [StatusInfo] =&gt;
        )

    [session] =&gt; stdClass Object
        (
            [ApplicationKey] =&gt; your app key
            [BranchNumber] =&gt; 2055
            [Cookies] =&gt; stdClass Object
                (
                    [string] =&gt; Array
                        (
                            [0] =&gt; sessionTest=
                            [1] =&gt; v=WggAACp8E%3d%3d
                            [2] =&gt; CustomerId=9xxx9
                            [3] =&gt; CID=93
                            [4] =&gt; BTCCMS=h1qzwp%c%3d
                            [5] =&gt; UIMode=00000
                            [6] =&gt; PS=CSC=D
                            [7] =&gt; SSVars=CustomerName=Bob&amp;basketTotal=&amp;basketCount=&amp;slotStart=&amp;slotEnd=&amp;addrName=
                            [8] =&gt; u=oQgttVAeDK%2bg%3d%3d
                            [9] =&gt; t=dgcAA28XbJWE%3d
                        )

                )

            [CustomerName] =&gt; Bob
            [DeveloperKey] =&gt; your dev key
        )

)</pre>
<p>I've monkeyed around with the values in some of the keys (as these are my login credentials) but you can see the general structure. The session object needs to be stored and used in subsequent requests.</p>
<p>To interrogate the API and view the functions and types available, there are some PHP functions to help:</p>
<pre class="prettyprint">&lt;?php
define('SOAPSERVER', 'http://www.lansley.com/TescoAPI/TescoAPI.svc?wsdl');
define('DEV_KEY', 'your dev key');
define('APP_KEY', 'your app key');

$tesco = new SoapClient(SOAPSERVER);

print_r($tesco-&gt;__getFunctions());</pre>
</p>
<p>Which shows the following SOAP methods available:</p>
<pre class="commandline">Array
(
    [0] =&gt; LoginResponse Login(Login $parameters)
    [1] =&gt; LogEventResponse LogEvent(LogEvent $parameters)
    [2] =&gt; ProductSearchResponse ProductSearch(ProductSearch $parameters)
    [3] =&gt; ListProductOffersResponse ListProductOffers(ListProductOffers $parameters)
    [4] =&gt; ListProductCategoriesResponse ListProductCategories(ListProductCategories $parameters)
    [5] =&gt; ListProductsByCategoryResponse ListProductsByCategory(ListProductsByCategory $parameters)
    [6] =&gt; SetProductRatingResponse SetProductRating(SetProductRating $parameters)
    [7] =&gt; GetProductRatingResponse GetProductRating(GetProductRating $parameters)
    [8] =&gt; GetMultipleProductRatingsResponse GetMultipleProductRatings(GetMultipleProductRatings $parameters)
    [9] =&gt; ListBasketItemsResponse ListBasketItems(ListBasketItems $parameters)
    [10] =&gt; AddItemToBasketResponse AddItemToBasket(AddItemToBasket $parameters)
    [11] =&gt; ChangeItemQuantityResponse ChangeItemQuantity(ChangeItemQuantity $parameters)
    [12] =&gt; DeleteItemFromBasketResponse DeleteItemFromBasket(DeleteItemFromBasket $parameters)
)</pre>
<p>And:</p>
<pre class="prettyprint">&lt;?php
define('SOAPSERVER', 'http://www.lansley.com/TescoAPI/TescoAPI.svc?wsdl');
define('DEV_KEY', 'your dev key');
define('APP_KEY', 'your app key');

$tesco = new SoapClient(SOAPSERVER);

print_r($tesco-&gt;__getTypes());</pre>
</p>
<p>Which shows the following types available:</p>
<pre class="commandline">Array
(
    [0] =&gt; struct ArrayOfstring {
 string string;
}
    [1] =&gt; struct ResponseStatus {
 int StatusCode;
 string StatusInfo;
}
    [2] =&gt; struct Session {
 string ApplicationKey;
 string BranchNumber;
 ArrayOfstring Cookies;
 string CustomerName;
 string DeveloperKey;
}
    [3] =&gt; struct ArrayOfProduct {
 Product Product;
}
    [4] =&gt; struct Product {
 string Id;
 string ImagePath;
 string Name;
 string OfferPromotion;
 string OfferValidity;
 double Price;
 int Quantity;
 float Rating;
}
    [5] =&gt; struct ArrayOfCategory {
 Category Category;
}
    [6] =&gt; struct Category {
 ArrayOfCategory Children;
 string Href;
 string Id;
 string Name;
 string RawHtml;
}
    [7] =&gt; struct ProductRating {
 string Id;
 int MyRating;
 float Rating;
 int Rating1Count;
 int Rating2Count;
 int Rating3Count;
 int Rating4Count;
 int Rating5Count;
}
    [8] =&gt; struct Login {
 string email;
 string password;
 string developerKey;
 string applicationKey;
}
    [9] =&gt; struct LoginResponse {
 ResponseStatus LoginResult;
 Session session;
}
    [10] =&gt; struct LogEvent {
 Session session;
 string eventText;
}
    [11] =&gt; struct LogEventResponse {
 ResponseStatus LogEventResult;
}
    [12] =&gt; int char
    [13] =&gt; duration duration
    [14] =&gt; string guid
    [15] =&gt; struct ProductSearch {
 Session session;
 string searchString;
 boolean getRatings;
}
    [16] =&gt; struct ProductSearchResponse {
 ResponseStatus ProductSearchResult;
 ArrayOfProduct products;
}
    [17] =&gt; struct ListProductOffers {
 Session session;
 boolean getRatings;
}
    [18] =&gt; struct ListProductOffersResponse {
 ResponseStatus ListProductOffersResult;
 ArrayOfProduct offers;
}
    [19] =&gt; struct ListProductCategories {
 Session session;
}
    [20] =&gt; struct ListProductCategoriesResponse {
 ResponseStatus ListProductCategoriesResult;
 ArrayOfCategory categories;
}
    [21] =&gt; struct ListProductsByCategory {
 Session session;
 Category shelf;
 boolean getRatings;
}
    [22] =&gt; struct ListProductsByCategoryResponse {
 ResponseStatus ListProductsByCategoryResult;
 ArrayOfProduct products;
}
    [23] =&gt; struct SetProductRating {
 Session session;
 Product product;
}
    [24] =&gt; struct SetProductRatingResponse {
 ResponseStatus SetProductRatingResult;
}
    [25] =&gt; struct GetProductRating {
 Session session;
 Product thisproduct;
}
    [26] =&gt; struct GetProductRatingResponse {
 ResponseStatus GetProductRatingResult;
 ProductRating productrating;
}
    [27] =&gt; struct GetMultipleProductRatings {
 Session session;
 string spaceDelimitedProductIDs;
}
    [28] =&gt; struct GetMultipleProductRatingsResponse {
 ResponseStatus GetMultipleProductRatingsResult;
 string productRatingsInfo;
}
    [29] =&gt; struct ListBasketItems {
 Session session;
}
    [30] =&gt; struct ListBasketItemsResponse {
 ResponseStatus ListBasketItemsResult;
 ArrayOfProduct products;
}
    [31] =&gt; struct AddItemToBasket {
 Session session;
 Product item;
}
    [32] =&gt; struct AddItemToBasketResponse {
 ResponseStatus AddItemToBasketResult;
}
    [33] =&gt; struct ChangeItemQuantity {
 Session session;
 Product item;
}
    [34] =&gt; struct ChangeItemQuantityResponse {
 ResponseStatus ChangeItemQuantityResult;
}
    [35] =&gt; struct DeleteItemFromBasket {
 Session session;
 Product item;
}
    [36] =&gt; struct DeleteItemFromBasketResponse {
 ResponseStatus DeleteItemFromBasketResult;
}
)</pre>
<p>Hope this helps, not just with the Tesco Grocery API, but in general debugging SOAP calls from within PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/08/t-jam-and-the-tesco-grocery-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Yahoo! Homepage</title>
		<link>http://www.kingkludge.net/2009/08/new-yahoo-homepage/</link>
		<comments>http://www.kingkludge.net/2009/08/new-yahoo-homepage/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 21:40:20 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Yahoo!]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[yahoo homepage]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/08/new-yahoo-homepage/</guid>
		<description><![CDATA[So the reason I've not posted anything for a while, and have had to be careful about what I talk about when and if I do.
Last week we turned on the opt in to the Yahoo! Homepage http://uk.yahoo.com/trynew 
My personal project was writing the Facebook App, which does seem to have received a fair amount [...]]]></description>
			<content:encoded><![CDATA[<p>So the reason I've not posted anything for a while, and have had to be careful about what I talk about when and if I do.</p>
<p>Last week we turned on the opt in to the Yahoo! Homepage <a href="http://uk.yahoo.com/trynew">http://uk.yahoo.com/trynew</a> </p>
<p>My personal project was writing the Facebook App, which does seem to have received a fair amount of press coverage.</p>
<p>However for the last 18 months we've been working on a complete rewrite of the homepage.</p>
<p>This has included releasing four countries (France, United Kingdom, United States and India) all using the same codebase and the same developers.</p>
<p>Personally I've been involved in setting up testing frameworks, continuous integration and code quality.</p>
<p>I'll try and publish further updates later. Specifically, if possible, information on the Facebook App.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/08/new-yahoo-homepage/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The CodeSniffer Series</title>
		<link>http://www.kingkludge.net/2009/08/the-codesniffer-series/</link>
		<comments>http://www.kingkludge.net/2009/08/the-codesniffer-series/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 21:04:55 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Yahoo!]]></category>
		<category><![CDATA[code analysis]]></category>
		<category><![CDATA[codesniffer]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/08/the-codesniffer-series/</guid>
		<description><![CDATA[Recently I wrote a series of posts about PHP CodeSniffer the PHP PEAR project.
This is a brief reminder of the series and a list of all the articles.
These articles are the originals and are being used as a base for a YDN article to be published shortly.

Introduction to CodeSniffer 
CodeSniffer Output 
Writing an example CodeSniffer [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I wrote a series of posts about PHP CodeSniffer the PHP PEAR project.</p>
<p>This is a brief reminder of the series and a list of all the articles.</p>
<p>These articles are the originals and are being used as a base for a <a title="Yahoo Developers Network" href="http://developer.yahoo.com">YDN</a> article to be published shortly.</p>
<ol>
<li><a href="/2009/01/codesniffer-part-1-introduction-to-codesniffer/">Introduction to CodeSniffer</a> </li>
<li><a href="/?p=62">CodeSniffer Output</a> </li>
<li><a href="/2009/02/codesniffer-part-3-writing-an-example-codesniffer-standard/">Writing an example CodeSniffer Standard</a> </li>
<li><a href="http://www.kingkludge.net/2009/02/codesniffer-part-4-how-does-codesniffer-work/">How does CodeSniffer work?</a> </li>
<li><a href="http://www.kingkludge.net/2009/08/codesniffer-part-5-writing-an-examples-codesniffer-sniff/">Writing an example CodeSniffer Sniff</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/08/the-codesniffer-series/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeSniffer Part 5: Writing an examples CodeSniffer Sniff</title>
		<link>http://www.kingkludge.net/2009/08/codesniffer-part-5-writing-an-examples-codesniffer-sniff/</link>
		<comments>http://www.kingkludge.net/2009/08/codesniffer-part-5-writing-an-examples-codesniffer-sniff/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 21:02:20 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[code analysis]]></category>
		<category><![CDATA[codesniffer]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[static code analysis]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/08/codesniffer-part-5-writing-an-examples-codesniffer-sniff/</guid>
		<description><![CDATA[How to go about developing your own CodeSniffer Sniff ready for inclusion in a CodeSniffer standard.]]></description>
			<content:encoded><![CDATA[<p>There has been a significant delay between the original posts and this final post in the initial CodeSniffer series, for which I apologise. This delay is mainly due to my recent workload increase, and the happy news that my wife is pregnant coupled with the brief flutter of nesting activity increase at home.</p>
<p><a href="/2009/02/codesniffer-part-4-how-does-codesniffer-work/">In the last post</a> we looked at the internals of CodeSniffer and how the processing of files is done. This time we will look at how an individual Sniff is constructed.</p>
<h3>Sniff Basics</h3>
<ul>
<li>Each <strong>Sniff</strong> is a PHP class. </li>
<li>Each class consist of a minimum of two methods.
<ul>
<li>A register method, that returns an array of tokens that the Sniff is interested in. </li>
<li>And a process method that is executed each time that token is encountered. </li>
</ul>
</li>
<li>Each Sniff class lives inside a <strong>Standard.</strong>
<ul>
<li>Each Sniff lives inside a subfolder &quot;Sniffs&quot; under the standard </li>
<li>Each Sniff lives inside a subfolder of &quot;Sniffs&quot; containing themed Sniffs </li>
</ul>
</li>
<li>Each Sniff class must adhere to the naming convention. </li>
</ul>
<h3>Starting a Sniff</h3>
<p>Let's take a look at an example Sniff. For instance a Sniff designed to check that our PHP code has no extraneous whitespace outside of our PHP code, that could cause a PHP error should we subsequently send headers to the browser.</p>
<p>First of all we create a class and decide on a name for it. </p>
<p>As CodeSniffer uses an autoloader that loads the class' file and path based on the class name we have to stick to a specific naming convention.</p>
<p><code class="prettyprint">class KingKludge_Sniffs_PHP_NoExtraneousWhiteSpaceSniff      <br />implements PHP_CodeSniffer_Sniff</code><code class="prettyprint"> {}</code> </p>
<p>equates to a path of:</p>
<p>{CodeSniffer}/Standards/KingKludge/Sniffs/PHP/NoExtraneousWhiteSpaceSniff.php</p>
<p>where {CodeSniffer} is your CodeSniffer install path.</p>
<p>Secondly, inside our new class we must define our register method:</p>
<pre class="prettyprint">public function register()
{
	return array(
		T_OPEN_TAG,
		T_CLOSE_TAG,
		);
} </pre>
<p>As we want to check for whitespace before or after our PHP declarations, we state that this sniff is interested in PHP open and close tags.</p>
<p>Thirdly, we must define our process method:</p>
<pre class="prettyprint">

public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{

}
</pre>
<p>As you can see, our process method is passed some parameters.</p>
<p>These are <code>$phpcsFile</code> which is <code>PHP_CodeSniffer_File</code> object, containing the file being processed and <code>$stackPtr</code> an integer value pointing to CodeSniffer's current place in the file.</p>
<p><a title="Empty class file with function definitions only" href="http://github.com/b3cft/kingkludge-codesniffer/raw/3a3334dce2e76441c539d5fd94272c5b3bb0009d/KingKludge/Sniffs/PHP/NoExtraneousWhiteSpace.php">View the empty standard file on GitHub</a></p>
<p>Now on to the actually code in our Sniff.</p>
<p>As our proposed Sniff is going to look for whitespace being output before our page is ready to be rendered, we are interested in whitespace that occurs before the opening PHP tag or after the closing PHP tag.</p>
<p>We are only interested in whitespace, any HTML or other markup is okay.</p>
<p>So we can see if our pointer is at the beginning of the file, if so, drop out of the process.</p>
<pre class="prettyprint">$tokens = $phpcsFile-&gt;getTokens();
if (T_OPEN_TAG === $tokens[$stackPtr]['code'])
{
	if (0 === $stackPtr)
	{
		return;
	}
}</pre>
<p>The getTokens() command returns all of the tokens for the current file in an associative array. (in case you didn't realise).</p>
<p>The rest should be self explanatory.</p>
<p>We can also do a similar check for a PHP close tag</p>
<pre class="prettyprint">if (T_CLOSE_TAG === $tokens[$stackPtr]['code'])
{
	$content = $tokens[$stackPtr]['content'];
	if (
	    false === isset($tokens[($stackPtr + 1)]) &amp;&amp;
	    trim($content) === $content
	   )
	{
		return;
	}
}</pre>
<p><a title="Class file which returns when no whitespace is found." href="http://github.com/b3cft/kingkludge-codesniffer/raw/7944b8cd7146d10a64b5bec55632e6c4a50c93cf/KingKludge/Sniffs/PHP/NoExtraneousWhiteSpace.php">View the basic standard file on GitHub</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/08/codesniffer-part-5-writing-an-examples-codesniffer-sniff/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeSniffer Part 4: How does CodeSniffer Work</title>
		<link>http://www.kingkludge.net/2009/02/codesniffer-part-4-how-does-codesniffer-work/</link>
		<comments>http://www.kingkludge.net/2009/02/codesniffer-part-4-how-does-codesniffer-work/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 16:03:08 +0000</pubDate>
		<dc:creator>Bob</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[code analysis]]></category>
		<category><![CDATA[codesniffer]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[static code analysis]]></category>

		<guid isPermaLink="false">http://www.kingkludge.net/2009/02/codesniffer-part-4-how-does-codesniffer-work/</guid>
		<description><![CDATA[Looking at the internal workings of CodeSniffer and how it does it's analysis.]]></description>
			<content:encoded><![CDATA[<p><a title="Go back and read the previous article" href="/2009/02/codesniffer-part-3-writing-an-example-codesniffer-standard/">In the previous article</a> we looked at writing our own CodeSniffer standard based on pre-existing rules or sniffs.</p>
<p>This article will try to cover in-depth how CodeSniffer actually works to give insight into the next proposed article, writing a sniff from scratch.</p>
<h3>The PHP Tokenizer</h3>
<p>CodeSniffer works by extending the PHP tokenizer function.</p>
<p>Given the following section of code:</p>
<pre class="prettyprint">&lt;?php

function DoSomething(array $foo) {
    print_r($foo);
}

?&gt;&nbsp;&nbsp; </pre>
<p>and running it through PHP's native tokenizer we get the following output</p>
<p><a title="PHP Tokenized version of foo.php" href="http://github.com/b3cft/kingkludge-codesniffer/raw/8e0348253cf01c27bb6966a79dae6b7a7e592323/misc/php_tokenized_foo.txt" rel="shadowbox">PHP Tokenized version of foo.php</a></p>
</p>
<pre></pre>
<p>PHP's tokenizer only identifies a limited subset of PHP syntax <a title="List of PHP Tokens on the english PHP Manual site" href="http://www.php.net/manual/en/tokens.php" rel="shadowbox">as listed here</a>.</p>
<p>All other potential tokens get either identifies as a string, signified by the sub array[0] integer value of 307 or the constant <code>T_STRING</code>, else it simply returns the string value of the token i.e. those seen array values 17,18 and 20 in the sample output above.</p>
<p>To map the above integer values to PHP's string constant name you can use the PHP function token_name() </p>
<p>For example:</p>
<pre class="commandline">$ php -r "print(token_name(369));"
T_CLOSE_TAG</pre>
<p>As once the PHP tokenizer has run, we have a lot of code still encapsulated as T_STRING or with no tokenizing done, CodeSniffer takes these simple tokens and expands them further. </p>
<p>CodeSniffer introduces new constants such as <code>T_TRUE</code>, <code>T_FALSE</code>, <code>T_NULL</code>, <code>T_PARENT</code>, <code>T_OPEN_CURLY_BRACKET</code> and so on.</p>
<p>This gives CodeSniffer considerable scope to be able to handle much finer detail of the PHP syntax. </p>
<h3>The PHP CodeSniffer Tokenizer</h3>
<p>When CodeSniffer first loads, the standard in use is determined from the command line or from the stored config. The standard is then loaded and all of that standard's sniffs are loaded.</p>
<p>Each of the sniffs gets called via the register() method and a hash of all the tokens and classes is created.</p>
<p>Then CodeSniffer starts looking for the files to check, if a directory is specified, CodeSniffer iterates through the directories until a file with the correct extension is found, then each file is processed in turn.</p>
<p>If a list of files or a single file is specified, then the above step is skipped and CodeSniffer starts parsing the file(s) as defined in the parameters.</p>
<p>Once CodeSniffer has tokenized the file under analysis into one (rather large) multidimensional array of language syntax tokens, the rest is quite simple.</p>
<p>CodeSniffer breaks each file under examination down and does a series of context checks before processing the tokens and calling all the registered sniffs.</p>
<p>These checks are:</p>
<ol>
<li>Bracket Map: checking braces
</li>
<li>Scope Map: checking for class, function and conditional statement scopes
</li>
<li>Level Map: checking for class, function and conditional statement levels </li>
</ol>
<p><a title="PHP CodeSniffer Tokenized version of foo.php" href="http://github.com/b3cft/kingkludge-codesniffer/raw/698c0bb0dbb0441f4f759c96be697c37876aca31/misc/phpcs_tokenized_foo.txt" rel="shadowbox">If we look at the CodeSniffer Tokenized version of foo.php</a> we can see the levels of our sample script above.</p>
<p>Each Sniff in the standard has registered which tokens they are interested in being invoked to handle during the initialisation phase.</p>
<p>CodeSniffer then runs through each token in the file from beginning to end and calls all of the sniff process() method for sniffs that registered and interest in that token.</p>
<p>Finally all of the errors and warnings generated by those sniffs are organised into the desired report type and displayed.</p>
<p>So now we have an insight into how CodeSniffer works, in the next and final post in this series on CodeSniffer, we'll look and writing a new Sniff.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kingkludge.net/2009/02/codesniffer-part-4-how-does-codesniffer-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
