<?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: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/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:rawvoice="http://www.rawvoice.com/rawvoiceRssModule/" version="2.0">

<channel>
	<title>techPortal</title>
	
	<link>http://techportal.inviqa.com</link>
	<description>Techportal for better PHP</description>
	<lastBuildDate>Wed, 08 May 2013 13:19:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
<!-- podcast_generator="Blubrry PowerPress/4.0.8" -->
	<itunes:summary>Techportal for better PHP</itunes:summary>
	<itunes:author>techPortal</itunes:author>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="http://techportal.inviqa.com/wp-content/plugins/powerpress/itunes_default.jpg" />
	<itunes:subtitle>Techportal for better PHP</itunes:subtitle>
	<image>
		<title>techPortal</title>
		<url>http://techportal.inviqa.com/wp-content/plugins/powerpress/rss_default.jpg</url>
		<link>http://techportal.inviqa.com</link>
	</image>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ibuildingstechportal" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="ibuildingstechportal" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Speedy Sites: Building the Stack</title>
		<link>http://techportal.inviqa.com/2013/05/08/speedy-sites-building-the-stack/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=speedy-sites-building-the-stack</link>
		<comments>http://techportal.inviqa.com/2013/05/08/speedy-sites-building-the-stack/#comments</comments>
		<pubDate>Wed, 08 May 2013 13:19:47 +0000</pubDate>
		<dc:creator>Barney Hanlon</dc:creator>
				<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4642</guid>
		<description><![CDATA[In the previous post about speedy sites, we discussed the static assets of a site, and how providing them to users can be optimised through selective use of aggregation and HTML. Let’s move away from considering what to give the user, and instead look at how we provide it to them: the stack. How do [...]]]></description>
				<content:encoded><![CDATA[<p>In the <a href="http://techportal.inviqa.com/2013/03/27/speedy-sites-and-why-you-need-them/" title="Speedy Sites and Why You Need Them" target="_blank">previous post about speedy sites</a>, we discussed the static assets of a site, and how providing them to users can be optimised through selective use of aggregation and HTML. Let’s move away from considering what to give the user, and instead look at how we provide it to them: <strong>the stack</strong>.</p>
<p>How do we define "the stack"? For the purposes of this article, the stack represents everything between the user and the PHP generating the content they see. As with all performance tuning work, you will need to have a sandbox to try out these techniques, and see what works for you. Often this will be a mixture of several technologies, which I affectionately refer to as the <strong>"Speed Sandwich"</strong>, with each layer doing a specific role to improve the overall performance of the user experience, while aiming to limit complexity to a few distinct components. We want to give the end user the page they requested as fast as possible. So how can  we achieve this?<span id="more-4642"></span></p>
<h3>Measuring Stack Performance</h3>
<p>Before we even look at what makes up the stack, we need to think about <strong>benchmarking</strong>. Measuring the effect of your stack on performance is key: indeed, there is no reason to have anything more than the simplest of application servers if we don’t measure performance. Most stacks are a combination of many layers, each with specific tasks and benefits, but these benefits must be weighed against the potential complexity and latency that they themselves add. While TCP communication on the same host is fast, it is not instant (ping is a far simpler communication between machines than HTTP traffic is, and even pinging localhost still takes greater than zero time). This latency adds up (more so if the stack is distributed across many machines), so be sure to measure that the benefits of your stack are still what you believe them to be.  There are many measures you can use for determining stack performance: time to first byte (TTFB), first-byte latency, and page load time are good measures to use, but the reality is that the most important measure will be the end user’s experience, so look at your HAR (HTTP ARchive) record in your browser and see if the user experience is being enhanced or degraded by your choices.</p>
<h3>Core Principles of the Stack</h3>
<p>Before we look at various solutions, we need to identify what we're trying to achieve. Our choices in components will then complement these goals. What are these goals?</p>
<ol>
<li>to serve content fast</li>
<li>to have a robust, fault-tolerant solution</li>
<li>our users should feel safe and have confidence in their data</li>
<li>each component should only deal with the jobs (and traffic) we want them to</li>
</ol>
<p></p>
<p>With these goals in mind, we can move on to consider the responsibilities we need the components of the stack to cover:</p>
<ul>
<li>application server, to serve dynamic pages (in our case, with PHP)
</li>
<li>SSL termination, to protect user data
</li>
<li>static asset serving, for both HTTP and HTTPS traffic
</li>
<li>caching, to decrease both the workload of the application server and the time a user has to wait for a request to be served.
</li>
</ul>
<p></p>
<p>Most modern PHP applications aimed at end users will have all of these responsibilities covered by components within the stack. The question is: which components to use, and how to arrange them in the stack?</p>
<h3>SSL Termination</h3>
<p>Clearly some responsibilities within the stack are immovable: if the site is going to support HTTPS traffic, then you need SSL termination, and for simplicity, it should be the first layer. When we speak of SSL termination, note that we are talking about the successor, Transport Layer Security (TLS), which most browsers support. SSL is an area with lots of considerations and strategies including asymmetric key size, the algorithm chosen, and CPU of the component responsible, and these factors can really hurt performance if overlooked. To learn more about this area, I strongly recommend <a href="http://blog.exceliance.fr/2011/09/16/benchmarking_ssl_performance/">the blog of Baptiste Assman</a>, which covers a lot of the general principles as well as how to benchmark performance. </p>
<p>Before we decide on a component to cover this responsibility, we need to consider our architecture as a whole. Essentially there are two common designs: a single gateway such as an SSL load balancer, or distributed nodes as in a cloud architecture using DNS load balancing. </p>
<figure>
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/05/SSL-termination-load-balanced.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/05/SSL-termination-load-balanced-300x180.jpg" alt="SSL termination - load balanced" width="300" height="180" class="alignnone size-medium wp-image-4648" /></a></p>
<figcaption>
SSL termination with the single gateway model: a load balancer supporting SSL distributes requests upstream via HTTP.<br />
</figcaption>
</figure>
<p>The <strong>gateway model</strong>, where SSL requests are terminated by a single component, has the advantage of having direct communication with the components behind to establish their state. This means it can subsequently add or subtract them from the pool of nodes available to serve requests.  There can be <em>n</em> number of nodes behind this layer awaiting requests, which are now using HTTP, rather than HTTPS, to communicate. There is some overhead between the client and server during SSL handshakes, which can slow down performance. Most components capable of SSL termination have an SSL session cache, which makes subsequent re-negotiations with the client faster if they support TLS. With a single gateway, it is guaranteed that the client will request secure content through the gateway again, making it far more likely that a SSL session (or “ticket” - there is a very good overview of the relevant parlance in <a href="http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html#setting-a-session-cache-with-apache-nginx" target="_blank">this article by Vincent Bernat</a>) can be reused, and thus not require the full handshake again.  Note that when looking at fulfilling responsibilities, a component doesn't have to be a separate and distinct piece of software or hardware within the stack: If you've created a private SSL certificate for a local sandbox instance of Apache, then this is essentially the same: a single piece of your stack is solely responsible for all HTTPS requests (in this case, the mod_ssl Apache module).</p>
<figure>
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/05/SSL-termination-DNS-round-robin.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/05/SSL-termination-DNS-round-robin-300x164.jpg" alt="SSL termination - DNS round robin" width="300" height="164" class="alignnone size-medium wp-image-4647" /></a></p>
<figcaption>Distributed SSL termination: each node is responsible for SSL termination, and load balancing for users is via DNS round robin.<br />
</figure>
<p>In the <strong>distributed stack</strong>, each node handles SSL termination itself, and requests are load balanced by DNS. Each new DNS lookup request is given a different node's IP address, generally by round robin, so that traffic is distributed across the nodes within the pool. This generally scales well: there's no single point of failure as in the gateway model, and it becomes much easier to scale across geographic locations. However, it is less obvious how to remove a failing node out of the pool, so unless rolling out your own DNS service, you are reliant on the implementation of the DNS service provider to define how nodes are added or removed from the pool. Additionally, sessions are “semi-sticky”; most modern browsers will cache the DNS lookup and so return to the previous node, though there is no guarantee that they will. To mitigate the increased latency of creating a new SSL session ticket, there are SSL implementations that support distributing SSL tickets to peers: <a href="https://github.com/bumptech/stud" target="_blank">Stud, the Scalable TLS Unwrapping Daemon</a>, supports passing these tickets to other nodes via UDP, alleviating the overhead of doing this for every single request. </p>
<p>Variants exist between these two models, where there are multiple load balancers responsible for SSL termination for a set pool, and the load balancers themselves are balanced by DNS round robin. Load balancing and SSL termination are not necessarily closely coupled, so the manner of load balancing could be DNS or simple round robin hardware, but at the point you need to know something about the request, you need to terminate. Load balancing with infrastructure without termination does have the disadvantage that sessions cannot be sticky so nodes must either share tickets or the user will suffer performance penalties in handshaking every request. </p>
<p>There are many different implementations for terminating SSL, from a dedicated proxy such as <a href="http://www.apsis.ch/pound" target="_blank">Pound</a> or Stud, to hardware implementations with dedicated accelerator cards, to simply handling this with a Web server. Each solution has its own benefits and drawbacks, so there is no one size fits all implementation. We’ll be looking at the benefits of using SSL for all requests (and the <a href="http://www.chromium.org/spdy" target="_blank">SPDY protocol</a>) in a future article.</p>
<h3>Static Assets</h3>
<p>Unless the Web application is purely an API, there will undoubtedly be static assets that need to be served to the user. Most common lore immediately says "use a Content Delivery Network!", but before running off to find a CDN provider, consider a few things first:</p>
<p>If your site serves HTTPS traffic, then to gain the full padlock icon within the browser requires ALL assets to be served by HTTPS, otherwise end users may be warned that the page contains insecure items. At the very worst, the site may become unusable if pages rely on JavaScript and the browser blocks access due to being insecure and/or from a separate domain. While there are workarounds, it is a situation that can be avoided if the assets themselves are also available via HTTPS. Many CDN providers support serving assets via HTTPS, but there is wildly differing pricing for this, so keep this in mind when shopping around.</p>
<p>It is always worth considering whether a CDN is needed at all. The rationale of using one is largely to do with providing assets to users in separate geographical locales: massively beneficial if hosting a site in London with a large user base in São Paulo, but less useful if the remotest user using the site is in Watford. There's another <a href="http://techportal.inviqa.com/2012/07/09/do-you-need-a-multiregion-website-deployment/" title="Do You Need A Multiregion Website Deployment?" target="_blank">excellent techportal article on multi-region deployments</a> which will help you work out if this would help your application.</p>
<p>A simple and expedient method of providing assets under HTTPS, while also gaining the benefits, is simply to have them served by your standard nodes. Many companies have “vanity domains” that simply redirect traffic to the main domain; these vanity domains could be used to provide asset provisioning (so for example, serving assets for foo.org from foo.org.uk), while requests for the base URL can still redirect browsers to the main site. Again, whether or not to shard content onto separate domains is not a straightforward decision (when we discuss SPDY later, this will become clearer), because of the differences between browsers as to how many parallel pipelines they can support. </p>
<p>Another factor to consider with domain sharding is cookies: these are sent only with requests to the parent domain (so in our example, cookies for foo.org would not be sent to foo.org.uk but would be sent to www.foo.org). With some mobile devices only having upload speeds similar to dial-up, considering how large the request itself is can also be as important as the server response, so it may be better to serve assets from a domain where cookies won't be sent and aren't needed.</p>
<h3>Caching Dynamic Content</h3>
<p>While PHP is sufficiently performant for serving dynamic content, it can become a bottleneck to your users. This is not a weakness in PHP: taking the average Web page, even the fastest super-accelerated C application would be orders of magnitude slower than serving the same content statically. Add in the near-ubiquitous need to communicate with a data persistency, and at high load the application can grind to a halt. There are numerous in-application points that we can cache with a variety of tools such as memcached, Redis or APC, but to use them we've already hit the application layer. Enter <strong>reverse proxies</strong>.</p>
<p>There are a variety of vendors for reverse proxy solutions, but they all essentially work in the same way: dynamic content sits behind (often described as "upstream of") the proxy, and requests are transparently passed to them. If the response from the upstream server is deemed cacheable by the proxy, then it stores a copy (generally in memory) and subsequent requests receive the cached response directly from the proxy cache.</p>
<p>Not only can a reverse proxy save application latency (in that users get content faster), but load across the application itself will also be reduced. While the majority of queries to a persistence layer are generally read (and so lighter than write operations), these can still overwhelm databases, Redis clusters, and memory. If your application is written in a way that is “friendly” to reverse proxies, then not only are these issues alleviated, but the application can actually be improved. </p>
<p>A well-planned integration with a reverse proxy can allow the application to be brought down briefly without the majority of users being aware that the site is completely being served by the proxy, while more ambitious integrations can use the advanced features of reverse proxies that support <a href="http://en.wikipedia.org/wiki/Edge_Side_Includes" target="_blank">Edge Server Includes (ESI)</a>, to effectively “widgetize” their site into separate parts, each with individual lifetimes. This allows a page to consist of a mixture of cached and uncached content without having to only provide uncached content.</p>
<h3>Tripping Up Reverse Proxies</h3>
<p>One of the common pitfalls with reverse proxies is that generally, unless told otherwise, they treat requests with domain cookies appended as uncacheable, regardless of whether the application server needs to use them to produce the response. Generally one of  the first things to configure in a reverse proxy are the rules to ignore all but the most essential cookies, to include as a minimum the one used by your application to keep the user's session ID. However, because sessions are a handy place to store transient data, they can be misused. Session misuse means that slow pages cannot be cached and harms the user experience, but in many cases they are absolutely necessary to ensure user Y sees content designated for them and not private content for user X (a common occurrence when first experimenting with caching is seeing a welcome message with the name of the first developer to log in).</p>
<p>Taking an example of a common session implementation, the problem becomes clear:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// you need to do this to even have the $_SESSION superglobal.</span>
<span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// this causes a session cookie to be generated.</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span>‘user_id’<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>						
<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>There are a few basic ways to fix this issue:</p>
<ul>
<li>Create sessions only when you have to.
</li>
<li>Create sessions lazily, so that they are only created when data is set in them.
</li>
<li>Delete sessions if they contain no data.
</li>
</ul>
<p></p>
<p>Here is an updated snippet that doesn't automatically create a session cookie:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// is the user logged in?</span>
<span style="color: #000088;">$sessionCookieName</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ini_get</span><span style="color: #009900;">&#40;</span>‘session<span style="color: #339933;">.</span>name’<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// slightly faster to read ini_get() than</span>
<span style="color: #666666; font-style: italic;">// session_name() for some reason...</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_COOKIE</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$sessionCookieName</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// clearly with no session cookie, you can’t have a session ID						</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">// they already have a session cookie,</span>
<span style="color: #666666; font-style: italic;">// so creating one is no overhead.</span>
<span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// now check:</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span>‘user_id’<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>In this snippet, by checking for the existence of the session cookie, and then only fire up <code>session_start()</code> if it exists, we avoid the side effect of creating a session if we only want to check a variable.</p>
<h3>The Application Server</h3>
<p>Whatever your personal taste in application server, the core performance increases are in <strong>bytecode optimization and output minification</strong>. In the Doctrine documentation is a great quote by Stas Malyshev, a PHP core contributor:</p>
<blockquote><p>“If you care about performance and don’t use a bytecode cache then you don’t really care about performance. Please get one and start using it.”</p></blockquote>
<p>Whether the bytecode cache is APC, XCache, Zend Opcache in newer versions of PHP, or perhaps the application server is <a href="https://en.wikipedia.org/wiki/HipHop_(computing)" target="_blank">HipHop</a> and the code is precompiled, these solutions can improve performance enormously. Poorly planned <code>include_once</code> and <code>require_once</code> operations can mean a lot of statting the disk, so it is a good practice to try and resolve include paths logically. One approach is to simply run composer with the <code>--optimize-autoloader</code> flag in production, which <strong>turns your PSR-0 classloader into a class map</strong>. Another might be to write your own autoloader that, after resolving a class, caches the resolved path, or even populates a file of includes to be used by the application.</p>
<p>The final part that will help performance is minification; bytes-on-the-wire savings through taking verbose HTML output and removing whitespace, comments and optional elements can be very constructive, especially for mobile users. Whether this is done as an output filter by the application, the application server, or further downstream is a matter of preference, however, if it does behind a caching layer then the overhead is again reduced, as the minified content will be cached and presented to the user without further optimisation required. We’ll be looking at one possible solution, <a href="https://developers.google.com/speed/pagespeed/" target="_blank">Google PageSpeed</a>, in the next article.</p>
<h3>Laying Out The Stack</h3>
<p>After identifying all the responsibilities we want our stack to cover, the temptation is immediately to look at particular solutions to cover these responsibilities, but before we look at those, we need to think about the order of our components.</p>
<figure>
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/05/speedy-sandwich.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/05/speedy-sandwich-300x148.png" alt="speedy-sandwich" width="300" height="148" class="alignnone size-medium wp-image-4662" /></a><br />
</figure>
<p>As already mentioned, some things simply have to happen in a certain order. For our stack it is a fairly obvious sandwich, with SSL termination on the downstream side, and the application server on the upstream side. The choice of whether the layer immediately behind SSL is a Web server or a caching layer depends very much on several factors: if the entirety of static content is served by CDN and all of it is referenced by domain-sharded markup, and you see no need for any post-processing, then there is no advantage in putting the Web server in front of the caching layer. However, if you are looking to do pre- or post-processing, support SPDY, or serve some static elements, then having a Web server in front of the caching layer is a must. A caching layer really should only be concerned with dynamic content, so having the reverse proxy behind a Web server makes sense, as it will only receive requests that by their very nature are for content not servable by the Web server. Additionally, maintaining the caching layer is easier, as the rule sets need not be concerned with static assets at all. Readers familiar with the Varnish reverse proxy may be familiar with statements such as this in the VCL file:</p>
<pre>
if (req.url ~ "(?i)\.(jpeg|jpg|png|gif|ico|swf|js|css|gz|rar|txt|bzip|pdf)(\?.*|)$") 
{
    // ignore because this is a static file....
    return(pass);
}
</pre>
<p>Blocks like these are no longer needed if the static assets are served in front of the cache and only dynamic content can reach the caching layer. Here’s a snippet of an nginx configuration where PHP pages or content not in the docroot are passed upstream:</p>
<pre>
http {
...
	# Address of Varnish server
    upstream _varnish {
        server 127.0.0.1:6081;
    }
}

server {
...

    location / {
        # This is cool because no php is touched for static content.
        try_files $uri @backend;
    }

    # pass all PHP requests upstream
    location ~* \.php$ {
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        proxy_pass http://_varnish;
    }

    # Clearly it doesn’t exist in the docroot, so maybe it’s dynamic.
    # Let’s pass this along to the caching layer
    location @backend {
        proxy_pass http://_varnish;
    }
}
</pre>
<p>With the above Web server in front of the caching layer, you can be fairly certain that the traffic reaching the reverse proxy is for dynamic content. Additionally, we can do some interesting things with post-processing to preserve caching, and this is a topic we'll return to as part of this article series.</p>
<h3>What’s next?</h3>
<p>Hopefully by now you have a clearer picture in your head of the responsibilities that need to be covered by the application stack, and an idea of where in the user request-response flow these need to be addressed. We asked earlier what components we should to address these; the answer to that is very much to do with your own needs and preferences. So in the next group of articles about performance, we’ll look through some possibilities for the application layer, caching layer, and Web layer, starting with Apache and mod_pagespeed.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F&amp;title=Speedy+Sites%3A+Building+the+Stack" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F&amp;title=Speedy+Sites%3A+Building+the+Stack" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F&amp;title=Speedy+Sites%3A+Building+the+Stack" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F&amp;headline=Speedy+Sites%3A+Building+the+Stack" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Speedy+Sites%3A+Building+the+Stack&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Speedy+Sites%3A+Building+the+Stack&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Speedy+Sites%3A+Building+the+Stack&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Speedy+Sites%3A+Building+the+Stack&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Speedy+Sites%3A+Building+the+Stack&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F&amp;title=Speedy+Sites%3A+Building+the+Stack&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F08%2Fspeedy-sites-building-the-stack%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/05/08/speedy-sites-building-the-stack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Functionally Testing Your Application Using Mink</title>
		<link>http://techportal.inviqa.com/2013/05/02/functionally-testing-your-application-using-mink/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=functionally-testing-your-application-using-mink</link>
		<comments>http://techportal.inviqa.com/2013/05/02/functionally-testing-your-application-using-mink/#comments</comments>
		<pubDate>Thu, 02 May 2013 10:49:09 +0000</pubDate>
		<dc:creator>Konstantin Kudryashov</dc:creator>
				<category><![CDATA[Planet PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[behat]]></category>
		<category><![CDATA[mink]]></category>
		<category><![CDATA[quality assurance]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4625</guid>
		<description><![CDATA[Automated testing is big news these days. There's hardly a PHP conference happening without a talk on testing automation or derivative methodologies. TDD (Test-Driven Development) and BDD (Behaviour Driven Development) are all around us. So why should you care about all this? Well, there are many excellent reasons to do automated testing, including assuring application [...]]]></description>
				<content:encoded><![CDATA[<p>Automated testing is big news these days. There's hardly a PHP conference happening without a talk on testing automation or derivative methodologies. TDD (Test-Driven Development) and BDD (Behaviour Driven Development) are all around us. So why should you care about all this? Well, there are many excellent reasons to do automated testing, including assuring application quality and inspiring developer confidence in a system. If you are a business person, you're most likely to care about the quality; if you're a developer then the confidence aspect is more important. The more complex an application becomes, the harder it is to be sure that each new feature or bug fix won't break the system, and that decreases your overall confidence in your work as developer. That's exactly the reason why you need automated testing - <strong>to be confident</strong> that you're not breaking important parts of an application.</p>
<p>Now you're convinced that automated testing is important, but isn't unit testing enough? Unit tests are cheap, fast and small. Why might you want to expand into using a technique such as functional testing? Once again the answer is <strong>confidence</strong>. The more complicated an application becomes, the more complicated the interactions between separate parts of the application become. Just as you can't be confident your car is roadworthy by manually turning each of its wheels independently, you can't be sure that an entire application is working by testing each of its units independently. You need functional testing for complex applications - and today, that's every application.<span id="more-4625"></span></p>
<h3>Silex</h3>
<p><a href="http://silex.sensiolabs.org">Silex</a> is a PHP microframework based on Symfony2 components. It has rapidly become a popular tool in the Symfony2 community thanks to its simplicity and shallow learning curve. That said, the simplicity of Silex does not mean that it is only fit for simple applications, in fact the opposite is true. Some types of application, like <a href="http://en.wikipedia.org/wiki/Rich_Internet_application">RIAs</a> (Rich Internet Applications) are better built with PHP and the minimalism of Silex.</p>
<p>As an application becomes more complex, so it becomes more important to properly test it. Silex provides <a href="http://silex.sensiolabs.org/doc/testing.html#webtestcase">some tools</a> for functional testing using the Symfony2 BrowserKit component. This is useful, but what if some of of the application's functionality requires real HTTP requests to be made? Those could be done using a console browser emulator like <a href="https://github.com/fabpot/Goutte">Goutte</a>. How about if some functions depend on AJAX to behave properly? Using <a href="http://docs.seleniumhq.org">Selenium</a> or even <a href="http://zombie.labnotes.org">Zombie.js</a> could be a good option in that case. </p>
<p>There are two problems with all the solutions mentioned here:</p>
<ol style="list-style-type: decimal">
<li>There's simply no single best choice in terms of browser emulation. Some emulators (BrowserKit, Goutte) are extremely fast, but don't support AJAX. Others (Zombie.js, Selenium) support AJAX but are much slower. In an ideal world, you would want to use multiple emulators at the same time, choosing the best one for each specific case. That leads us to problem #2.</li>
<li>Different browser emulators are written in different languages (PHP, JS, Java), using different libraries and provide extremely inconsistent APIs for developers to work with. That means it is difficult to switch from one emulator to another as it will require all helpers and testing tools be rewritten.</li>
</ol>
<p></p>
<h3 id="mink">Mink</h3>
<p>To help solve some of these problems, a library called <a href="http://mink.behat.org">Mink</a> was written. It was created originally as a complementary tool for <a href="http://behat.org">Behat</a>, but is not tightly coupled to Behat itself and so it can also be used with any framework or tool out there. Mink is a browser emulator abstraction layer - a tool that removes the differences between the various browser emulators and provides one single API through which you can control them all. This essentially means you can switch from browser emulator to browser emulator quite seamlessly as they all use the same PHP API. This article will show you how to use Mink to functionally test an example Silex application using a couple of different browser emulators.</p>
<h3 id="setup">Setting Up</h3>
<p>As our test application we'll use a very simple Silex blog application that is already prepared for you. The code is on github at <a href="https://github.com/everzet/silex-mink">https://github.com/everzet/silex-mink</a> so use that as your starting point.</p>
<h4 id="test-suite-setup">Set Up the Test Suite</h4>
<p>In order to install and integrate Mink, Silex and PHPUnit, some extra entries are needed in <code>composer.json</code>.  The new section should look something like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="yaml" style="font-family:monospace;"><span style="color: green;">&quot;require-dev&quot;</span><span style="font-weight: bold; color: brown;">: </span><span class="br0">&#123;</span><span style="color: green;">
    &quot;phpunit/phpunit&quot;</span><span style="font-weight: bold; color: brown;">: </span>              <span style="color: #CF00CF;">&quot;3.7.19&quot;</span>,<span style="color: green;">
    &quot;behat/mink&quot;</span><span style="font-weight: bold; color: brown;">: </span>                   <span style="color: #CF00CF;">&quot;~1.5&quot;</span>,<span style="color: green;">
    &quot;behat/mink-browserkit-driver&quot;</span><span style="font-weight: bold; color: brown;">: </span> <span style="color: #CF00CF;">&quot;~1.1&quot;</span>,<span style="color: green;">
    &quot;behat/mink-selenium2-driver&quot;</span><span style="font-weight: bold; color: brown;">: </span>  <span style="color: #CF00CF;">&quot;~1.1&quot;</span>
<span class="br0">&#125;</span>,</pre></td></tr></table></div>

<p>These changes ask Composer to install the latest versions of PHPUnit, Mink and couple of Mink drivers in the "dev" environment.  To effect these changes, run the following command:</p>
<p><code>$> php composer.phar update --dev --prefer-dist</code></p>
<p>Drivers are what gives Mink knowledge about different browser emulators (Symfony2 BrowserKit and Selenium, in this case). Mink supports quite a selection of drivers out of the box:</p>
<ul>
<li><strong>BrowserKit</strong> - Symfony2 TestClient driver. Extremely fast headless emulator without isolation or AJAX support.</li>
<li><strong>Goutte</strong> - written in PHP browser emulator. Fast fully isolated headless emulator that doesn't have AJAX support.</li>
<li><strong>Sahi</strong> - <a href="http://sahi.co.in">Sahi.js</a> driver. Extremely slow real browser controller. Has best AJAX support in town.</li>
<li><strong>Selenium2</strong> - <a href="http://seleniumhq.com">Selenium v2</a> driver. Slow real browser controller. Has decent level of AJAX support.</li>
<li><strong>Zombie.js</strong> - <a href="http://zombie.labnotes.org">Zombie.js</a> driver. Fast headless browser emulator with AJAX support. Known to be buggy in some cases.</li>
</ul>
<p>For demonstration purposes, we'll install only the BrowserKit and Selenium2 drivers, however the technique to switch between them is the same for switching to any other Mink driver. </p>
<h4 id="phpunit-setup">PHPUnit setup</h4>
<p>Next step is to create our PHPUnit test configuration. Put inside your <code>phpunit.xml</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phpunit</span> <span style="color: #000066;">backupGlobals</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">backupStaticAttributes</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">colors</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">convertErrorsToExceptions</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">convertNoticesToExceptions</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">convertWarningsToExceptions</span>=<span style="color: #ff0000;">&quot;true&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">processIsolation</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">stopOnFailure</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">syntaxCheck</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">         <span style="color: #000066;">bootstrap</span>=<span style="color: #ff0000;">&quot;vendor/autoload.php&quot;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;php<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;BASE_URL&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;LOCAL_APP_URL&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/php<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;testsuites<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;testsuite</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Silex app test suite&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>./tests/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/testsuite<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/testsuites<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;whitelist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>./src/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/whitelist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phpunit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Nothing really special here, except maybe the <code>BASE_URL</code> server variable. We'll use this in our test cases as this is a test suite environment detail.</p>
<h4 id="base-mink-test-case">Base Mink Test Case</h4>
<p>Now we're ready to start writing the first Mink test case for the Silex app. First let's create a base <code>MinkTestCase</code> class, which can be extended by each of the functional test classes. I put the following code into <code>tests/functional/MinkTestCase.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">use</span> Silex\WebTestCase<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\HttpKernel\Client<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Behat\Mink\Mink<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Behat\Mink\Session<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Behat\Mink\Driver<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> MinkTestCase <span style="color: #000000; font-weight: bold;">extends</span> \PHPUnit_Framework_TestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> static <span style="color: #000088;">$mink</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> setUpBeforeClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">===</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$mink</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$app</span> <span style="color: #339933;">=</span> <span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'../PATH_TO_YOUR/app.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'debug'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'session.test'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$app</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'exception_handler'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">disable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$mink</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Mink<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
                <span style="color: #0000ff;">'silex'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Session<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Driver\BrowserKitDriver<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Client<span style="color: #009900;">&#40;</span><span style="color: #000088;">$app</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'selenium'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">new</span> Session<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Driver\Selenium2Driver<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$mink</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDefaultSessionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'silex'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> teardown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMink</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">resetSessions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> getMink<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$mink</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> getSession<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMink</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> getPage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> assertSession<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMink</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertSession</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The main area of interest at this point is the <code>setUpBeforeClass()</code> method. This method sets up Mink with two preconfigured browser sessions (one Silex, one Selenium) backed by BrowserKit and Selenium2 drivers. We also set a Silex session as the default, which means that when no <code>$name</code> argument is provided to the helper methods, they will work with this exact session.</p>
<p>The other 3 methods are helper methods which will be very useful when writing test cases:</p>
<ul>
<li><code>getSession([$name])</code> returns a Mink <a href="http://mink.behat.org/api/behat/mink/session.html">session object</a>.</li>
<li><code>getPage([$name])</code> returns a session <a href="http://mink.behat.org/api/behat/mink/element/documentelement.html">webpage object</a>.</li>
<li><code>assertSession([$name])</code> returns a session <a href="http://mink.behat.org/api/behat/mink/webassert.html">assertion object</a>.</li>
</ul>
<p></p>
<h3 id="first-test-case">Writing the First Test Case</h3>
<p>With a preconfigured base <code>TestCase</code> class, the first test can now be written. Let's test that we can see and fill in the article form. In my project I added this to <code>tests/functional/ArticleTest.php</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'MinkTestCase.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ArticleTest <span style="color: #000000; font-weight: bold;">extends</span> MinkTestCase
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testThatArticleFormIsAccessible<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'BASE_URL'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">clickLink</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Add article'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$articleForm</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'css'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fieldExists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Title'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$articleForm</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fieldExists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Body'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$articleForm</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Let's work through the code snippet above:</p>
<ol style="list-style-type: decimal">
<li>Visit the application homepage using the <code>Session::visit()</code> method and the <code>BASE_URL</code>.</li>
<li>Find the article form using CSS identifiers, and assign the resulting DOM object to a variable called <code>$articleForm</code>.</li>
<li>Make an assertion that a field with an attribute 'id', 'value', 'label' or 'name' containing 'Title' exists inside the form stored in <code>$articleForm</code></li>
<li>Do the same for a 'Body' field.</li>
</ol>
<p></p>
<p>Now invoke PHPUnit to run the new testcase:</p>
<p><code>$> vendor/bin/phpunit</code></p>
<p>The test completes quickly; this is because by default it runs against the Silex browser session, which uses the BrowserKit driver, which in turn uses the internal Silex TestClient.</p>
<p>Were you expecting something more complicated? Let's add another test case, but this time filling in the fields on the form and checking that a preview area is shown:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testArticlePreview<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">visit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'BASE_URL'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/add-article'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fillField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Title'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Hello Mink!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fillField</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Func testing is fun!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pressButton</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Preview'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">elementTextContains</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'css'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'.preview'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Hello Mink!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">elementTextContains</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'css'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'.preview'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Func testing is fun!'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Again, let's work through the example in order:</p>
<ol style="list-style-type: decimal">
<li>Visit the <code>/add-article</code> page.</li>
<li>Fill the 'Title' field with a value of 'Hello Mink!'.</li>
<li>Fill the 'Body' field with 'Func testing is fun!'.</li>
<li>Then press the 'Preview' button.</li>
<li>Assert that element identified by a specific CSS selector contains some text.</li>
</ol>
<p>Run the entire test suite again:</p>
<p><code>$&gt; vendor/bin/phpunit</code></p>
<p>For completeness we should also test that preview area is hidden by default, which is fairly simple:</p>
<pre>
public function testPreviewIsHiddenByDefault()
{
    $this->getSession()->visit($_SERVER['BASE_URL'].'/add-article');

    $this->assertSession()->elementNotExists('css', '.preview');
}
</pre>
<p>Hopefully the examples have seemed quite straightforward so far.  Perhaps you are wondering though whether this could have been done with a default Silex function test case?</p>
<p>In fact, we can't quite do it with the other tools. One major benefit of Mink is a much cleaner API, which is <strong>consistent across all browser emulators</strong>. This potentially means that both our tests could be checked against different browsers with minimum effort.</p>
<p>Remember that optional <code>$name</code> argument to the helper methods? By providing "selenium" as an argument, it is possible to force Mink to use the Selenium session and Selenium2 driver for each written instruction. Multiple sessions and drivers can be mixed inside a single test case. You can even have multiple sessions using same driver working together to test, for example, a chat application.</p>
<p>For demonstration purposes let's switch all of our test cases to use Selenium2. How? By changing the default session name. Add this to your test class:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMink</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDefaultSessionName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'selenium'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>At this point, you should download and run the Selenium Server JAR <a href="http://selenium.googlecode.com/files/selenium-server-standalone-2.32.0.jar">from the Selenium website</a> and then run the test suite again:</p>
<p><code>$> vendor/bin/phpunit</code></p>
<p>When you run the tests this time, an actual browser (firefox by default) should have opened and performed all the actions in the tests. That's the power of Mink. It works exactly the same way for any Mink driver, such as Zombie.js or Sahi.js.</p>
<p>Are you using Mink?  Would you like to? Tell us what you think in the comments - and happy testing!</p>
<h3 id="further-links">Additional Resources</h3>
<ul>
<li>You can read more about automated testing <a href="http://en.wikipedia.org/wiki/Test_automation">on wikipedia</a>.</li>
<li>Information about Mink can be found on <a href="http://mink.behat.org">official website</a>.</li>
<li>There is documentation for all available Mink methods on the <a href="http://mink.behat.org/api/">Mink API website</a>.</li>
</ul>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F&amp;title=Functionally+Testing+Your+Application+Using+Mink" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F&amp;title=Functionally+Testing+Your+Application+Using+Mink" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F&amp;title=Functionally+Testing+Your+Application+Using+Mink" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F&amp;headline=Functionally+Testing+Your+Application+Using+Mink" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Functionally+Testing+Your+Application+Using+Mink&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Functionally+Testing+Your+Application+Using+Mink&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Functionally+Testing+Your+Application+Using+Mink&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Functionally+Testing+Your+Application+Using+Mink&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Functionally+Testing+Your+Application+Using+Mink&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F&amp;title=Functionally+Testing+Your+Application+Using+Mink&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F05%2F02%2Ffunctionally-testing-your-application-using-mink%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/05/02/functionally-testing-your-application-using-mink/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Conference Report: WhiskyWeb II</title>
		<link>http://techportal.inviqa.com/2013/04/29/conference-report-whiskyweb-ii/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=conference-report-whiskyweb-ii</link>
		<comments>http://techportal.inviqa.com/2013/04/29/conference-report-whiskyweb-ii/#comments</comments>
		<pubDate>Mon, 29 Apr 2013 13:02:12 +0000</pubDate>
		<dc:creator>Marco De Bortoli</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[whiskyweb]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4611</guid>
		<description><![CDATA[After my great experience last year I was eager to attend the second edition of WhiskyWeb and it has to be said that the organisers (in random order, Juozas "Joe" Kaziukėnas, Michael Maclean, Max Manders, Paul Dragoonis and Ben Longden) didn't let me down. The atmosphere was incredible and once again they managed to create [...]]]></description>
				<content:encoded><![CDATA[<p>After my great<a href="http://techportal.inviqa.com/2012/05/09/conference-report-whisky-web/" title="Conference Report: Whisky Web"> experience last year</a> I was eager to attend the second edition of WhiskyWeb and it has to be said that the organisers (in random order, <a href="http://juokaz.com" target="_blank">Juozas "Joe" Kaziukėnas</a>, <a href="http://mgdm.net" target="_blank">Michael Maclean</a>, <a href="http://www.maxmanders.co.uk/" target="_blank">Max Manders</a>, <a href="http://www.ppi.io/" target="_blank">Paul Dragoonis</a> and <a href="http://nocarrier.co.uk/" target="_blank">Ben Longden</a>) didn't let me down.  The atmosphere was incredible and once again they managed to create something really special. <span id="more-4611"></span></p>
<h3>Day One</h3>
<p>The gathering started in front of the Scottish parliament where a crowd of about 100 people slowly grew.  We then got on coaches to Airth castle, how many other conferences can get credited with being held in a Scottish castle?  After some refreshment and the registration process, we got straight into the mood of the conference.</p>
<h3>How Google Builds Web Services (Ian Barber)</h3>
<p>Ian's talk was quite technical and very interesting; it gave fresh perspective on how web services and APIs should be designed and the importance of isolating your core API from third parties. If you have an API you are proud of and you want to share it, consider creating a wrapper for it rather than exposing it as it is. Ian showed how Google failed to avoid coupling the core API feature set to clients requirements in the past, by discussing how products like GData didn’t have the expected success because of lack of consistency, documentation and a common interface. </p>
<p>He then demonstrated how Google are now providing a new API layer on the top of all their services, how it’s been documented, and how everyone can now easily access it via a "discovery file" that describes the APIs.</p>
<h3>Building Better Developers (Rowan Merewood)</h3>
<p>Rowan introduced the crowd to various practices we constantly use here at Inviqa, and he also gave an idea about what we should look for as a developer in order to have fun everyday and keep on enjoying what we do. It’s not the amount of things you know that makes you better but it’s how efficiently you do what you are good at; to improve that, a little bit like an athlete you have to practice, practice and practice. It’s important to realise you work in a team, whether this team is within your company or within the community, so it is better to collaborate than to be a superhero.</p>
<h3>Real Time Web Apps in the Wild (Phil Leggetter)</h3>
<p>I was impressed by the number of use cases and applications running on Pusher and how we can nowadays make the web more immediate where the technology allows us, however I would have expected less of a marketing focus to the talk. I'd have preferred to see a showcase about how to easily implement the Dolphin race game that was demonstrated; this would have been more relevant to the developer audience.</p>
<h3>Identity, responsiveness and the future of the web (Ade Oshineye)</h3>
<p>The last talk of my day and probably one of my favourites of the entire event. Ade is an incredible speaker and I was excited to hear him tell how all these responsive design buzz words are leading us in the wrong direction. He clearly pointed out how developers should stop focusing on the idea of <strong>content</strong>, while they should instead pay more attention to the <strong>context</strong>. While surely content is relevant and important, Ade asked the crowd what a mobile user wants? And the answer is simple: he wants features, features which are beneficial to him having a better service and experience from the service provider. </p>
<h3>Evening Festivities</h3>
<p>After Ade’s talk, in perfect Whisky Web tradition, we then all moved into Airth Castle itself for our whisky tasting masterclass - this year sponsored by Dewar’s. Sadly for me their production specialises on blended whisky while I happen to be an Islay single malt lover, however they were able to impress me with their full cask strength single malt used as base of any of their blends.</p>
<h3>Day Two</h3>
<p>Day two took us back to the centre of lovely Edinburgh.  The event was held within the walls of the beautiful Surgeon’s Hall, the major medical museum in Scotland, considered a museum of national relevance and one of the many tourist attractions in Edinburgh.</p>
<h3>Coming Soon to a Browser Near You (Alan Greenblatt)</h3>
<p>Do you remember the days when Adobe was leading the market when people were talking about interactive online experiences? Things have changed quite a bit since then, but it seems like this amazing company is coming back with some interesting ideas. No more flash this time, simply a pioneering approach to HTML5 and other delights that the W3C is planning for us in the near future. WebSockets is just the beginning of the revolution and Adobe seems to be willing to push the standards; bringing tools to meet our publishing needs into our browsers, offering the ability to shape content with ease and present our website like a press magazine in a way that has been impossible until now. </p>
<p>The down side? These experimental features only work in the latest chrome dev build and not even automatically. Let’s see what will happen in the future!</p>
<h3>Scaling Applications with RabbitMQ (Alvaro Videla)</h3>
<p>If your application needs a focus on performance, scalability, or language-agnostic communication between services, then a message queue system could be your answer - and RabbitMQ possibly one of the best.  What Alvaro highlighted very well during his talk was that having a good messaging queue service in place will help you improve decoupling between your systems.</p>
<p>Decoupling between systems means better load distribution, better control on your streams of information, and also an improved user experience.  For example in a Publisher/Subscriber scenario, the application does not need wait for something to happen since the relevant message will be provided at the appropriate time, allowing me to carry on doing other things without any need to worry.</p>
<h3>3rd Talk: Open Search (Chaitanya Mishra)</h3>
<p>Before I saw this talk, I was aware of OpenGraph by Facebook, but I didn’t know that Facebook plan to release a new feature called Open Search on top of it. Open Search will basically allow people to perform complex queries on any public content stored on Facebook servers using a human-readable language. A simple example, we will be able to type a phrase like “photos of people living in London who are friends of my friends” and this will produce the expected results. The Facebook engineer gave a complete overview of the project, its current status, how they architected the system, and how they solved some of the performance problems they encountered while developing this incredible and amazing feature.</p>
<h3>Closing Keynote (Josh Holmes)</h3>
<p>Josh did a great job last year opening the conference, and this year he did another great job closing the ocnference talking about <em>change</em>. In a different light he once again tried to motivate people to do more, to search for innovation, to experiment, to share ideas, to share credits and fame, as well as failure. At the same time he tried to induct responsibility, and probably the most memorable sentence I took with me out of his talk was “Don’t change just for the sake of it”.</p>
<h3>Wrap Up</h3>
<p>Whisky Web’s organisers wanted to create something different once more and once more they succeeded in their aims.  This year they created a smaller conference with a limited number of available spots to give people a sense of familiarity and to enforce human interactions. One of their goals was “we want you to leave this conference having spoken with everyone” and I think that all the attendees created new connections and strengthened old ones. Many thanks to everyone who made this event happen.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F&amp;title=Conference+Report%3A+WhiskyWeb+II" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F&amp;title=Conference+Report%3A+WhiskyWeb+II" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F&amp;title=Conference+Report%3A+WhiskyWeb+II" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F&amp;headline=Conference+Report%3A+WhiskyWeb+II" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Conference+Report%3A+WhiskyWeb+II&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Conference+Report%3A+WhiskyWeb+II&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Conference+Report%3A+WhiskyWeb+II&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Conference+Report%3A+WhiskyWeb+II&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Conference+Report%3A+WhiskyWeb+II&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F&amp;title=Conference+Report%3A+WhiskyWeb+II&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F29%2Fconference-report-whiskyweb-ii%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/04/29/conference-report-whiskyweb-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Hypermedia API</title>
		<link>http://techportal.inviqa.com/2013/04/24/the-hypermedia-api/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-hypermedia-api</link>
		<comments>http://techportal.inviqa.com/2013/04/24/the-hypermedia-api/#comments</comments>
		<pubDate>Wed, 24 Apr 2013 14:52:07 +0000</pubDate>
		<dc:creator>Ben Longden</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4604</guid>
		<description><![CDATA[As experienced developers we're regularly told that very few API's out there are really RESTful, and sometimes we're even told why and how they could be. But what is the process of actually designing an API that uses hypermedia, and what is hypermedia anyway? This talk takes the listener through the process of designing an [...]]]></description>
				<content:encoded><![CDATA[<p>As experienced developers we're regularly told that very few API's out there are really RESTful, and sometimes we're even told why and how they could be. But what is the process of actually designing an API that uses hypermedia, and what is hypermedia anyway?</p>
<p>This talk takes the listener through the process of designing an API structure up front that uses hypermedia at it's core over HTTP, what considerations do you need when selecting a media type to represent your resource and what is out there to help you document it for others to use. This session is recommended for architects and developers alike and will give a good grounding in writing excellent, self-explanatory Hypermedia APIs.</p>
<p><span id="more-4604"></span></p>
<p>The video below is a recording of Ben's conference talk at PHPUK 2013:</p>
<p><object width="560" height="315"><param name="movie" value="http://www.youtube.com/v/eyiwSePBMUM?hl=en_GB&amp;version=3&amp;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/eyiwSePBMUM?hl=en_GB&amp;version=3&amp;rel=0" type="application/x-shockwave-flash" width="560" height="315" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Video Courtesy of the <a href="http://phpconference.co.uk/about">PHP UK Conference</a> organised by <a href="http://phplondon.org/">PHP London</a></p>
<p>Ben is technical assurance manager at Inviqa (Sheffield). He has many years of professional experience in a variety of programming languages including C, C++, Perl, Python and has been working with PHP for the last 6 years. Throughout his career he has worked at a variety of places in different industries; mobile marketing, data, ISP and in professional services all of which has given him diverse experience of software engineering in different fields.</p>
<p>Outside of work he is a father, and with what little spare time he has left he can be found hacking one of his own projects (lots of ideas, not enough time!), playing on his PS3, or infrequently blogging on techPortal and his own personal blog at <a href="http://nocarrier.co.uk">http://nocarrier.co.uk</a></p>
<p>If you'd like to learn more about the Hypermedia API and creating RESTful applications Ben has devised a training course which gives an in-depth understanding of REST and how to implement it. It covers HTTP, Hypermedia, HATOAS, SOA, and more advanced topics like testability and intermediaries.  <a href="http://inviqa.com/services/get-trained/training-courses/creating-restful-hypermedia-applications/">Creating RESTful Hypermedia Applications</a></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F&amp;title=The+Hypermedia+API" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F&amp;title=The+Hypermedia+API" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F&amp;title=The+Hypermedia+API" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F&amp;headline=The+Hypermedia+API" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=The+Hypermedia+API&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=The+Hypermedia+API&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=The+Hypermedia+API&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=The+Hypermedia+API&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=The+Hypermedia+API&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F&amp;title=The+Hypermedia+API&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F24%2Fthe-hypermedia-api%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/04/24/the-hypermedia-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pair Programming, TDD and Other Impractical Things</title>
		<link>http://techportal.inviqa.com/2013/04/22/pair-programming-tdd-and-other-impractical-things/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pair-programming-tdd-and-other-impractical-things</link>
		<comments>http://techportal.inviqa.com/2013/04/22/pair-programming-tdd-and-other-impractical-things/#comments</comments>
		<pubDate>Mon, 22 Apr 2013 17:38:03 +0000</pubDate>
		<dc:creator>Marcello Duarte</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[Pair Programming]]></category>
		<category><![CDATA[PHP UK Conference]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4585</guid>
		<description><![CDATA["Why should we write our tests first? Isn't that going to slow my development?" "What? Assigning a single task to 2 developers? How is that efficient? What a waste of resources!" "Look, in the perfect world your advice is great, but I have a project to finish here." In this talk Marcello explores efficiency in [...]]]></description>
				<content:encoded><![CDATA[<p>"<em>Why should we write our tests first? Isn't that going to slow my development?</em>"<br />
"<em>What? Assigning a single task to 2 developers? How is that efficient? What a waste of resources!</em>"<br />
"<em>Look, in the perfect world your advice is great, but I have a project to finish here.</em>"</p>
<p>In this talk Marcello explores efficiency in contrast to effectiveness. He looks into how practices, traditionally accepted as efficient, sometimes turn out to be less effective than a few "impractical" things he has come across.</p>
<p><span id="more-4585"></span></p>
<p>The video below is a recording of Marcello's popular conference talk at PHPUK 2013:</p>
<p><object width="560" height="315"><param name="movie" value="http://www.youtube.com/v/XcGlVB7MBos?hl=en_GB&amp;version=3&amp;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/XcGlVB7MBos?hl=en_GB&amp;version=3&amp;rel=0" type="application/x-shockwave-flash" width="560" height="315" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Video Courtesy of the <a href="http://phpconference.co.uk/about">PHP UK Conference</a> organised by <a href="http://phplondon.org/">PHP London</a></p>
<p>Marcello Duarte is the lead developer of PHPSpec and heads the <a href="http://inviqa.com/services/get-trained/">Training at Inviqa</a>. As an agile coach, he's coached many teams in many organisations into Agile processes and development practices like Scrum, TDD, Refactoring, Collaborative Product Ownership and Software Quality.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F&amp;title=Pair+Programming%2C+TDD+and+Other+Impractical+Things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F&amp;title=Pair+Programming%2C+TDD+and+Other+Impractical+Things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F&amp;title=Pair+Programming%2C+TDD+and+Other+Impractical+Things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F&amp;headline=Pair+Programming%2C+TDD+and+Other+Impractical+Things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F&amp;title=Pair+Programming%2C+TDD+and+Other+Impractical+Things&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F04%2F22%2Fpair-programming-tdd-and-other-impractical-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/04/22/pair-programming-tdd-and-other-impractical-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Speedy Sites and Why You Need Them</title>
		<link>http://techportal.inviqa.com/2013/03/27/speedy-sites-and-why-you-need-them/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=speedy-sites-and-why-you-need-them</link>
		<comments>http://techportal.inviqa.com/2013/03/27/speedy-sites-and-why-you-need-them/#comments</comments>
		<pubDate>Wed, 27 Mar 2013 14:25:20 +0000</pubDate>
		<dc:creator>Barney Hanlon</dc:creator>
				<category><![CDATA[Planet PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[optimising]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4552</guid>
		<description><![CDATA[Anyone who went to the PHP Conference 2013 in London hopefully saw Ilia Alshanetsky’s talk on analysing bottlenecks in your application, which had some great techniques for how to test the performance of your site. This article assumes you've taken a look at his slides or are already familiar with Google Chrome’s Developer Tools, so [...]]]></description>
				<content:encoded><![CDATA[<p>Anyone who went to the PHP Conference 2013 in London hopefully saw <a href="http://ilia.ws/archives/265-Bottleneck-Analysis-Slides-from-PHP-UK.html" target="_blank">Ilia Alshanetsky’s talk</a> on analysing bottlenecks in your application, which had some great techniques for how to test the performance of your site. This article assumes you've taken a look at his slides or are already familiar with Google Chrome’s Developer Tools, so you can refer to the Network tab to gain insight into what is happening to your users. Other tools such as <a href="http://yslow.org/" target="_blank">YSlow</a> and <a href="https://www.pingdom.com/" target="_blank">Pingdom</a> will also help in gathering data, though they don’t tell the full story. </p>
<p>What happens though if you complete your analysis and you do have a bottleneck, and it’s going to take a while to fix? Or you have some sluggish legacy code that is a huge lump of technical debt? Fixing sites is hard, and as engineers, we are frequently attracted to the most difficult technical challenges. We want to <em>fix</em> the problem, not <em>mask</em> it. That said, there are many ways we can deal with performance without actually fixing the problem, while keeping users even happier.<span id="more-4552"></span></p>
<h3>Speed vs Performance</h3>
<p>First let’s quantify what we’re talking about here: speed. What is the difference between speed and performance, you may ask?  The core of it is this: you care about performance, but <strong>your users care about speed</strong>. The average consumer of your site does not care how fast or slow your service layer is, nor about the efficiency of your database calls. They simply want to use your site as fast as possible, and an ever-increasing number of them are accessing your site on mobile devices.</p>
<p>Speed is therefore more than just how fast the page loads, but also how fast the user perceives your site to be. So, how do we improve this? Well, there is no single fix that will make your site incredibly fast, although some will have more or less effect than others. It requires a holistic approach of a great many small modifications.</p>
<p class="textcenter"><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/Cycling.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/Cycling-300x199.jpg" alt="Cycling Race" width="300" height="199" class="aligncenter size-medium wp-image-4569" /></a></p>
<p><a href="https://en.wikipedia.org/wiki/Dave_Brailsford" target="_blank">David Brailsford</a> is the Performance Director of the British Cycling team - a team that has come to dominate world cycling, with 65 medals at the London 2012 Olympics, 29 of which were gold. In an interview after the Games, he cited, in addition to crediting the athletes themselves, part of their success to Matt Parker, Head of “Marginal Gains”:</p>
<blockquote><p>"The whole principle came from the idea that if you broke down everything you could think of that goes into riding a bike, and then improved it by 1%, you will get a significant increase when you put them all together"</p></blockquote>
<p><i>(full article: <a href="http://www.bbc.co.uk/sport/0/olympics/19174302" target="_blank">http://www.bbc.co.uk/sport/0/olympics/19174302</a>)</i></p>
<p>This methodology works very well with websites too. What are these marginal gains we can make? They fall broadly into three categories:</p>
<ol>
<li>Give the user what they want (and only what they need).</li>
<li>Give them what they need faster.</li>
<li>Don’t make them ask for it lots of different times if you can give it to them all at the same time.</li>
</ol>
<p></p>
<p>All of this seems fairly straightforward, and some of this has already been covered in the <a href="http://inviqa.com/blog/10-tips-for-improving-website-performance/" target="_blank">post on web performance tips</a> on the main Inviqa blog. There is a another collection of tweaks however, which I guess could be described as “magic” - or more accurately, illusion.</p>
<p>These “sleight of hand” tricks give the illusion of a fast site, even if something is taking a while to do. Recently a friend asked me to put together a website for his cottage industry. He paints miniatures for tabletop wargamers, and he has a level of control with a brush that is simply incredible; I could easily believe he could put makeup on an ant. As you can imagine, his website is very much about showing off his work, and so he has lots of high resolution images of models he has painted. These images are stored on <a href="http://flickr.com" target="_blank">Flickr</a> and displayed via a <a href="http://jquery.com/" target="_blank">jQuery</a> carousel on his front page. </p>
<p>The problem is of course, that these images are huge, and his customers want to see his handiwork right away. You can optimize, crop, and play with the image only so much before a site showing off artwork is soon showing off fuzzy quality images that detract from the message he’s trying to convey. In the end, we put up his favourite image from the set statically on the page, then as soon as enough images were loaded, replaced the image with the carousel, fading in the new content. The effect was that his users believed that the page was loaded extremely quickly, as opposed to waiting for the carousel which would have led to the page taking many seconds to load.</p>
<p>Of course, this isn’t limited to static binary assets for giving the user an illusion of speed. A popular website design is to have a navigation bar across the top of the page, indicating the user is logged in by their username and/or avatar being present. If a user wishes to modify their profile settings, this will mean fetching data from one or more sources to populate the forms. But what do we already have? Well, we can at least populate part of the form with the same details we have present in the navigation already, and then bring in additional details via AJAX. The net result is that the site feels more active to the user, because they have something they can do immediately.</p>
<h3>Don’t Overlook Mobile Connectivity</h3>
<p>These days, when Web developers refer to “responsive” websites, we are referring to <a href="http://en.wikipedia.org/wiki/Responsive_web_design" target="_blank">Responsive Web Design</a>. “Responsive” can also mean reacting or replying quickly or favourably; this becomes more important to consider in design as users of websites increasingly interact via mobile devices.  We tend to forget while working on a laptop with a constant Ethernet or reliable Wifi connection that this is not the user experience of someone out and about on an iPhone. </p>
<p>Emulating the experience of a mobile user is very hard to emulate if your development environment is a VirtualBox instance running on your local machine. Network latency can of course be synthesized (check out our previous post about <a href="http://techportal.inviqa.com/2013/03/05/manipulating-http-with-charles-proxy/" title="Manipulating HTTP with Charles Proxy" target="_blank">Charles</a>), but it isn’t a natural step, and you would want to switch it off when not testing for front end performance. The other downside is that it can give you a marked advantage to your local instance versus assets on a CDN (Content Delivery Network): given a round-trip to get jQuery from your local <code>/js</code> directory, compared to getting it from something like the <a href="https://developers.google.com/speed/libraries/devguide" target="_blank">Google Ajax APIs</a>, Google will seem slower, which is unlikely in reality. As a result of all these factors, I recommend that you get a “playground” - fire up a cloud instance and test performance against that.</p>
<h3>Are Public CDNs Right For You?</h3>
<p>Since I just mentioned the Google Ajax libraries, this is a good time to talk about specifics. A lot of developers immediately assume that if they use Google to provide a library such as jQuery, then you have improved your site loading times. This is possible, and there is also the advantage that Google serves these under both HTTP and HTTPS, allowing you to use the non-scheme-specific URL <code>//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js</code> to get the file. If your site only used this file for JavaScript, all is well, but if not then there is a "gotcha". Let’s take a popular example of an HTML5 boilerplate, <a href="http://www.initializr.com/" target="_blank">initializr</a>. This gives you a responsive layout, <a href="http://twitter.github.com/bootstrap/" target="_blank">Twitter Bootstrap</a>, <a href="http://jquery.com/" target="_blank">jQuery</a> and <a href="http://modernizr.com/" target="_blank">Modernizr</a>, all in one bundle. It’s one of my personal favourites, so let’s look at some (abridged) code:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;!</span>DOCTYPE html<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> lt IE <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>      <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9 lt-ie8 lt-ie7&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> IE <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>         <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9 lt-ie8&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> IE <span style="color: #cc66cc;">8</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>         <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> gt IE <span style="color: #cc66cc;">8</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;&lt;!--&gt;</span> <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!--&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
    <span style="color: #339933;">&lt;</span>head<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>meta charset<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;utf-8&quot;</span><span style="color: #339933;">&gt;</span>
	   …More head tags<span style="color: #339933;">....</span>
        <span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;js/vendor/modernizr-2.6.2-respond-1.1.0.min.js&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
    <span style="color: #339933;">&lt;/</span>head<span style="color: #339933;">&gt;</span>
   <span style="color: #339933;">&lt;</span>body<span style="color: #339933;">&gt;</span>
       …The main body<span style="color: #339933;">,</span> then<span style="color: #339933;">...</span>
        <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!--</span> <span style="color: #339933;">/</span>container <span style="color: #339933;">--&gt;</span>
        <span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
        <span style="color: #339933;">&lt;</span>script<span style="color: #339933;">&gt;</span>window<span style="color: #339933;">.</span>jQuery <span style="color: #339933;">||</span> document<span style="color: #339933;">.</span>write<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;script src=&quot;js/vendor/jquery-1.9.1.min.js&quot;&gt;&lt;\/script&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
        <span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;js/vendor/bootstrap.min.js&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
        <span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;js/plugins.js&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
        <span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;js/main.js&quot;</span><span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
<span style="color: #339933;">...</span>
<span style="color: #339933;">&lt;/</span>body<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>This works well, but you have five JavaScript files being included on this, and probably every other, page: </p>
<ul>
<li><code>modernizr-2.6.2-respond-1.1.0.min.js<br />
</code></li>
<li><code>jquery.min.js</code> from Google’s CDN</li>
<li><code>bootstrap.min.js</code></li>
<li><code>js/plugins.js</code></li>
<li><code>js/main.js</code></li>
</ul>
<p></p>
<p>As these are across two domains, that’s two DNS lookups and six requests (one for the page itself, five for the JavaScript alone, and we haven’t touched CSS yet). Compare this with creating an <code>init.js</code> file with all of these files combined, it becomes one DNS lookup (which the browser has already done, to find the page) and two requests (again, including the page). In such a circumstance, is it worthwhile using the Google CDN? You could of course combine just the local files together, resulting in two DNS lookups and three file requests, but you need to actually play around to see which works for you (read <a href="http://techportal.inviqa.com/2012/07/09/do-you-need-a-multiregion-website-deployment/" title="Do You Need A Multiregion Website Deployment?" target="_blank">Adam's post on multiregion deployments</a> for examples on how to establish what works best). </p>
<p>There's a common misconception that, by using jQuery directly from Google, there is a greater chance of it being already cached in the browser from visiting a previous site, and that the browser will have already done the DNS lookup. However, as most sites want to link against a particular version of jQuery for stability, this can mean dozens of minor versions. Additionally, Mobile Safari doesn’t persist cache over application restart, so the chances are smaller than you might initially assume.  Relying on your user already having done something elsewhere is not a strategy to rely on for performance, so always test your assumptions in your playground.</p>
<h3>Prefetching Domains</h3>
<p>While browsers are getting better at preprocessing HTML to gather domains referenced in the HTML ahead of schedule, not all of them are, and there also cases where content is dynamically loaded in from another domain. In the earlier example, an API feed from Flickr was consumed, and then the images were displayed directly into the carousel. When the browser comes across this API feed (and subsequently the images, as they are static files and only the information on how to concoct their URL comes from <a href="http://api.flickr.com" target="_blank">api.flickr.com</a>) it has to do a DNS lookup, adding typically 10-30ms to each request. Taking the worst case, that’s 30ms to get the API feed, and another 30ms to get the IP of whichever static farm the image is hosted on!  Adding 60ms to the lookup time is something that can be avoided, however. Let a browser know that somewhere on this page you will need content from a particular domain by using <code>dns-prefetch</code> tags just after the opening <code>&lt;head&gt;</code> tag:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span><span style="color: #990000;">link</span> rel<span style="color: #339933;">=</span>dns<span style="color: #339933;">-</span>prefetch href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;//ajax.googleapis.com&quot;</span><span style="color: #339933;">/&gt;</span></pre></td></tr></table></div>

<p>This tells browsers that support dns-prefetching that they should, in parallel, look up the domain specified because it will be needed at some point. This prevents DNS blocking when fetching assets. There is <a href="http://www.mobify.com/dev/domain-sharding-bad-news-mobile-performance/" target="_blank">some debate as to whether domain sharding is still a good technique</a>, but if you use it, then prefetching will also speed up browsers if the asset domains are completely separate. The issue is muddied by more recent browsers ignoring the RFCs on <a href="http://en.wikipedia.org/wiki/HTTP_pipelining" target="_blank">HTTP pipelining</a>, so again, test your assumptions.</p>
<h3>Using JavaScript Passively</h3>
<p>So far the DNS lookup times have been improved, one large file has been created that has all of the site-generic JavaScript in it. Two questions then: </p>
<ul>
<li>how do we manage this file and dependencies</li>
<li>how do we use it?</li>
</ul>
<p></p>
<p>It is common practice to place the JavaScript includes right before the closing <code>&lt;/body&gt;</code> tag, or at least add <a href="http://caniuse.com/script-defer" target="_blank"><code>defer</code> </a>or HTML5’s <a href="http://caniuse.com/script-async" target="_blank"><code>async</code></a> attributes:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;script async src=&quot;foo.js&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>However, we want to also put JavaScript throughout the body of our page, and the techniques covered so far don’t deal with dependencies, only with loading the library in a non-blocking way. If we think of a simple Bootstrap page with three columns, and we want the leftmost column to contain the latest Tweets from our Twitter account, then the JavaScript to initialise this is best placed within the block. As we widgetize our sites more and more, we want to write small, easily-reusable components, and that means that we have JavaScript within the same logical block as the element that it relates to. If this application uses a templating engine that is aware of placeholders, we could append this block to the bottom of the page, but we still have a dependency: the library we are relying on must be present.</p>
<p>Most of the time we work on the premise that if we put a library like jQuery in the <code>&lt;head&gt;</code>, it is hopefully there by the time we use <code>$(document).ready()</code>. In browsers that block while loading JavaScript in the <code>&lt;head&gt;</code>, this is guaranteed, but in that case, any further page processing is blocked until the file is available. More and more browsers are behaving better when getting elements referenced in the head of HTML, so it is increasingly likely that the library is there when it is needed. However, with 3G mobile devices having an <a href="http://www.broadbandgenie.co.uk/mobilebroadband/help/how-fast-is-mobile-broadband-a-guide-to-3G-broadband-speed" target="_blank">average connection speed of under 2Mb</a>, this is never a certainty, especially if your first use of it is early in the body of the page.</p>
<p>We need to defer until at least the core dependencies are in place. Let’s take a look at some code, modifying again our initializr template.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;!</span>doctype html<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> lt IE <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9 lt-ie8 lt-ie7&quot;</span> lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;en&quot;</span> xmlns<span style="color: #339933;">:</span>fb<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;http://ogp.me/ns/fb#&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> IE <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>    <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9 lt-ie8&quot;</span> lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;en&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> IE <span style="color: #cc66cc;">8</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>    <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js lt-ie9&quot;</span> lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;en&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">&lt;!--</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">if</span> gt IE <span style="color: #cc66cc;">8</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;&lt;!--&gt;</span> <span style="color: #339933;">&lt;</span>html <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;no-js&quot;</span> lang<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;en&quot;</span><span style="color: #339933;">&gt;</span> <span style="color: #339933;">&lt;!--&lt;!</span><span style="color: #009900;">&#91;</span><span style="color: #b1b100;">endif</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--&gt;</span>
    <span style="color: #339933;">&lt;</span>head<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>meta charset<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;utf-8&quot;</span> <span style="color: #339933;">/&gt;</span>
        <span style="color: #339933;">&lt;</span><span style="color: #990000;">link</span> rel<span style="color: #339933;">=</span>dns<span style="color: #339933;">-</span>prefetch href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;//ajax.googleapis.com&quot;</span><span style="color: #339933;">/&gt;</span>
        <span style="color: #339933;">&lt;</span>script<span style="color: #339933;">&gt;</span>
        	<span style="color: #000000; font-weight: bold;">var</span> tp <span style="color: #339933;">=</span> window<span style="color: #339933;">.</span>tp <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
        	tp<span style="color: #339933;">.</span>fn <span style="color: #339933;">=</span> tp<span style="color: #339933;">.</span>fn <span style="color: #339933;">||</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #990000;">Array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
    <span style="color: #339933;">&lt;!--</span> rest of head from initializr<span style="color: #339933;">--&gt;</span>
    <span style="color: #339933;">...</span>
    <span style="color: #339933;">&lt;/</span>head<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>What is happening here? The script is creating a small JavaScript object called <code>tp</code> (for TechPortal), and defensively checking to see if it already exists, in case this script is being included in the page in an unexpected way (such as Lightbox, or an Ajax call). We also give it a property, <code>fn</code>, which is an array to hold callbacks. </p>
<p>Now let's add a JavaScript call to the page. The earlier example was a Twitter feed, so let’s assume we have a file, <code>tweets.js</code>, which requires the jQuery UI library. I’m basing this example on the <a href="http://tweet.seaofclouds.com/" target="_blank">Sea of Clouds Twitter widget</a>, with some additional jQuery UI functionality thrown in. Our template requires Modernizr to work properly, so we’ll simply use the built-in Modernizr loader, which is based on <a href="http://yepnopejs.com/" target="_blank">yepnope</a>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span>”tweets” <span style="color: #000000; font-weight: bold;">class</span><span style="color: #339933;">=</span>”span3”<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>script<span style="color: #339933;">&gt;</span>
    tp<span style="color: #339933;">.</span>fn<span style="color: #339933;">.</span>push<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        Modernizr<span style="color: #339933;">.</span>load<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span>
      load <span style="color: #339933;">:</span><span style="color: #009900;">&#91;</span>
            <span style="color: #0000ff;">'//ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js'</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'/js/vendor/tweet/tweet.min.js'</span>
      <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      complete<span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          $<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;#tweets&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>tweet<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
              join_text<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;auto&quot;</span><span style="color: #339933;">,</span>
              username<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;techportal&quot;</span><span style="color: #339933;">,</span>
              avatar_size<span style="color: #339933;">:</span> <span style="color: #cc66cc;">48</span><span style="color: #339933;">,</span>
              <span style="color: #990000;">count</span><span style="color: #339933;">:</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span>
              auto_join_text_default<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span>
                auto_join_text_ed<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span>
                auto_join_text_ing<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span>
                auto_join_text_reply<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span>
                auto_join_text_url<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">,</span>
                loading_text<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;loading tweets...&quot;</span><span style="color: #339933;">,</span>
                refresh_interval<span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Here, an anonymous function is appended to the <code>fn</code> array, and <code>Modernizr.load()</code> is used to retrieve the dependencies. Once these have been loaded, the tweets are then initialised, targeting the named <code>&lt;div&gt;</code>. However, this code won’t actually do anything just yet, because it is simply a function, and nothing has called it.</p>
<p>Let’s create a file called <code>init.js</code>. We’re going to use this file on every single page of the site, so we’ll prepend <a href="https://en.wikipedia.org/wiki/Minification_(programming)" target="_blank">minified</a> jQuery and Modernizr to it to reduce requests:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// init.js</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Modernizr and jQuery go here...</span>
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #006600; font-style: italic;">// we know that jQuery is loaded as it is prepended, and now we know</span>
	<span style="color: #006600; font-style: italic;">// that everything else is ready to go too.</span>
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">tp</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #000066; font-weight: bold;">in</span> tp.<span style="color: #660066;">fn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #006600; font-style: italic;">// iterate through all the stored functions...</span>
      		<span style="color: #000066; font-weight: bold;">var</span> fn <span style="color: #339933;">=</span> tp.<span style="color: #660066;">fn</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #006600; font-style: italic;">// and then execute them....</span>
            fn<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>And now we append this to our example page:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;!--</span> cover all bases and <span style="color: #000000; font-weight: bold;">use</span> both async and defer attributes →
<span style="color: #339933;">&lt;</span>script src<span style="color: #339933;">=</span>”<span style="color: #339933;">/</span>js<span style="color: #339933;">/</span>init<span style="color: #339933;">.</span>js” async defer<span style="color: #339933;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script&gt;</span>
<span style="color: #339933;">&lt;/</span>body<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>html<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>

<p>Using this method, we ensure that there are no blocking or dependency issues for the JavaScript on page load, while also allowing us to have libraries available without having to have advance knowledge of every single widget on a page. The page will load without needing any JavaScript until it reaches the closing <code>&lt;/body&gt;</code> tag, then call in the site-wide Modernizr and jQuery libraries in one file, reducing requests and DNS lookups. After that, it will iterate through all the page-specific JavaScript and sort out any dependencies as necessary, and finally execute any additional functionality nested within these latent functions.</p>
<p>We could also add into <code>init.js</code> all of our bootstrap and responsive files as well, although if there is a lot of HTML on the page, it may take a while before the browser reaches the tag to include it, which could leave the site looking odd for a second or two until the responsive elements are brought in. In which case, experiment with placing it in the <code>&lt;head&gt;</code>, keeping the <code>defer</code> and <code>async</code> attributes, and see how performance is affected by this change.</p>
<p>As the loop to call the anonymous functions is wrapped inside jQuery’s <code>$(document).ready()</code> event handler, it should still gracefully wait until the page is loaded. </p>
<h3>Test, Test, and Test Again</h3>
<p>You should (with effective analytics and logging) have an idea which browsers and devices are being used by your users, and be able to test to target these. Other considerations could include whether <code>tweets.js</code> is the only library that needs jQueryUI; if so, is there a benefit to having the two libraries separate, or instead combining them into one file with jQueryUI prepended? If there are only a few libraries like this, all using jQueryUI, another option is having a <code>libraries.js</code> file where all the libraries live, or including jQueryUI in the site-wide <code>init.js</code>, or simply having all of the JavaScript inside <code>init.js</code>. Again, test to see what works for you, and more importantly, your users.</p>
<p>This also applies to CSS files as well: you need to find what works for a specific application. A really handy tool for concatenating and managing CSS, <a href="http://lesscss.org/" target="_blank">LESS</a> and JavaScript is <a href="http://incident57.com/codekit/" target="_blank">CodeKit</a>. It watches your project folder and then automatically generates aggregated files. With it, I can easily choose to prepend or append libraries, process LESS files and output CSS, and also choose to minify the output if I wish. This means I don’t have to worry about writing my custom JavaScript and CSS files in a minified way: I simply have the files in a resources directory, and tell CodeKit to output the files into the <code>/js</code> and <code>/css </code>folders in my <code>html</code> directory. It also has the <a href="http://yui.github.com/yuicompressor/" target="_blank">YUI Compressor</a> and <a href="http://www.jslint.com/" target="_blank">JSLint</a> built-in, allowing you to produce very small aggregate files and also avoid obvious parsing issues in your aggregated JavaScript libraries. CodeKit isn’t free, but I find the licence fee worth it for the time it saves me. Alternatively, you can use <a href="http://nodejs.org/" target="_blank">node.js</a> and have the compilation of your LESS files and JavaScript validation as part of your build process. </p>
<p>In my next article, I’ll be looking beyond optimising the HTML and static assets of the page and look at how we can optimise the stack to improve delivery of your pages.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F&amp;title=Speedy+Sites+and+Why+You+Need+Them" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F&amp;title=Speedy+Sites+and+Why+You+Need+Them" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F&amp;title=Speedy+Sites+and+Why+You+Need+Them" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F&amp;headline=Speedy+Sites+and+Why+You+Need+Them" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Speedy+Sites+and+Why+You+Need+Them&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Speedy+Sites+and+Why+You+Need+Them&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Speedy+Sites+and+Why+You+Need+Them&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Speedy+Sites+and+Why+You+Need+Them&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Speedy+Sites+and+Why+You+Need+Them&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F&amp;title=Speedy+Sites+and+Why+You+Need+Them&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F27%2Fspeedy-sites-and-why-you-need-them%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/03/27/speedy-sites-and-why-you-need-them/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PHPNE 2013 Conference Report</title>
		<link>http://techportal.inviqa.com/2013/03/22/phpne-2013-conference-report/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=phpne-2013-conference-report</link>
		<comments>http://techportal.inviqa.com/2013/03/22/phpne-2013-conference-report/#comments</comments>
		<pubDate>Fri, 22 Mar 2013 11:12:52 +0000</pubDate>
		<dc:creator>Adam Smith</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[phpne13]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4531</guid>
		<description><![CDATA[As a native geordie I was pleased to have a chance to attend a PHP conference in the north east. Even after living in Manchester for nearly a decade now, Newcastle still feels like home. Despite the nostalgia of revisiting the Tyneside Cinema for the first time in many years, I was a little apprehensive [...]]]></description>
				<content:encoded><![CDATA[<p>As a native geordie I was pleased to have a chance to attend a PHP conference in the north east.  Even after living in Manchester for nearly a decade now, Newcastle still feels like home.  Despite the nostalgia of revisiting the Tyneside Cinema for the first time in many years, I was a little apprehensive about it's suitability as a conference venue – I couldn't help but recall the regular disturbances to films watched there, caused by the noisy metro line passing underneath the building.  I'm pleased to report that I was wrong to doubt the choice, the venue and staff were excellent throughout as we took over both the third and fourth floors of the building.</p>
<p>I arrived in plenty of time to enjoy the complimentary bacon sandwich and coffee on offer before finding some faces I recognised and settling in to the Electra Room where the main track was due to start, with Inviqa's very own Rowan Merewood taking to the stage to deliver the opening keynote.<span id="more-4531"></span></p>
<h3><a href="http://conference.phpne.org.uk/schedule/#rowan" target="_blank">Rowan Merewood</a></h3>
<p><em>Building Better Developers</em><br />
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/rowan.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/rowan-300x187.jpg" alt="rowan" width="300" height="187" class="aligncenter size-medium wp-image-4538" /></a></p>
<p>After starting his presentation by pronouncing himself a tool, Rowan went on to highlight a number of key aspects to being a good and productive developer.  Luckily for him, he was speaking to an audience who appreciate their tools and the content was well received.  The huge cinema screen was a little odd at first, but once you'd gotten acclimatized it was a good addition to proceedings – I only hope it hasn't ruined my enjoyment of future conferences where such impressive AV equipment is not available.  Every time Rowan added a new body part to his dream colleague it came with a twitter friendly summary, many of which did make it to twitter soon after - “Being passionate and authoritative is not the same as being an angry asshole” was one of my favourites.
<p>Thanks to a prompt start there was plenty of time to decide what to go and see next, I decided I was going to head to track two.  As I arrived it seemed many others had the same idea and I found myself taking the last available seat.</p>
<h3><a href="http://conference.phpne.org.uk/schedule/#alex" target="_blank">Alex Bilbie</a></h3>
<p><em>API Driven Development: Eating Your Own Dog Food</em></p>
<p>Despite some minor technical hitches with the microphone, Alex Bilbie spoke confidently about some of the work he has been doing at Lincoln University.  There were some good insights on why we should both develop well designed APIs, and then actually use them ourselves - if it's good enough for your clients, it's good enough for you, right?  The content was kept quite high-level throughout and I actually took more from some of the periphery topics mentioned than the main topic, but I did enter the room already sold on the concept.  I came out with a note to investigate Swagger for documenting my next API and Alex was also the first of the day to talk about measuring metrics and building dashboards, a topic that would recur throughout the event.</p>
<h3><a href="http://conference.phpne.org.uk/schedule/#bastian" target="_blank">Bastian Hofmann</a></h3>
<p><em>Measuring and Logging Everything in Real Time</em></p>
<p>A quick dash up the stairs back to track one to watch Bastian Hoffman talk about logging.  I'd done some reading around Graylog2 based on an aside during a talk at the PHPNW conference but was yet to use it in anger, so I was pleased to hear more on the subject.  Many more tools for me to investigate were introduced, including StatsD and Logstash which can, if used all together, create a robust centralised logging solution.  Of course we mustn't forget that after collecting all this data we need a good way to see it.  Creating yourself a dashboard using Graphite gives a great way to do just that.  Bastian's suggestion to add a unique id to error messages to make it possible to identify the specific instance of what went wrong, when and which requests were related to it sounds so obvious now that I wonder why I haven't been doing it for years.</p>
<h3>Lunch</h3>
<p>Time for lunch and an unexpected surprise as everyone was handed a black plastic PHPNE branded lunchbox containing a sandwich, crisps and a variety of sweet treats.  I've not seen this done before at a conference, and it seemed to go down pretty well.  The lack of chairs added to the unusual lunch choice, as many of us sat on the floor and ate our sandwiches in scenes more akin to a summer picnic than a PHP conference.  It was also during lunch that I discovered a personalised mug had been provided for me, and every other attendee, by one of the sponsors – another unexpected little bonus.</p>
<h3><a href="http://conference.phpne.org.uk/schedule/#fabrice" target="_blank">Fabrice Bernhard</a></h3>
<p><em>Modernisation of legacy PHP applications using Symfony2</em></p>
<p>First up after the break was Fabrice Bernhard talking about upgrading legacy apps.  Many of the points here were useful, but it did feel at times like a marketing pitch.  It also seemed unnecessary to have included Symfony2 in the title, as most of the talk was around techniques and considerations for upgrading rather than the technical detail of implementation.  Nonetheless the concepts were sound and the key message to upgrade legacy code module by module rather than a complete rewrite from scratch makes a lot of sense.  The asides were interesting too, another mention for measuring business metrics and dashboards along with promoting the idea of regular deployments, regular here meaning many times a day, not the fortnightly or even monthly release cycles often seen in agile projects.</p>
<p>My decision to stay in track one for the next talk meant I had now committed to my chair for another two hours and I was certainly pleased with the cinema seating at this point, a lesser seat may have had me more concerned about the time ahead.</p>
<h3><a href="http://conference.phpne.org.uk/schedule/#lukas" target="_blank">Lukas Kahwe Smith</a></h3>
<p><em>Introduction to Symfony CMF</em></p>
<p>Despite being an official sub-project of Symfony I have to admit I had no knowledge of the Symfony CMF before this session.  I was pleased to be introduced to it as it looks like an excellent option for any developer who needs to customise a content management system.  Lukas was very accomodating to the crowd and even offered a choice of showing slides, a demo or the code.  With only one hand raised for slides and a split between the other two options, we were treated to a quick overview of the system and a little bit of code.  I came away eager to get a chance to play with some of the features and hope that going forward the project will catch on, as it looks a far nicer system for developers to work with than some of the CMS systems I've come across.</p>
<h3><a href="http://conference.phpne.org.uk/schedule/#thijs" target="_blank">Thijs Feryn</a></h3>
<p><em>Keeping The Cloud In Check</em><br />
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/thijs.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/thijs-300x225.jpg" alt="thijs" width="300" height="225" class="aligncenter size-medium wp-image-4544" /></a></p>
<p>To close the day, Thijs gave a well judged closing keynote about “the cloud”, or as he put it “the internet”.  Lots of amusing anecdotes helped sell his message, his insistence that nobody tweet the stories suggests that they may well be true too.  The core message throughout was that there is no silver bullet solution to high availability and scaling problems, and the fact that many people believe “the cloud” will solve all of their problems is in itself a real problem.</p>
<h3>Wrapping up</h3>
<p>The post-talk conference giveaways were interestingly executed, as the winner of each prize was selected by a php script, not in itself a complicated idea, but it added to the event nicely.  Finally, after a quick word from the sponsors and some difficulties operating a mac, which entertained the delegates enough that part of me wonders if they were scripted, everyone was given a free t-shirt as they left the Tyneside cinema to add to the goodies that had already been showered upon us throughout the day.</p>
<p>After heading out for some food I ended up back at the post-conference social, where a sponsored bar was in full force.  Given that the money behind the bar did not run out until gone 1AM, I feel little should be said about the events of the social, other than I had some interesting conversations and I am appreciative to the organisers and sponsors for a very enjoyable day and night.  I took something from every talk and I don't really have a bad word to say about any of it.  I hope this does not end up as the only PHPNE, it is only a shame that next year a new venue will likely need to be found as I expect demand for tickets will be high.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F&amp;title=PHPNE+2013+Conference+Report" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F&amp;title=PHPNE+2013+Conference+Report" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F&amp;title=PHPNE+2013+Conference+Report" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F&amp;headline=PHPNE+2013+Conference+Report" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=PHPNE+2013+Conference+Report&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=PHPNE+2013+Conference+Report&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=PHPNE+2013+Conference+Report&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=PHPNE+2013+Conference+Report&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=PHPNE+2013+Conference+Report&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F&amp;title=PHPNE+2013+Conference+Report&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F22%2Fphpne-2013-conference-report%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/03/22/phpne-2013-conference-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips for Developing Apps with PhoneGap</title>
		<link>http://techportal.inviqa.com/2013/03/20/tips-for-developing-apps-with-phone-gap/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tips-for-developing-apps-with-phone-gap</link>
		<comments>http://techportal.inviqa.com/2013/03/20/tips-for-developing-apps-with-phone-gap/#comments</comments>
		<pubDate>Wed, 20 Mar 2013 14:03:55 +0000</pubDate>
		<dc:creator>Amy Benson</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4511</guid>
		<description><![CDATA[Over the last few months at Inviqa we've been developing our first two mobile apps – BNY Mellon Boat Race, a rowing app for iPhone and Android, and another app just for iPhone. We chose to use PhoneGap to build the apps as the idea of developing once and deploying to multiple platforms is very [...]]]></description>
				<content:encoded><![CDATA[<p>Over the last few months at Inviqa we've been developing our first two mobile apps – <a href="http://whichblueareyou.com/phoneapp" target="_blank">BNY Mellon Boat Race</a>, a rowing app for iPhone and Android, and another app just for iPhone. We chose to use <a href="http://phonegap.com" target="_blank">PhoneGap</a> to build the apps as the idea of developing once and deploying to multiple platforms is very appealing and since we're web developers, HTML, CSS and Javascript are what we know best. There has been a lot of debate recently about using frameworks like PhoneGap versus building native apps, but PhoneGap has worked well for us and I'd happily use it again.</p>
<p class="textcenter">
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/rowing.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/rowing-300x163.jpg" alt="rowing" width="300" height="163" class="alignnone size-medium wp-image-4512" /></a></p>
<p>Building these apps has been a learning process for us so I thought it might be useful to share some of things I’ve learned along the way.<span id="more-4511"></span></p>
<h3>Test on Real Phones</h3>
<p>In the world of iOS, things aren’t too bad, using Xcode and the iPhone emulator is fairly realistic.  Even then however, there may be some nasty surprises if testing on real devices is left to the end of the project. For example, you might find that your animation looks great on the emulator but is painfully slow on an iPhone 3GS.  Some features can't be emulated; for example if your app uses the accelerometer then there’s no way to emulate it (you can try shaking your laptop but it won’t get you very far).</p>
<p>When it comes to Android there’s a huge set of different challenges.  The emulator is often slow, unresponsive and frequently flaky when using it to run the app with Eclipse.  Consequently I used it very rarely for testing.  Luckily deploying an app to real devices during development using Eclipse and the Android SDK is straightforward, and unlike iOS there is no requirement to have developer accounts to test your apps.</p>
<p>How does a project decide which devices and versions of Android to test on? There are a plethora of devices out there and the potential combinations of devices and Android versions is huge.  It would be impossible to test on all of them, but as a minimum it is best to aim for at least one of each of the main screen sizes, so something fairly old and small like a HTC Wildfire, a medium size one such as a Samsung Galaxy S2, and a large one like a Nexus 4.  This only scratches at the surface of the range of devices available, so the best thing to do is agree with the client on which devices and Android versions will be used for testing, and always make sure this includes the phone they use.</p>
<h3>CSS3 and HTML5</h3>
<p>One of the nice things about working on mobile apps is that you can use CSS3 and HTML5 without having to worry about providing fallbacks  There will be no need for HTML5 shivs, no images pretending to be gradients, or workarounds for Internet Explorer.  Sadly that doesn't mean everything will work exactly as you expect, here are a few things that might trip you up:</p>
<ol>
<li>Some CSS3 properties can affect performance, box-shadow is especially bad for this, so if your animations are looking choppy try removing any box-shadows, it may help.</li>
<li>3D CSS3 animations are hardware accelerated, but you can trick it into using hardware acceleration on 2D animations by adding:

<div class="wp_syntax"><table><tr><td class="code"><pre class="css" style="font-family:monospace;">-webkit-transform<span style="color: #00AA00;">:</span> translate3d<span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span>
transform<span style="color: #00AA00;">:</span> translate3d<span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">,</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span></pre></td></tr></table></div>

</li>
<li>Bear in mind that while many CSS3 properties no longer require prefixes, these may still be needed for earlier versions of Android and iOS. For example <code>box-shadow</code> requires the <code>-webkit</code> prefix in Android up to version 4 and iOS up to version 5. The ever-helpful <a href="http://caniuse.com" target="_blank">http://caniuse.com</a> includes mobile browsers in its compatibility tables. It's also worth noting that older versions may use different syntax for background gradients, but generators such as <a href="http://www.colorzilla.com" target="_blank">http://www.colorzilla.com</a> can provide these for you.</li>
</ol>
<p></p>
<h3>jQuery Mobile</h3>
<p><a href="http://jquerymobile.com" target="_blank">jQuery mobile</a> can be very useful and time-saving when developing apps as it’s easy to use and well documented.  From a front end point of view the ability to just be able to specify the desired transition directly on a link is great, it looks something like:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;a href=&quot;index.html&quot; data-transition=&quot;slidedown&quot;&gt;</pre></td></tr></table></div>

<p>However, where we found problems was when you need to have more control over the look and feel of your app. On another app we ended up removing jQuery mobile, writing our own page loader and spending time creating and tweaking a flip animation to get it to fit the client’s requirements exactly.</p>
<h3>Handy Tips, or "Things that took far too long to find by Googling"</h3>
<p>Renaming your App:</p>
<ol>
<li><strong>Android</strong>: Edit the <code>app-name</code> in <code>[project-folder]/android/[project]/res/values/strings.xml</code></li>
<li><strong>iOS</strong>: In xCode, select your project under Targets, then in the Info tab update the Bundle display name</li>
</ol>
<p></p>
<p>Force the phone to show the app in landscape mode:</p>
<ol>
<li><strong>Android</strong>: In <code>[project-folder]/android/[project]/AndroidManifest.xml</code> add <code>android:screenOrientation="landscape"</code> to the activity tag</li>
<li><strong>iOS</strong>: In xCode, select your project under Targets, In the Summary tab make sure that either Landscape Right or Landscape Left is selected and the Portrait ones are not selected.</li>
</ol>
<p></p>
<p>Hide the phone status bar while the app is running:</p>
<ol>
<li><strong>Android</strong>: In <code>[project-folder]/android/[project]/res/xml/config.xml</code> add <code></code></li>
<li><strong>iOS</strong>: In xCode, select your project under Targets, In the Summary tab select Visibility - Hide during application launch in the Status bar section.</li>
</ol>
<p></p>
<p>Opening external links in the in-app browser:</p>
<p>Without this a user can click on an external link in your app, and then can’t get back to the app, luckily the current version of PhoneGap comes with InAppBrowser which you can use with the <code>window.open</code> call.  For example, you can open a URL using a command like:</p>
<pre>
onClick="window.open('http://google.com', '_blank', 'location=yes');"
</pre>
<p><br/></p>
<h3>Developing with PhoneGap</h3>
<p>This has only been a brief overview of the learning process we have been through while developing these apps, but hopefully there will be tips here that are useful to other developers taking their first steps into app development. Using PhoneGap does comes with some limitations, but for our apps it has done the job and for web developers, especially front-end types like me, it’s a good way to get started and begin to learn about app development.</p>
<p><em>The BNY Mellon Boat Race app is available for <a href="http://play.google.com/store/apps/details?id=com.inviqa.Rower" target="_blank">Android</a> and for <a href="https://itunes.apple.com/us/app/boat-race/id606297975?mt=8&amp;ign-mpt=uo=2" target="_blank">iPhone</a>. </em></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F&amp;title=Tips+for+Developing+Apps+with+PhoneGap" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F&amp;title=Tips+for+Developing+Apps+with+PhoneGap" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F&amp;title=Tips+for+Developing+Apps+with+PhoneGap" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F&amp;headline=Tips+for+Developing+Apps+with+PhoneGap" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Tips+for+Developing+Apps+with+PhoneGap&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Tips+for+Developing+Apps+with+PhoneGap&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Tips+for+Developing+Apps+with+PhoneGap&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Tips+for+Developing+Apps+with+PhoneGap&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Tips+for+Developing+Apps+with+PhoneGap&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F&amp;title=Tips+for+Developing+Apps+with+PhoneGap&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F20%2Ftips-for-developing-apps-with-phone-gap%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/03/20/tips-for-developing-apps-with-phone-gap/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Relic for PHP: Web Application Performance Monitoring</title>
		<link>http://techportal.inviqa.com/2013/03/14/new-relic-for-php-web-application-performance-monitoring/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=new-relic-for-php-web-application-performance-monitoring</link>
		<comments>http://techportal.inviqa.com/2013/03/14/new-relic-for-php-web-application-performance-monitoring/#comments</comments>
		<pubDate>Thu, 14 Mar 2013 14:17:17 +0000</pubDate>
		<dc:creator>Sarunas Valaskevicius</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[new relic]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[xdebug]]></category>
		<category><![CDATA[xhgui]]></category>
		<category><![CDATA[xhprof]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4475</guid>
		<description><![CDATA[The performance of a web application plays a critical role in how an application is perceived by its users. It is important to measure it, identify the causes if it changes and react swiftly to any unexpected changes. This article describes an industry leading tool, New Relic, and how it can be used to monitor [...]]]></description>
				<content:encoded><![CDATA[<p>The performance of a web application plays a critical role in how an application is perceived by its users. It is important to measure it, identify the causes if it changes and react swiftly to any unexpected changes. This article describes an industry leading tool, <a href="http://newrelic.com" target="_blank">New Relic</a>, and how it can be used to monitor and improve your site performance.</p>
<p>Setting up a good web application monitoring system can be tiresome, but it's well worth it. Without the monitoring tools the only thing we could tell is <em>if</em> our site is performing as expected or not. In order to <em>improve</em> the performance we have to be able to identify the worse performing user actions and profile them independently to <em>pinpoint the cause</em>. New Relic achieves that and more in just a few screens, all without manually adding any profiling code to your application.</p>
<p><span id="more-4475"></span></p>
<p>New Relic is a real-time application monitoring service, providing various metrics about the performance of your production site, covering everything from application database queries through to the time it takes for the end-user to view a page. This data is then collected, post-processed and converted to simple and clean charts presented in the New Relic web interface. Since the New Relic agent has to collect and report the data, it does add some overhead to the application stack.  Unless you're running a service that has to respond in a few milliseconds, however, the overhead added is minimal and is far outweighed by the value of the reports enabling you to detect and solve problems early.</p>
<p>This article covers both the basic functionality of New Relic (that can be used for free) as well as describing what the Enterprise version has to offer.</p>
<h3 id="getting-started">Getting Started</h3>
<p>The New Relic installation is split into several distinct components:</p>
<ul>
<li>the <em>agent</em> component – a PHP extension, which collects the data and reports to a locally running New Relic daemon.</li>
<li>the <em>daemon</em> component, acting as a proxy between the PHP agents and New Relic datacenters. The main responsibility of the daemon is to reduce the time of reporting the data to New Relic.</li>
<li>New Relic <em>reporting</em> suite – the main New Relic website, where the data is presented for the user.</li>
</ul>
<p></p>
<p>Both the agent and the daemon components are installed using the provided <a href="http://newrelic.com/docs/php/the-newrelic-install-script">newrelic-install</a> script. The script will detect the available PHP installations and deploy the agent extension to all of them.</p>
<p>Please refer to the <a href="http://newrelic.com/docs/php/new-relic-for-php">official documentation</a> for more detailed information regarding the installation and configuration of the New Relic package on your specific platform.</p>
<h3 id="basic-charts">Basic Charts</h3>
<p><em>“Forever. Seriously. That’s right. Free. Just the basics.” (newrelic.com)</em></p>
<p>While the free version of New Relic does not have all the bells and whistles of the Enterprise version, it does provide some basic, yet useful, feedback regarding your site performance.</p>
<h3 id="application-performance">Application Performance</h3>
<p>If you are interested in an overview of how your application performs at PHP level, this is the chart to look at. It displays the average execution time of your PHP scripts in real time, split into separate layers by their execution type:</p>
<ol type="1">
<li>time spent to execute database queries</li>
<li>time spent in PHP</li>
<li>external web service calls</li>
</ol>
<p></p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/app_chart.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/app_chart.png" alt="app_chart" width="624" height="190" class="alignnone size-full wp-image-4479" /></a></p>
<p>Depending on which of the application layers take the most time, different optimisation (or scaling) techniques can be applied.</p>
<ol type="1">
<li>The time spent in the <strong>database</strong> can usually be reduced by doing one or more of the following:
<ul>
<li>analysing the queries that are executed, ensuring that they are using indexes correctly or creating new indexes for them</li>
<li>caching the most frequently-accessed and computationally-expensive result sets from the database</li>
<li>optimising the structure of your application’s data using techniques such as database partitioning</li>
<li>scaling up the database layer (e.g. adding more slave nodes)</li>
</ul>
<p></li>
<li>The <strong>PHP time</strong> is the time that your application is processing the data and good tactics for bringing this down could include:
<ul>
<li>caching intermediate results</li>
<li>optimising the code, using faster algorithms</li>
<li>adding more webnodes (if the hardware limits are reached)</li>
</ul>
<p></li>
<li>A few things that can help to optimise the <strong>network operations</strong>:
<ul>
<li>cache everything that can be cached;</li>
<li>introduce an asynchronous job queue if possible.</li>
</ul>
<p></li>
</ol>
<p></p>
<h3 id="browser-performance">Browser Performance</h3>
<p>Even if the performance of your application is good, there is no guarantee that the users of the site will get it loaded within a reasonable timescale.  The New Relic chart for browser page load time provides an overview of how your website is performing.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/browser_chart.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/browser_chart.png" alt="browser_chart" width="630" height="177" class="alignnone size-full wp-image-4480" /></a></p>
<p>Similar to the application performance overview shown previously, this chart is composed of several separate layers:</p>
<ol type="1">
<li>
<p><strong>Web application</strong> time tells how long it takes for your application to process the requests. More information about this layer can be seen in the <a href="#application-performance">application performance chart</a> shown earlier in this article.</p>
</li>
<li><strong>Network time</strong> is the time that is spent purely for the user request to travel to your application server and then for the response to reach the browser, disregarding the time spent in the application itself.<br /> To optimise this component one would need to review the network performance of your system architecture by considering the following questions:
<ul>
<li>do you compress the response sent to the site users (depending on <code>Accept-Encoding</code>)?</li>
<li>is it just that the response is huge and some of it can be loaded later?</li>
<li>is the bandwidth used reaching its limits and you simply need a faster network link?</li>
<li>would distributing your servers worldwide (see more on this<a href="#worldwide-site-delivery"> later</a>) help?</li>
</ul>
<p></li>
<li><strong>DOM Processing</strong> includes the time from browsers receiving the HTML until the <a href="http://developer.mozilla.org/en-US/docs/Mozilla_event_reference/DOMContentLoaded_event">DOMContentLoaded</a> is fired. The work done by browsers is essentially a preparation to execute your JavaScript logic, thus, it prepares the DOM structure, preloads CSS (<a href="http://molily.de/weblog/domcontentloaded">if there are any script tags after them</a>) and JavaScript files.<br /> To optimise the site performance at this New Relic layer, there are several actions that can be performed:
<ul>
<li>make fewer requests to retrieve JavaScript and CSS files</li>
<li>minify and compress JavaScript and CSS files</li>
<li>set caching headers so that static files could be cached by the client</li>
<li>reduce the number of DOM elements</li>
<li>use a CDN for the static files</li>
</ul>
<p></li>
<li><strong>Page Rendering</strong> time is the time a browser takes to download everything needed after the DOMContentLoaded event; this is usually the time when all the images are downloaded.  Similarly as for the JavaScript and CSS files, the list of actions available to optimise the delivery of static content includes:
<ul>
<li>optimising image files</li>
<li>using CSS sprites instead of multiple images</li>
<li>using correct caching headers</li>
<li>using a CDN to bring your content closer to the user (there's also a chart for that, shown <a href="#worldwide-site-delivery">later in this post</a>)</li>
</ul>
<p></li>
</ol>
<p></p>
<p>An extended list of rules and how they affect your website’s frontend performance can be found at <a href="http://developer.yahoo.com/performance/rules.html">Best Practices for Speeding Up Your Web Site</a>. Also, there are several tools that can help you to analyse the frontend performance such as Yahoo’s<a href="http://developer.yahoo.com/yslow/"> YSlow</a> or Google’s<a href="https://developers.google.com/speed/pagespeed/"> PageSpeed</a>.</p>
<p>More information about the Real User Monitoring functionality can be found at <a href="https://newrelic.com/docs/features/how-does-real-user-monitoring-work#what-does-the-network-time-include">How Does Real User Monitoring Work?</a> (New Relic documentation) or <a href="http://blog.newrelic.com/2011/05/17/how-rum-works/">How we provide real user monitoring: A quick technical review</a> (New Relic blog).</p>
<h4 id="throughput-charts">Throughput Charts</h4>
<p>Even if your application is performing very well, it is only performing this way given the request rate at that time. As the number of users on the site increases, new bottlenecks “appear” – which can slow the overall usage of the site or even bring it down. As a result, the rate your application is handling the requests is at least as important as the time it takes for your application to send the response.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/throughput_chart.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/throughput_chart.png" alt="throughput_chart" width="375" height="180" class="alignnone size-full wp-image-4482" /></a></p>
<p>There are two separate throughput lines available – one for the browser requests and one the application. The browser throughput tells how many pages were requested per minute. Some of those requests may be served from cache before even reaching the application server, other pages may include additional application requests via Ajax. Thus – the two lines may be completely different and suggest different optimisation targets.</p>
<h4 id="apdex-rate">Apdex Rate</h4>
<p>In addition to measuring your website performance in time, New Relic provides an <a href="https://en.wikipedia.org/wiki/Apdex" target="_blank">Apdex</a> score, which tells how many of your site visitors were <em>satisfied</em>, <em>tolerating</em> or <em>frustrated</em> by the response time of the application.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/apdex_chart.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/apdex_chart.png" alt="apdex_chart" width="379" height="178" class="alignnone size-full wp-image-4478" /></a></p>
<p>Once the target times for the browser and application servers are set, it will be used to calculate the Apdex ratio:</p>
<ul>
<li><em>satisfied requests</em> are all requests that have completed in less than the target time (T), and “pull” the Apdex score towards 1.0</li>
<li><em>tolerating requests</em> are those which have taken more than T, but less than 4*T. These requests are given the score of 0.5</li>
<li><em>frustrated requests</em> are all the rest, and their Apdex score is 0.0</li>
</ul>
<p></p>
<p>The main difference between using the Apdex ratio and the application response time, is that no one request (outlier) can affect the global ratio more than any other.  This makes it a more scientific metric for the global overview of your site’s performance if your goal is to answer the question “what proportion of the site visitors see a page loaded quickly enough?”.</p>
<p>For more information about the Apdex score see the <a href="https://newrelic.com/docs/site/apdex">New Relic documentation</a> about this metric.</p>
<h4 id="worldwide-site-delivery">Worldwide Site Delivery</h4>
<p>Is your site performing well for local users? What about the users overseas? The Internet is really fast these days, however it is not instant. The further your user physically is from your servers, the longer distance the information packets will have to travel.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/worldwide_apdex.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/worldwide_apdex.png" alt="worldwide_apdex" width="403" height="251" class="alignnone size-full wp-image-4484" /></a></p>
<p>To get a glimpse of how your site is performing for different countries, you could look at the worldwide Apdex chart. New Relic also provides more detailed information for the enterprise customers.</p>
<p>Since the performance problem in this case is usually due to the global network speed, there is no fix that can be applied locally – you’ll need to bring your service closer to the user. Depending on your application needs one or more of the following measures can be employed:</p>
<ul>
<li>use a CDN to serve static files from local servers</li>
<li>use local dynamic content caching servers for slower areas</li>
<li>implement your service locally for the slower areas</li>
</ul>
<p></p>
<h3 id="enterprise-functionality">Enterprise Functionality</h3>
<p><em>“The Total Package!”</em></p>
<p>The basic functionality that New Relic offers for free can give us a lot of valuable insights about the global site performance. We can see what areas need more attention than others and this alone can save some precious time while optimising the site. Yet, it does not provide some of the (sometimes crucial) information; where <em>exactly</em> is the bottleneck?</p>
<p>In addition to the free Lite account New Relic offers <a href="http://newrelic.com/pricing/details">two more</a> plans (Standard and Pro) which extend the basic reports and introduce some new ones, allowing you to drill down to the root of performance problems quickly and efficiently.</p>
<h4 id="application-profile-traces">Application Profile Traces</h4>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/transaction_overview.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/transaction_overview.png" alt="transaction_overview" width="397" height="405" class="alignnone size-full wp-image-4483" /></a></p>
<p>One of the best features offered to help debug performance problems is the comparison between different web transactions and the ability to see timed application traces of slow calls. New Relic provides charts similar to those described above for each web transaction type (provided that New Relic <a href="http://newrelic.com/docs/php/new-relic-for-php">supports the framework</a> you’re using). Also, a list of slow transaction traces is included with the detailed information.</p>
<p>There are already several tools available to profile your PHP code, such as Xdebug and XHProf. Xdebug is a really powerful development tool as well as offering profiling capabilities. XHProf is <a href="http://techportal.inviqa.com/2009/12/01/profiling-with-xhprof/">simple to configure and relatively easy to use</a>, and there are also companion tools such as <a href="https://github.com/preinheimer/xhprof" target="_blank">XHGui</a> which make life even easier. So what is different about New Relic?</p>
<p>The code profiling trace that New Relic provides is a call tree with only Incl. Wall (absolute and relative) information. This tree alone is not very well suited for a generic code analysis since  it does not provide the count of how many times a method was invoked, nor its total time during the application run. The power of it is that it is integrated with all other New Relic features and is easily accessible for a quick review once a slower transaction is detected. In addition to PHP code profiling, New Relic also provides a separate report for slow SQL statements, with their execution times and call counts.</p>
<p>With the help of these integrated traces, finding slower pieces of the application code is a straightforward task, helping to keep the focus on the site as a whole while still being able to detect problems and pinpoint them to the method level.</p>
<h4 id="compare-with-historical-data">Compare with Historical Data</h4>
<p>In addition to displaying the current state, New Relic also provides a comparison mode. When this mode is turned on, all the basic charts are affected – in addition to the current data they now also provide information from one day and one week ago. This mode is especially useful to show whether the site is performing any better (or worse) than before.</p>
<h4 id="scalability">Scalability</h4>
<p>How well is your website performing under load? The easiest way to answer that is to look at the scalability chart that New Relic provides. The chart plots the application response time versus the throughput.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/scalability.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/scalability.png" alt="scalability" width="603" height="405" class="alignnone size-full wp-image-4481" /></a></p>
<p>This chart can quickly give you an idea about how well your website is responding given that there are a certain number of requests per minute. If the response time is constant as the throughput increases then your site is performing well. However, if you notice that the response time is increasing together with the throughput then it is time to take action. Finding the bottleneck using New Relic should now be an easy task using the database and application code profiling tools described above.</p>
<p>More information about this chart can be found in the New Relic <a href="http://blog.newrelic.com/2011/06/13/of-rainbows-and-polka-dots-new-relics-scalability-charts-explained/">blog</a>.</p>
<h3 id="final-thoughts">Final Thoughts</h3>
<p>New Relic is an amazing service to monitor your web application. It is simple and powerful – all the numbers are presented in such a way that a quick glance to the chart enables one to tell a lot about the site’s performance. In this blog post we have reviewed the common problems that New Relic can help us to detect and provided several suggestions of how to fix them.</p>
<p>Also, it is probably worthwhile mentioning that while New Relic is very good at what it does, it is a service to monitor your application and it usually works best if combined with a separate system to monitor the server resources or the performance of each service you’re using – understanding how the whole application ecosystem behaves is essential in order to build a stable and well performing web service.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F&amp;title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F&amp;title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F&amp;title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F&amp;headline=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F&amp;title=New+Relic+for+PHP%3A+Web+Application+Performance+Monitoring&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F14%2Fnew-relic-for-php-web-application-performance-monitoring%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/03/14/new-relic-for-php-web-application-performance-monitoring/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Manipulating HTTP with Charles Proxy</title>
		<link>http://techportal.inviqa.com/2013/03/05/manipulating-http-with-charles-proxy/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=manipulating-http-with-charles-proxy</link>
		<comments>http://techportal.inviqa.com/2013/03/05/manipulating-http-with-charles-proxy/#comments</comments>
		<pubDate>Tue, 05 Mar 2013 10:00:04 +0000</pubDate>
		<dc:creator>Lorna Mitchell</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[charles]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[techniques]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[wireshark]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4434</guid>
		<description><![CDATA[Charles Proxy is exactly what its name implies; a proxy. This proxy is special however, as it is specifically aimed at giving functionality that developers will need. It allows you to view, change and replay the traffic that passes through, and can handle SSL. Charles isn't free, but at $50 (at the time of writing) [...]]]></description>
				<content:encoded><![CDATA[<p>Charles Proxy is exactly what its name implies; a proxy.  This proxy is special however, as it is specifically aimed at giving functionality that developers will need.  It allows you to view, change and replay the traffic that passes through, and can handle SSL.  Charles isn't free, but at $50 (at the time of writing) for a license, it reaps returns from day one.  This article will show you how to start using Charles and covers techniques that will help you work with your web and mobile applications; basically anything that works over HTTP. <span id="more-4434"></span></p>
<h3>Getting Set Up</h3>
<p>You can download Charles Proxy from the project website: <a href="http://www.charlesproxy.com/" target="_blank">http://www.charlesproxy.com/</a>.  Under the "Documentation" section you will find instructions for installing the tool onto whichever platform you use (Charles supports Windows, Mac and Linux).</p>
<h3>Firefox Extension</h3>
<p>Charles offers a Firefox extension from its download page that makes it very easy to start using your web applications with Charles immediately.  Once you have the extension installed, simply run Charles and then enable the extension from the Tools menu in Firefox.  When a web request is made in Firefox, the HTTP traffic involved is routed through Charles.  This is a great way to get started and is the approach used to generate the first few examples in this article.</p>
<h3>Inspecting Traffic in Charles</h3>
<p>Charles isn't the only option for inspecting traffic, but it is at least as fully featured as using alternatives such as browser plugins such as <a href="https://chrome.google.com/webstore/detail/rest-console/cokgbflfommojglbmbpenpphppikmonn" target="_blank">REST Console</a> or LiveHTTPHeaders, or capturing traffic using a <code>tcpdump</code> and/or <a href="http://www.wireshark.org/" target="_blank">Wireshark</a>.  Charles understands more types of traffic than just what comes through a browser, and has better support for storing, sharing, altering and repeating requests than Wireshark.</p>
<p>By default in Charles, when you start to capture traffic you'll be looking at the "Structure" tab, which shows all the requests that have been made, organised by URL.  Each folder has a domain, then there are subfolders for each element of the path. The view ends up looking something like:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/structure-tab.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/structure-tab-1024x671.png" alt="Structure Tab" width="550" class="aligncenter size-large wp-image-4453" /></a></p>
<p>A more linear way to look at the traffic is to use the "Sequence" tab, which will show something like this:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/sequence-tab.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/sequence-tab-1024x671.png" alt="Sequence Tab" width="550" class="aligncenter size-large wp-image-4444" /></a></p>
<p>Where to look next depends entirely what you're looking <em>for</em>.  The filter box (below the sequence of requests and above the detail section) is very smart, including the ability to configure it to use a regular expression in its search, and will search all the fields shown in the grid.  This allows you to filter down the results to just requests with a given response or using a particular verb, or to a particular domain or subdomain.</p>
<p>Once you have identified the request you want to see, check out the tabs in the bottom half of the screen.  These typically show the following options:</p>
<ul>
<li><strong>Overview:</strong> Some summary information about the request and response formats, sizes, time taken, and so on.  This can be useful when comparing similar requests.</li>
<li><strong>Request:</strong> Full, detailed information about the request, headers, data sent.  Look at the different aspects using the tabs along the bottom of the window.</li>
<li><strong>Response:</strong> Much like the request tab, the response tab has some very nice feaures, in particular its ability to nicely represent data formats such as JSON which can be viewed raw, pretty-printed, or parsed into a structure you can drill down into.</li>
<li><strong>Summary:</strong> Shows all the requests that were made as a result of this request, such as loading other assets to display the page, plus information about the overall size and time of these.  Mostly useful when requesting a root page which loads in other elements such as images.</li>
<li><strong>Chart:</strong> Also mostly useful when requesting a page that loads other elements, this gives a timing diagram of things arriving as shown in the figure below:</li>
<ul></p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/chart-tab.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/chart-tab-1024x671.png" alt="Chart Tab" width="550" class="aligncenter size-large wp-image-4441" /></a></p>
<p>Armed with this information, you can take a good look at what's taking the time in your application, which pages are pulling in which other pages, and so on.  Once you have identified where a problem exists, we can use the following techniques to further diagnose or observe it.</p>
<h3>Replay a Request</h3>
<p>Charles offers the ability to <strong>repeat a specific request</strong> as many times as you want to.  Either right-click on the request to see the options and choose "repeat", or press the blue circular arrows button on the toolbar to repeat the request.  As a debugging tool, this is much nicer than having to fill in the same web form lots of times, or otherwise follow a tricky, multi-step process to replicate a bug.</p>
<p>The right-click menu also offers the ability to "repeat advanced", which allows the same request to be made to the server multiple times, including the option to specify the concurrency.  If you are seeing weirdness under load or you suspect a race condition, then this feature is your friend!</p>
<h3>Sharing Requests</h3>
<p>It's possible to import and export sessions with Charles, in HAR (HTTP ARchive) format, which is supported by other tools as well.  This is superbly handy when one developer is seeing a problem and wants to show another one what's happening without the aforementioned tricky process to reproduce the bug.  Simply <strong>export your session</strong> from Charles and add it as an attachment in the bug tracker; whether it is you or someone else that picks this up, it makes it very easy to replicate the problem and be able to begin working on a fix.</p>
<h3>Throttling Requests</h3>
<p>This is a really good use of a local proxy; to throttle the traffic going through your browser in order to simulate a particular setup or network speed.  For websites where it is likely that the user is either using a mobile phone or is connected via a mobile data connection, this gives us, as developers, insight into how the user experience will be in that scenario.</p>
<p>Charles offers a few options for speed restrictions to simulate different kinds of network connection, shown in the screenshot below:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/throttling.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/throttling-263x300.png" alt="throttling" width="263" height="300" class="aligncenter size-medium wp-image-4447" /></a></p>
<p>It is also possible to limit throttling to just a particular set of hosts, so if for example you know that one particular 3rd party may provide slow connection speeds in some situations, then you can narrow that down using these settings.</p>
<p>Throttling is a very important step in testing mobile applications, especially when working with either mobile sites or with app simulators, since it gives a more realistic sense of the user experience.  I lead an open source project (<a href="http://joind.in" target="_blank">http://joind.in</a>) which is used mostly at conferences, and conference wifi is usually fairly awful – so I throttle down to old modem speeds to give myself a sense of experience when developing that site.</p>
<p>Another feature of Charles which is relevant to this area of development is that it can <strong>disable caching</strong>.  This enables you to reproduce the experience that a new visitor to your site will see.  To achieve this, Charles changes the headers in the HTTP traffic, a feature that we can take direct advantage of ourselves.</p>
<h3>Changing Requests and Responses</h3>
<p>Sometimes, the request and responses that are made by an application aren't exactly what we need them to be.  This can be useful for playing tricks such as redirecting traffic from a mobile app which assumes a particular URL for its API backend, or injecting a specific header to be able to trace your request in the server logs or to enable debugging for requests coming in via this route.</p>
<p>The rewrite functionality can be applied to all requests, or just a subset, and multiple rewrites can be configured at one time.  They are encapsulated into rule sets, so you can save the settings of these, and then enable/disable them at will.  For the rewrites themselves, there are yet more choices; here is the input dialog for creating a rule, to give you an idea of what's possible:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/rewrite-options.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/rewrite-options-291x300.png" alt="Rewrite Options" width="291" height="300" class="aligncenter size-medium wp-image-4443" /></a></p>
<p>As you can see, the options here are endless.  There are any number of reasons why you might need to add things, but these are my most common use cases:</p>
<ul>
<li>Injecting extra headers, either so that I can track a journey through the site because the additional information gets added to a log file, or to enable additional debugging.
</li>
<li>Injecting response headers to see how a client would react on receiving these from a server.  HTTP supports the use of custom headers, so in theory you can use any header you like so long as your server knows how to understand it, and the RFC (see <a href="https://www.ietf.org/rfc/rfc2616" target="_blank">RFC 2616</a>) recommends picking a prefix.  In practice, it's common to use <code>X-</code> as the prefix for these "invented" headers.
</li>
<li>Modifying headers to alter a <code>User-Agent</code> header to chase down a particular bug.
</li>
<li>Setting <code>Host</code> headers – easily the most-used, mostly when using other machines or devices on a network to hit a local development virtual host with a different domain name than expected by the application (more on this in the next section showing how I develop with mobile devices against my local development machine via Charles).
</li>
<li>Adding a rule to do a find-and-replace on the body of a request or response is also very useful at times, for example to rewrite links.
</li>
</ul>
<p></p>
<p>These are very useful tools and the biggest advantage is that you don't need to recompile or reconfigure either the client or server to make these changes; Charles can intercept the traffic and make the changes on the fly.  When developing a mobile app, where you might want to change whether it hits live or development copies of the back end API for example, this is a very quick and easy way to do it.  It also protects against hardcoding these changes into your application and then finding that they get erroneously committed and deployed.</p>
<p><a name="mobile-debug"></a></p>
<h3>Mobile Debugging and Re-routing</h3>
<p>Charles can act as a proxy for other devices to route via the machine it runs on, allowing us to observe and operate on traffic to clients other than the Firefox plugin.  To get set up is fairly straightforward using the following steps.</p>
<p>First, check the IP address of your machine, and check or set which port Charles will listen on by looking under Proxy, then Proxy Settings.  By default this is 8888, and in this example my machine has the IP 10.1.0.121.</p>
<p>Add either the machine hostname or IP to the device to proxy under the wifi settings for the shared network.  I'm using an Android phone as I've been looking at the updated Android app for joind.in, although do be aware that some versions of Android (stock ROMs in the 2.x series, also known as "bug 1273") do <em>not</em> allow you to specify a proxy when adding network settings.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/android-proxy.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/android-proxy-168x300.png" alt="Android Proxy Settings" width="168" height="300" class="aligncenter size-medium wp-image-4439" /></a></p>
<p>When you try to make a web request from the phone now, Charles will alert you that something is trying to proxy through, and give you the opportunity to allow or deny the access:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/proxy-prompt.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/proxy-prompt-300x74.png" alt="Proxy Prompt" width="300" height="74" class="aligncenter size-medium wp-image-4442" /></a></p>
<p>While working with the mobile app, this is a very easy way to observe the traffic being sent and received, and to spot any errors that might be silently ignored or not handled by the application (particularly as my application is in very early stages).</p>
<p>At this point we have the opportunity to perform all of the filtering and altering of traffic that were seen earlier when making web requests.  In this scenario, sometimes I want to try the mobile app against my local development version of the API.  To do this, I have a rewrite that simply routes anything for <a href="http://api.joind.in" target="_blank">http://api.joind.in</a> to <code>http://api.joindin.local</code>.  This is in the hosts file on my machine, so it knows that domain is on the local host.  Here is the rewrite rule in Charles:</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/api-dev-settings.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/api-dev-settings-300x293.png" alt="Settings for API Development" width="300" height="293" class="aligncenter size-medium wp-image-4440" /></a></p>
<p>When I tick and untick the "joindin-api-dev" box, I interrupt traffic to the live API, and instead send it to my local version of the API, which contains sample data and possibly local modifications.  This is such a powerful feature when doing mobile development, because the data sources can be swapped without any need to restart the app, and certainly without changing or rebuilding it.  This tactic is useful both when the app can't be changed, and also when it's simpler to intercept its traffic for testing.</p>
<h3>Charles and SSL</h3>
<p>In the interests of saving the best feature until last: <strong>Charles will also work with SSL traffic</strong>.  SSL traffic is usually very difficult to debug, by design, because nothing other than the client and the server taking part in the transaction should be be able to see the traffic.  An encrypted channel is established and everything is passed over it.  So how can Charles intercept it?</p>
<p>What actually happens is that Charles executes a classic "man in the middle" attack.  The encrypted channel gets set up between Charles and the remote server using the "real" SSL certificate.  Charles then uses its own certificate to sign a second encrypted channel between Charles and the browser or client.  In order to protect you against man-in-the-middle attacks, your browser won't accept a certificate that isn't from a trusted Certificate Authority unless you specifically grant permission for it.  This is fairly common on development servers where it doesn't make sense to pay for an official SSL certificate, so you may have seen these types of untrusted certificate warnings in such scenarios.</p>
<p>To use this feature, first of all you will need to enable Charles to proxy SSL traffic, by ticking the box in the Proxy Settings screen.  You should also specify which domains should have their SSL traffic proxied.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/ssl-setup.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/ssl-setup-300x243.png" alt="SSL Setup" width="300" height="243" class="aligncenter size-medium wp-image-4445" /></a></p>
<p>As we already mentioned, Charles then intercepts the traffic, using the remote site's correct SSL certificate for the connection between there and Charles, then an untrusted one between Charles and the client.  This means that when you enable this in Charles, your browser will tell you that there isn't a valid SSL certificate for the remote site.</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2013/03/untrusted.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/03/untrusted-1024x679.png" alt="untrusted" width="550" class="alignright size-large wp-image-4448" /></a></p>
<p>Confirm the security exception and you can now proceed as normal with all the features mentioned in the earlier sections of this post.  Charles isn't the only tool to offer this functionality, but it's one of the easiest to get up and running with.  When testing or debugging for SSL setups, this is a very valuable addition to the toolbox, and one that I hope you'll find useful moving forward.</p>
<h3>Charles, Web Debugging Proxy</h3>
<p>This article aimed to give you an overview of some of the most useful aspects of Charles for both web and mobile developers, as well as some pointers on how to actually apply the techniques covered here.  All the requests, settings and configuration in Charles can be exported and shared, which is a huge help when using this tool across a team.</p>
<p>Other good products are available and you may also choose to make use of these.  We also use <a href="http://curl.haxx.se/" target="_blank">Curl</a> for being able to make many different kinds of web requests and to easily share them by pasting the commands into the bug trackers.  Another alternative if you only need to inspect (non-SSL) traffic is <a href="wireshark.org" target="_blank">Wireshark</a>, as we mentioned earlier in the article.  Both Curl and Wireshark are free, multiplatform tools.</p>
<p>Charles' tag line "web debugging proxy" is pretty accurate, making it indispensable in many situations.  If you've got a Charles tip to share, or want to tell us how you make use of the techniques shown here, please do leave us a comment, we'd love to hear from you!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F&amp;title=Manipulating+HTTP+with+Charles+Proxy" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F&amp;title=Manipulating+HTTP+with+Charles+Proxy" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F&amp;title=Manipulating+HTTP+with+Charles+Proxy" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F&amp;headline=Manipulating+HTTP+with+Charles+Proxy" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Manipulating+HTTP+with+Charles+Proxy&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Manipulating+HTTP+with+Charles+Proxy&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Manipulating+HTTP+with+Charles+Proxy&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Manipulating+HTTP+with+Charles+Proxy&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Manipulating+HTTP+with+Charles+Proxy&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F&amp;title=Manipulating+HTTP+with+Charles+Proxy&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F03%2F05%2Fmanipulating-http-with-charles-proxy%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/03/05/manipulating-http-with-charles-proxy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHPUK 2013 Conference - Day 2</title>
		<link>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-day-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=phpuk-2013-conference-day-2</link>
		<comments>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-day-2/#comments</comments>
		<pubDate>Tue, 26 Feb 2013 18:07:40 +0000</pubDate>
		<dc:creator>Tom Kitchin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4411</guid>
		<description><![CDATA[It’s the start of a new day, and off we go to the Brewery for the second day of PHPUK 2013. Day 1 has been covered with aplomb by Javier so I’ll not go into details here, but suffice it to say that it was my first day of my first conference and I had [...]]]></description>
				<content:encoded><![CDATA[<p>It’s the start of a new day, and off we go to the Brewery for the second day of PHPUK 2013.  <a href="http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-report-day-1/" target="_blank">Day 1</a> has been covered with aplomb by Javier so I’ll not go into details here, but suffice it to say that it was my first day of my first conference and I had an excellent time wandering without the hint of a clue, eyes filled with the misty wonder of a newborn.  This, however, is about day 2, with a day’s worth of experience under my belt, the confidence of a conference veteran, and the bleary eyes of an early morning after a late night’s social.  </p>
<p>The day started off well, with an excellent breakfast which I’d mostly missed out on the day before.  A colleague had extolled the virtues of the porridge - the <em>porridge</em> - some four hours after breakfast had passed on day 1, and any breakfast able to make porridge so memorably exciting had to be tried.  It was, I think, possibly the best porridge I have ever tasted.  A strange thing to score a conference on, but there we have it.  Moving on...  </p>
<p><span id="more-4411"></span></p>
<h3>Talks - Saturday morning</h3>
<p>We started with a keynote delivered by <a href="http://martijnverburg.blogspot.co.uk/" target="_blank">Martijn Verburg</a>, <strong>The Diabolical Developer</strong>.  He seemed human enough to me, but I suppose he might have been in disguise - you never can tell with Java developers.  In any case, a confidently delivered talk on the subject of best practices disguised as exhortations to protect job security.  Team meetings?  Ha!  Avoid your co-workers and manager at all costs, lest they try to find out what you’re doing or - horror of horrors - try to <em>help</em>.  The thrust of the talk, as I understood it, could be summarised as "best practices are there to serve the developers, not the other way around".  Careful analysis of team practices to make sure none of them are hindering more than they help is clearly worthwhile, and the core message of "the developers and the project are the most important thing" is worth restating regularly.  Unfortunately, regular but unmarked switches between irony and serious speech made the talk a little confusing, weakening the argument.  </p>
<p>For my first talk decision I headed off to <a href="http://videlalvaro.github.com/" target="_blank">Alvaro Videla</a>’s talk <strong><a href="http://www.slideshare.net/old_sound/rabbitmq-hands-on " target="_blank">RabbitMQ Hands On</a></strong>, which was an introduction to - you guessed it - the messaging system <a href="http://www.rabbitmq.com/" target="_blank">RabbitMQ</a>.  My experience with messaging systems is limited to Gearman, which I found a little unwieldy for me, so I was pleased to receive an excellent introduction suitable for newcomers.  Alvaro gave a strong talk aided by an excellent RabbitMQ simulator of his own creation.  Whether you’re a RabbitMQ greenhorn or a veteran I strongly recommend looking out for his simulator - he plans on open sourcing it soon, but until then there’s a <a href="http://vimeo.com/56986242" target="_blank">handy introductory video</a> which is well worth watching.  I found the talk both informative and encouraging, and has left me watching out for an opportunity to make use of RabbitMQ in a project some time soon.  </p>
<p>My second talk was <strong>Scaling with HipHop</strong>, delivered by <a href="https://twitter.com/SaraMG" target="_blank">Sara Golemon</a>.  This was, I think, the most enthusiastic talk I attended over the entire conference.  Quite infectious, really.  I walked in with a passing knowledge of <a href="https://github.com/facebook/hiphop-php" target="_blank">HipHop</a> ("it’s sort of a PHP to C++ compiler for Facebook, right?") and walked out quite dizzy with knowledge.  Sara came across as both knowledgeable on her topic and deeply passionate about it, a combination which is always a joy to find.  HipHop itself is rather more than I had thought, effectively a highly tuned replacement PHP engine which analyses and converts PHP to native bytecode for storage in a database, providing an astonishing 500% performance boost over PHP 5.2.  Throw in the additional PHP features, the in-house-developed streamlined web server and even the in-house IDE and it becomes clear how Facebook can handle around one billion active users.  </p>
<p>One billion active users.  One <em>billion</em>.  <em>Active</em>.  </p>
<p>I know this is kind of old news, but just think about that for a few moments.  For reference, current estimates put us at around 7 billion people on the planet.  </p>
<p>Huh.  </p>
<h3>Lunch</h3>
<p>Anyway.  Lunchtime!  Lunch was up to the standards set by breakfast.  Not much more I can say about this, except for a brief comment on the strange image of a room full of developers holding plates with those funny cup holder clips on, fighting over about twenty people’s worth of table space and even fewer seats.  </p>
<p>I took the opportunity to cheerfully obliterate the current record for the <a href="http://ow.ly/i/1z3qw" target="_blank">Inviqa/SensioLabs Bigtrak programming race</a>... which would be more meaningful if I hadn’t spent some of the day before practicing.  My honour demanded that I keep my time to myself, as did the judges who sadly recognised me perfectly well.  So much for fame and fortune.  </p>
<p>I didn’t actually attend the talks immediately after lunch, as I was feeling quite overwhelmed by the veritable torrent of knowledge I’d received that morning.  Instead I sat down in the Hackspace and investigated (read: googled) some of the technologies I’d heard about, as well as having a chat with the chaps over at the <a href="http://zeroturnaround.com/software/liverebel/" target="_blank">LiveRebel</a> booth.  Worth checking out, incidentally - looks like quite a neat deployment management solution.  </p>
<h3>Talks - Saturday Afternoon</h3>
<p>On, then, to the fourth talk:  <strong><a href="http://www.slideshare.net/juokaz/you-cant-optimize-what-you-cannot-measure-php-uk " target="_blank">You Can’t Optimise What You Can’t Measure</a></strong>.  <a href="http://juokaz.com/" target="_blank">Juozas "just call me Joe" Kaziukėnas</a> handled this one with the message "logs are useless."  Don’t even write them.  I recognise the knee-jerk reaction we all have to that, but he made a good case - and I should clarify that we’re referring to production servers here.  How often do we even read our logs?  Instead he made a strong argument for good metrics-based data gathering, passed to suitable analysis tools.  If we can be automatically warned whenever the metrics start to veer off their expected state, not only can we react to failures and bugs but even user experience issues we would otherwise have missed.  Not so sure about "data doesn’t lie," though.  Data might not lie, but we have to convert it to information to use it, and we can certainly bring a few of our own lies in (quite unintentionally) on the way.  I found his argument persuasive, in any case.  </p>
<p>For my final talk I attended  <strong><a href="http://www.leggetter.co.uk/pres/php-uk-2013/pres/" target="_blank">Realtime Web Apps in the Wild</a></strong> with <a href="http://www.leggetter.co.uk/" target="_blank">Phil Leggetter</a>.  This was primarily about event-driven web applications, as advancing technologies have finally allowed us to implement a "true" real-time web.  The talk actually had a set of interactive apps woven into it, accessed by attendee browsers from smartphones to laptops - a fun addition to the usual style of a talk.  A good discussion of available technologies (with a commendable lack of bias from the <a href="http://pusher.com/ " target="_blank">Pusher</a> developer) and an informative if light coverage of the history of hacks, techniques and trickeries used to emulate realtime work in the past.  It’s rather subjective, but I found the talk to have less impact than any of the others I attended, though.  Perhaps this talk would have had a greater effect on someone who works more closely with near-real-time web apps - personally, I’m now aware of the technical differences but I struggle to really sense the difference between the old hacks and the new approaches favoured by the talk.  Definitely worth a look if that’s your focus, though.  </p>
<p>Last (but by no means least, as they say) we had the panel.  Day 2’s panel had a much better feel than the first day’s, with some genuine enthusiasm and good humour displayed by a panel consisting of <a href="http://aralbalkan.com/" target="_blank">Aral Balkan</a>, <a href="http://phpir.com/" target="_blank">Ian Barber</a>, <a href="https://twitter.com/SaraMG" target="_blank">Sara Golemon</a>, <a href="http://www.alittleofboth.com/" target="_blank">Beth Tucker Long</a> and <a href="http://martijnverburg.blogspot.co.uk/" target="_blank">Martijn Verburg</a>.  The topic was <strong>Open Source in Action</strong>, and to me the highlight was some discussion of previous open source projects by the panelists which had achieved things, or changed things, or ended up in strange and unexpected places.  If you needed a reminder of why open source is worth our time and effort and our creative energies (and I discovered I did), it was worth hearing.  It’s because you can write a piece of code for yourself, just because you need it, and throw it out on the web just because someone else might need the same - and in the end that code you’d have written anyway makes someone’s life easier, or ends up in places you never expected.  A creative industry indeed.  </p>
<p>Do I need to cover the post-conference social?  I thought not.  </p>
<h3>Conclusion</h3>
<p>So we come at last to the wrap-up.  I had a great time at the first conference I’ve attended and hope others felt the same.  I listened to and spoke to interesting, enthusiastic people, both speakers and attendees, and more than anything I feel like it brought home why I got into software development in the first place.  </p>
<p>Because we can create amazing, interesting things that people need or like or enjoy or didn’t even realise they wanted or don’t need at all and share them with the world.  Now, if you’ll excuse me, I have a few new projects I need to think about.  </p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F&amp;title=PHPUK+2013+Conference+-+Day+2" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F&amp;title=PHPUK+2013+Conference+-+Day+2" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F&amp;title=PHPUK+2013+Conference+-+Day+2" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F&amp;headline=PHPUK+2013+Conference+-+Day+2" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=PHPUK+2013+Conference+-+Day+2&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=PHPUK+2013+Conference+-+Day+2&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=PHPUK+2013+Conference+-+Day+2&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=PHPUK+2013+Conference+-+Day+2&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=PHPUK+2013+Conference+-+Day+2&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F&amp;title=PHPUK+2013+Conference+-+Day+2&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-day-2%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-day-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHPUK 2013 Conference Report - Day 1</title>
		<link>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-report-day-1/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=phpuk-2013-conference-report-day-1</link>
		<comments>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-report-day-1/#comments</comments>
		<pubDate>Tue, 26 Feb 2013 15:32:20 +0000</pubDate>
		<dc:creator>Javier Lopez</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[london]]></category>
		<category><![CDATA[phpuk]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4347</guid>
		<description><![CDATA[Last week, the 8th PHPUK Conference took place. Due to a previous commitment I could only attend Friday's session so if you think I am missing something, do not hesitate to leave a comment. Here is my personal point of view of the PHPUK Conference this year. Talks The conference opened with Aral’s keynote “You [...]]]></description>
				<content:encoded><![CDATA[<p>Last week, the 8th PHPUK Conference took place. Due to a previous commitment I could only attend Friday's session so if you think I am missing something, do not hesitate to leave a comment. Here is my personal point of view of the PHPUK Conference this year.</p>
<h3>Talks</h3>
<p>The conference opened with Aral’s keynote “You are a designer”. I have to say that the talk was just brilliant, probably one of the best talks I’ve ever been to. Unfortunately, in my humble opinion, the opening keynote for one of the biggest events on the PHP scene should be related to PHP. I know this is a matter of taste and I actually talked to a lot of people who thought it was an excellent opening.</p>
<h4><a href="https://speakerdeck.com/ianbarber/event-stream-processing-in-php" target="_blank">Event Stream Processing in PHP</a></h4>
<p>The next talk in my agenda was “Event Stream Processing in PHP”, by Ian Barber. I couldn’t have been happier to have picked this talk. Ian started from zero, introduced the basic concepts of event stream<span id="more-4347"></span> in an excellent way and went on to show us some code. This is the kind of talk that puts an idea in the back of your head that months later will pop out when you realise that you need it in a real life project.</p>
<h4><a href="http://patches.experimentalworks.net/Looking%20Ahead%20PHP%205%20Animations.pdf" target="_blank">Looking ahead: PHP 5.5</a></h4>
<p>David Soria Parra, in “Looking ahead: PHP 5.5” introduced some of the new ideas coming up with the latest version of PHP. He announced that PHP is going to change its release cycle and is going to be bundled with the following new features:<br />
- generators<br />
- the password API<br />
- DateInmutable<br />
- ::class<br />
- finally, mysql extensions are deprecated (At this moment he pointed out that WordPress core developers are going to have a lot of fun due to the intensive use of this function in the code, ;))</p>
<p>Probably, the best piece of news for the PHP community is that Zend Optimizer is likely (but not confirmed yet) to be included into the core.</p>
<p>You can read more about the new features on <a href="http://php.net/manual/en/migration55.new-features.php" target="_blank">php.net</a>.</p>
<p>It was quite shocking for me that when he was leaving the stage, he said he was eager to answer any questions throughout the event, but please, “don’t ask me any PHP code question, I am really bad at it”. It got me thinking and I realised that, ironically, he´s more of a C/C++ developer.</p>
<h4><a href="https://speakerdeck.com/dmi/api-design-its-not-rocket-surgery-phpuk13" target="_blank">API Design: It’s not rocket surgery</a></h4>
<p>Dave Ingram was explaining everything you should bear in mind when building an API. The talk was quite accurate but I would have added more spice in order to make it a little bit more dynamic. Anyways, with no hesitation, if I have to build an API in the future I will try to get back to these slides, I am pretty sure it’s going to be quite helpful going through all this valuable information.</p>
<h4><a href="http://www.slideshare.net/marcello.duarte/pair-programming-tdd-and-other-impractical-things" target="_blank">Pair Programming, TDD and Other Impractical Things</a></h4>
<p>Marcello Duarte, Head of Training at Inviqa, exposed with quite a sense of humour some of the new TDD practices. I really enjoyed the talk, not because it was mind blowing or there were new concepts I'd never heard of before, but how he managed to dazzle everyone in the room by exposing all these ideas from a completely different point of view.</p>
<p>If you are a newcomer to all the TDD philosophy, I really encourage you to check the slides for this talk.</p>
<h4><a href="http://michaelpeacock.co.uk/slides/r2sc/index.html#/" target="_blank">Refactoring to Symfony Components</a></h4>
<p>I closed my first and only day at the conference with this talk by Michael Peacock. Throughout the talk Michael showed us how he managed to rebuild an old legacy project using some of the Symfony Components (namely Routing, ClassLoader, Yaml, HttpFoundation and EventDispatcher) and some other third party libraries (Twig, Pimple and Swiftmailer). In my opinion, his strategy to rebuild the project was quite clever and showed us how sometimes you can’t follow the path marked by some of the biggest frameworks but you can still take advantage of all this code.</p>
<p>You can check all the slides of the event on <a href="https://joind.in/event/view/1144/slides" target="_blank">joind.in</a></p>
<h3>Venue</h3>
<p>The conference was celebrated in The Brewery, in the heart of the City of London.</p>
<p class="textcenter">
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/02/the-brewery.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/02/the-brewery-300x199.jpg" alt="The Brewey Conference Venue" width="300" height="199" class="alignnone size-medium wp-image-4349" /></a>
</p>
<p>I first discovered this site last September, during the SensioLabs UK Conference and I have to admit I really like it. It’s really well located and it has an English style that makes it attractive for foreigners like me.</p>
<p>The talks were split into four different rooms. The keynotes and the panels took place in the main auditorium. The acoustics of this massive room are impressive. Moreover, for the people sitting at the very end of the room there were several screens broadcasting the slides.</p>
<p class="textcenter">
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/02/auditorium-large.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/02/auditorium-large-300x225.jpg" alt="Track 1 PHPUK13" width="300" height="225" class="alignnone size-medium wp-image-4352" /></a><br />
(Picture courtesy of @aral)
</p>
<p>The rest of the talks were running in three smaller rooms but they were spacey enough to host 200 people each. There was a room that was considerably smaller than the others but it was amended with a complimentary room where the talk was broadcasted live, and I have to say that the quality of the sound and the video was really good.</p>
<p>The only “but” had to do with the main track where the bottom of the slides were quite close to the floor and it was hard for the people at the back of the room to see.</p>
<h3>On a side note...</h3>
<p>Even though the PHP UK Conference is a British conference, you can’t lose sight of the fact that there are a lot of non-native English speakers attending. I really liked the fact that none of the speakers had a broad accent, actually, the delivery of their speech was quite neat. I am not sure whether they were making a conscious effort but I’d like to thank them all for this.</p>
<p>Also, the food was quite good. I am used to attending the sort of geeky conference where you get served pizza or cold sandwiches. Having a proper hot meal was great and sets the conference at a professional level, as it rightly deserves.</p>
<h3>Summing up</h3>
<p>It was a great conference. Everything was great, from the talks and speakers, to the organisation. I have to own up this conference is becoming a must in my diary and I am pretty sure I’ll go next year.</p>
<p class="textcenter">
<a href="http://techportal.inviqa.com/wp-content/uploads/2013/02/2013-02-26-08.29.58.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2013/02/2013-02-26-08.29.58-300x179.jpg" alt="Javier Conference Badge" width="300" height="179" class="alignnone size-medium wp-image-4369" /></a></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F&amp;title=PHPUK+2013+Conference+Report+-+Day+1" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F&amp;title=PHPUK+2013+Conference+Report+-+Day+1" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F&amp;title=PHPUK+2013+Conference+Report+-+Day+1" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F&amp;headline=PHPUK+2013+Conference+Report+-+Day+1" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=PHPUK+2013+Conference+Report+-+Day+1&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=PHPUK+2013+Conference+Report+-+Day+1&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=PHPUK+2013+Conference+Report+-+Day+1&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=PHPUK+2013+Conference+Report+-+Day+1&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=PHPUK+2013+Conference+Report+-+Day+1&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F&amp;title=PHPUK+2013+Conference+Report+-+Day+1&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F26%2Fphpuk-2013-conference-report-day-1%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/02/26/phpuk-2013-conference-report-day-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting Started with Git</title>
		<link>http://techportal.inviqa.com/2013/02/19/getting-started-with-git/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=getting-started-with-git</link>
		<comments>http://techportal.inviqa.com/2013/02/19/getting-started-with-git/#comments</comments>
		<pubDate>Tue, 19 Feb 2013 14:30:20 +0000</pubDate>
		<dc:creator>Kacper Gunia</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4329</guid>
		<description><![CDATA[On a daily basis probably each and every software developer spends a lot of time collaborating and communicating with other developers. There are several tools that simplify this communication (or at least should). One of those tools is a Version Control System. Not so long ago, a new tool appeared on the horizon, called Git. [...]]]></description>
				<content:encoded><![CDATA[<p>On a daily basis probably each and every software developer spends a lot of time collaborating and communicating with other developers. There are several tools that simplify this communication (or at least should). One of those tools is a Version Control System. Not so long ago, a new tool appeared on the horizon, called Git.  It quickly became a very popular tool in the open source community. Though the ideas behind Git are very basic, becoming a master is not easy! It takes some time, especially for someone who has had the "pleasure" of working with other systems like SVN or CVS previously. If you are starting with Git or switching from another tool, then this post is an aggregation of ideas, not a full-featured tutorial. If you are already an experienced user, perhaps you will consider sharing your knowledge in the comments.</p>
<h3>Learn from the Best Sources</h3>
<p>There are several places where you can read and learn about Git, but it is hard to know which resource is best. In my opinion the best source of Git knowledge is a free book called "Pro Git" (<a href="http://git-scm.com/book" target="_blank">http://git-scm.com/book</a>). The second is an online tutorial called <a href="http://gitimmersion.com/" target="_blank">Git Immersion</a>. If you feel you missed something or want detail on something specific, then there is always the <a href="http://git-scm.com/docs" target="_blank">official documentation</a>.<span id="more-4329"></span></p>
<h3>Pick a Workflow and Strategy</h3>
<p>Git is a great tool that allows you to work in many different ways. The possibilities and flexibility that you can achieve with it are a great thing. If you want, you can even use it in exactly the same way that you were using SVN (but there is no real point in doing that). To simplify team communication and avoid conflicts, it is good to follow some rules and standards created by other developers. I would recommend you read about <a href="https://github.com/nvie/gitflow" target="_blank">GitFlow</a> and <a href="http://scottchacon.com/2011/08/31/github-flow.html" target="_blank">GitHub Flow</a>. Then you will be able to pick a strategy that suits you (and your team).</p>
<h3>Customise Git</h3>
<p>Git is only one of the many tools that you are using, but you will be spending a lot of time with this tool, so it is worth taking the time to customise it to your own needs. Most of the useful options were described in the Pro Git book, and I have also included below some basics from my configuration. To use these, you will need to edit the config file placed in your home directory. For example:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">vim</span> ~<span style="color: #000000; font-weight: bold;">/</span>.gitconfig</pre></td></tr></table></div>

<p>You can then copy, paste and customise the following lines as you wish:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>color<span style="">&#93;</span></span>
<span style="color: #000099;">diff</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> true</span>
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>user<span style="">&#93;</span></span>
<span style="color: #000099;">name</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> Name Surname</span>
<span style="color: #000099;">email</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> your@email.com</span>
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>alias<span style="">&#93;</span></span>
<span style="color: #000099;">co</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> checkout</span>
<span style="color: #000099;">fa</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> fetch --all</span>
<span style="color: #000099;">ci</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> commit</span>
<span style="color: #000099;">st</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> status</span>
<span style="color: #000099;">br</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> branch</span>
<span style="color: #000099;">last</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> log -1 HEAD</span>
<span style="color: #000099;">unstage</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> reset HEAD</span>
<span style="color: #000099;">amend</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> commit --amend</span>
<span style="color: #000099;">staged</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> diff --cached</span>
<span style="color: #000099;">unstaged</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> diff</span></pre></td></tr></table></div>

<p>Another great approach is to steal the best configurations provided by my colleague Alistair on his GitHub account <a href="https://github.com/alistairstead/dotfiles/blob/master/.gitconfig" target="_blank">https://github.com/alistairstead/dotfiles/blob/master/.gitconfig</a>. Alistair has taught me a lot about Git, so trust me when I say it is worth following his way of using it.</p>
<p><strong>Extra tip:</strong> configure your Bash prompt to display current branch and other related information, using the instructions in <a href="http://asemanfar.com/Current-Git-Branch-in-Bash-Prompt" target="_blank">http://asemanfar.com/Current-Git-Branch-in-Bash-Prompt</a>.</p>
<h3>Introduce Gamification</h3>
<p>If you like to be rewarded for your work you might be interested in a project called <a href="https://github.com/icefox/git-achievements" target="_blank">Git Achievements</a>.  This project allows you to receive points for using Git on a daily basis, and you can challenge your friends to do the same! To get you started, my result <a href="http://cakper.github.com/git-achievements" target="_blank">http://cakper.github.com/git-achievements</a> is waiting to be beaten by you ;)</p>
<h3>Just Do It</h3>
<p>The best way to learn is to begin - right now!  Create a testing repository, play with it and don't be scared to break something. The skills you learn by practising now will be very useful in the future. Not everything will be easy from the beginning, but to help you along your way here are some tips for solving common problems:</p>
<p>To edit the most recent commit message:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git commit</span> <span style="color: #660033;">--amend</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;new commit message&quot;</span></pre></td></tr></table></div>

<p>To revert an uncommitted file to the previous version:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git checkout</span> HEAD path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">file</span></pre></td></tr></table></div>

<p>To delete your last commit:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git reset</span> <span style="color: #660033;">--hard</span> HEAD~<span style="color: #000000;">1</span></pre></td></tr></table></div>

<p>To create a new branch from the current one (and move all uncommitted changes):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git checkout</span> <span style="color: #660033;">-b</span> branch-name</pre></td></tr></table></div>

<p>To check out a remote branch from the origin repo:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git checkout</span> <span style="color: #660033;">-b</span> branch-name origin<span style="color: #000000; font-weight: bold;">/</span>branch-name</pre></td></tr></table></div>

<p>If you want to learn some more serious stuff, a great way to do that is to join an open source project on <a href="https://github.com/" target="_blank">GitHub</a>. In my opinion it is the best place to acquire skills from other people, and also a good opportunity to use your own skills to contribute to a project used by many people.</p>
<p>I hope this short post will be a shortcut and allow you to kick off your experience with Git in a painless way. Having good Git skills will improve the way you work, and in time I think you will come to share my impression: this is such an easy and beautiful tool.</p>
<p>Leave your tips and share your experiences in the comments.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F&amp;title=Getting+Started+with+Git" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F&amp;title=Getting+Started+with+Git" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F&amp;title=Getting+Started+with+Git" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F&amp;headline=Getting+Started+with+Git" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Getting+Started+with+Git&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Getting+Started+with+Git&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Getting+Started+with+Git&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Getting+Started+with+Git&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Getting+Started+with+Git&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F&amp;title=Getting+Started+with+Git&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F02%2F19%2Fgetting-started-with-git%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/02/19/getting-started-with-git/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>2012: A Year in PHP</title>
		<link>http://techportal.inviqa.com/2013/01/08/2012-a-year-in-php/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=2012-a-year-in-php</link>
		<comments>http://techportal.inviqa.com/2013/01/08/2012-a-year-in-php/#comments</comments>
		<pubDate>Tue, 08 Jan 2013 08:38:32 +0000</pubDate>
		<dc:creator>Ben Longden</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Planet PHP]]></category>
		<category><![CDATA[2013]]></category>
		<category><![CDATA[opinion]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4307</guid>
		<description><![CDATA[Another year has passed, and yet again we find ourselves reflecting on what has happened in the world of PHP over the past year. Let's take a moment to look back over our 2012 predictions and see how close we were! Framework Convergence In 2011 we said that major frameworks would start to converge on [...]]]></description>
				<content:encoded><![CDATA[<p>Another year has passed, and yet again we find ourselves reflecting on what has happened in the world of PHP over the past year. Let's take a moment to look back over <a href="http://techportal.inviqa.com/2012/01/07/2011-a-year-in-php/" title="2011 A Year in PHP">our 2012 predictions</a> and see how close we were!</p>
<h3>Framework Convergence</h3>
<p>In 2011 we said that major frameworks would start to converge on similar strategies for basic functionality. The <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md" target="_blank">PSR-0 standard</a> defined a common autoloading strategy, and the release of <a href="http://getcomposer.org" target="_blank">Composer</a> in March 2012 has really boosted the adoption of this standard across the most popular frameworks. The release of <a href="http://symfony.com/" target="_blank">Symfony</a> 2.1.0 in June brought in Composer as the dependency management solution of choice and the first stable release of <a href="http://framework.zend.com/" target="_blank">Zend Framework 2.0</a> followed in September, also using Composer for autoloading and dependency management.</p>
<p>In March, the Drupal project announced that version 8 of their platform (currently due for release mid-2013) would be completely rebuilt on top of the <a href="http://symfony.com/components" target="_blank">Symfony components</a>, an exciting development and certainly one which has started to bring the Symfony and Drupal communities together at conferences and other community events.<br />
<span id="more-4307"></span><br />
It does appear to be the case that projects, even up to the framework level, are starting to move in the same direction, but the choice remains: Zend Framework 2 or Symfony 2? I think we can claim a point for this one!</p>
<h3>Dependency Injection Containers</h3>
<p>At the time we made this prediction, Symfony 2 was already in the wild and Zend Framework 2 was under heavy development with alpha versions available. We saw further releases of these two big hitters through 2012 and DIC (Dependency Injection Containers) have been a popular topic throughout the year at conferences. It's enabled practitioners to create testable, reusable code and has become a standard practice amongst practitioners of good PHP.</p>
<h3>Serious Caching</h3>
<p>We said that caching would be a big topic of 2012 as large enterprises and other organisations start to leverage open source solutions for their high traffic web applications. Almost all projects that we have started in 2012 have had a varnish layer designed in from the start to achieve the high performance that our clients expect, and Edge Side Includes (ESI) has started to see more use in new applications - putting caching proxies, of which Varnish is one, at the core of the platform.</p>
<p>We'll claim a point for this one as we have seen caching being a really hot topic in 2012, and one which we expect to continue to see in 2013. Varnish has seen an increase in usage during 2012 of 39% (see <a href="http://trends.builtwith.com/Web%20Server/growth#!oneYear" target="_blank">http://trends.builtwith.com/Web%20Server/growth#!oneYear</a>)</p>
<h3>Trending</h3>
<h4>Composer</h4>
<p>One of the most popular topics that has come up at conference talks in 2012 is Composer. We've mentioned it already in this write up, but if there was a top 10 for what has changed the face of PHP over the year, this would be #1. Not only has Composer been a conference talk topic in its own right across many events this year, it has also featured in talks about many other technologies. Support for Composer has become something that people working on open source PHP project libraries are proud to announce as a feature of their product - and quite rightly so! It has already become something that's almost expected for all PHP libraries - and pull requests on GitHub to add support for it across the board have become commonplace.</p>
<h4>Best Practice</h4>
<p>The old argument between PHP users and users of other languages has raged on. We are proud of PHP's roots in server-side templating, but the language has evolved into something completely different today. Because of this history, the PHP manual is focussed on the quick way of getting something done in PHP rather than what is necessarily the best practice, and 2012 saw the launch of a really great resource for developers: <a href="http://www.phptherightway.com/" target="_blank">http://www.phptherightway.com/</a>. It is a collection of recognised "best practices, options and good information" on using PHP and is a highly recommended read for all users of the language. The recent addition of comment voting on the <a href="http://php.net" target="_blank">PHP manual</a> will hopefully promote good information over poor practice in the official manual over time, which will only benefit us all.</p>
<h4>PHP5.4, PHP5.5, PHP5.2 and PHP5.3 (in that order...)</h4>
<p>The <strong>5.4</strong> stable release of PHP came out in March, and since then it has seen 10 maintenance releases - bringing us to the latest stable release of 5.4.10 (at the time of writing). </p>
<p>Towards the end of 2012 we also saw the first alpha releases of <strong>PHP 5.5</strong> - the next major release of the PHP 5 language. This will bring new features such as generators (simple iterators with the addition of the yield keyword in functions), the "finally" keyword (try, catch, finally), a new and redesigned password hashing API and various other improvements to the language core. It's worth mentioning that the current release is still alpha and new/deprecated features are still subject to change.</p>
<p>The <a href="http://w3techs.com/technologies/details/pl-php/5/all" target="_blank">w3techs usage statistics</a> reports that <strong>PHP 5.2</strong> is still the most popular deployment of PHP out there in the wild with 52.1% of all PHP deployments running on that version. The language hit end-of-life status back in 2010 and users of sites built on this old technology have been encouraged to upgrade to 5.3 as a matter of urgency.</p>
<p><strong>PHP 5.3</strong> is in second place with 42.9% of deployments. The PHP group announced that 5.3 would reach an end of life status in March 2013 - with these users being encouraged to upgrade to 5.4. It's important that existing users of 5.2 start to look at upgrading as the work required to jump two or even three major versions will quickly become problematic. A small minority of sites are still stuck on PHP 4 and PHP 5.1, but we won't talk about those...!</p>
<h4>PHP Closures</h4>
<p>How did we code in PHP before the 5.3 release brought us closures? From being able to write PHP code directly into core functions like <code>array_map()</code> et al, to seeing frameworks like Silex gaining popularity, built on Symfony2 components and leveraging the coding style that having support for closures allow, this welcome language addition has made it easy for us to write better PHP.</p>
<p>For example how ugly would the <a href="https://github.com/fabpot/Pimple/blob/master/lib/Pimple.php" target="_blank">code of the Pimple project</a> be, but for the support of Closure within PHP?</p>
<h3>Predictions For 2013</h3>
<p>Now we come to the part where we try to predict what is going to happen in the land of PHP during 2013.</p>
<h4>Framework Convergence ... Again</h4>
<p>We predicted it last year and some massive steps were made towards achieving this goal. We think that 2013 will bring more efforts to be able to share modules between frameworks through the establishment of defined interfaces.  These will be implemented by the framework core (a common approach to things like logging, authentication, etc). It only makes sense to build on what has already been achieved in 2012 with Composer and Packagist (the package repository that Composer uses).</p>
<h4>Content as a Service</h4>
<p>It's becoming more and more common for clients to ask us for a way of being able to create content and share it across many different sites and software platforms. Currently, the most popular CMS products force you to display the content you create through the templating system that is in-built to the platform you are using. We think that in 2013 we will start to see solutions for allowing a content repository to be able to push its content out to many different places - especially as more people consume data on a mobile platform.</p>
<h4>Dependency Injection Containers Mark 2</h4>
<p>With the previously-mentioned greater adoption of DIC within frameworks, more and more people have made use of DIC to resolve dependency management within their code. However this has lead to misuse by some and problems of an entirely different nature, especially within code libraries. As the wider community learns from these experiences good practices are formed. Dependency Injection needs to be considered when designing OO software rather than just ignored and left to the DIC.</p>
<h4>BDD with PHPSpec and Behat</h4>
<p>XUnit style testing frameworks seem to be losing favour within the community and the adoption of Spec frameworks and Behaviour Driven Development is set to increase in 2013. With the initial alpha release of PHPSpec 2 in October 2012 this alternative testing framework has given the PHP community a fresh perspective on testing and where it fits into the development process. This lean framework by design focuses on being a tool to help and support writing well structured OO code rather than provide mechanisms for validation. Used in conjunction with Behat, PHP now has the tools needed for full stack BDD. We predict a much greater adoption of these tools and BDD over 2013 and beyond.</p>
<h4>Use and Misuse of Traits</h4>
<p>Once PHP 5.3 reaches end of life status in March, framework and library developers will start to create releases with PHP 5.4 as a minimum dependency, allowing them to make use of traits. We anticipate that this will result in a great deal of code deletion from frameworks as multiple horizontal inheritance will allow a lot of boilerplate code from iterators (for example) to be removed and placed into traits.</p>
<p>This sounds like good news, and it is. However with great power comes great responsibility and this particular language feature is likely to be both used and abused! The community is always quick to learn from its mistakes however and we're sure that by this time next year traits will have had lots of good and some bad press.</p>
<h3>PHP and You in 2013</h3>
<p>What is on your horizon for the coming year?  Is there anything we should have seen coming and didn't mention?  Leave us a comment and let us know - and good luck with your PHP this year!</p>
<h3>Contributors</h3>
<p>Ben Longden<br />
Alistair Stead</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F&amp;title=2012%3A+A+Year+in+PHP" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F&amp;title=2012%3A+A+Year+in+PHP" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F&amp;title=2012%3A+A+Year+in+PHP" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F&amp;headline=2012%3A+A+Year+in+PHP" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=2012%3A+A+Year+in+PHP&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=2012%3A+A+Year+in+PHP&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=2012%3A+A+Year+in+PHP&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=2012%3A+A+Year+in+PHP&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=2012%3A+A+Year+in+PHP&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F&amp;title=2012%3A+A+Year+in+PHP&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2013%2F01%2F08%2F2012-a-year-in-php%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2013/01/08/2012-a-year-in-php/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Global Git Ignore</title>
		<link>http://techportal.inviqa.com/2012/11/01/global-git-ignore/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=global-git-ignore</link>
		<comments>http://techportal.inviqa.com/2012/11/01/global-git-ignore/#comments</comments>
		<pubDate>Thu, 01 Nov 2012 09:48:19 +0000</pubDate>
		<dc:creator>Alistair Stead</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4288</guid>
		<description><![CDATA[I was recently reviewing a number of projects on GitHub and I was amused by some details about people that can be inferred by the content of a project's .gitignore file. I could identify the owner's base OS and their preferred IDE - even some of the specific development tools or system plugins they have [...]]]></description>
				<content:encoded><![CDATA[<p>I was recently reviewing a number of projects on <a href="http://github.com" target="_blank">GitHub</a> and I was amused by some details about people that can be inferred by the content of a project's <code>.gitignore</code> file. I could identify the owner's base OS and their preferred IDE - even some of the specific development tools or system plugins they have installed.</p>
<p>If I worked for a marketing company, this could be a source of data to be mined to sell expensive alternate software. After all, between your GitHub identity and the <code>.gitignore</code> content, targeted contact lists could be derived. I hope that no marketing executive reads this otherwise I apologize in advance!</p>
<p><span id="more-4288"></span></p>
<p>Projects should have <code>.gitignore</code> rules committed as part of the project. This is of course functionally correct. However each individual developer might want to consider setting up their own system-wide ignore rules, so that project-specific files remain project-specific. You can then add rules to ignore the configuration files from your preferred IDE that no one else in the project uses.</p>
<p>There are many very valid reasons why you should do this:</p>
<ul>
<li>The project leads don't have to do this for each project or change it when you as a contributor move to a new IDE.</li>
<li>You can set-up your system to function they way you want without it impacting the project or others.</li>
<li>Some potentially unsafe<em>*</em> commands such as '<code>git add -A</code>' become safer as you will not commit sensitive or user specific files.</li>
<li>If you're sending pull requests to Open Source projects, they will not be declined due files that should not be present.</li>
<li>Reduce the need to duplicate rules between many projects for non-project files.</li>
</ul>
<p></p>
<h3>Okay this sounds good, how do I do that?</h3>
<p>Firstly let's create a file on your system that will hold these system-wide ignore rules.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">touch</span> ~<span style="color: #000000; font-weight: bold;">/</span>.gitignore-global</pre></td></tr></table></div>

<p>Then add the appropriate rules that you want to be ignored across all projects. Below is the content of my own <code>.gitignore-global</code> file</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Compiled source #</span>
<span style="color: #666666; font-style: italic;">###################</span>
<span style="color: #000000; font-weight: bold;">*</span>.com
<span style="color: #000000; font-weight: bold;">*</span>.class
<span style="color: #000000; font-weight: bold;">*</span>.dll
<span style="color: #000000; font-weight: bold;">*</span>.exe
<span style="color: #000000; font-weight: bold;">*</span>.o
<span style="color: #000000; font-weight: bold;">*</span>.so
&nbsp;
<span style="color: #666666; font-style: italic;"># Packages #</span>
<span style="color: #666666; font-style: italic;">############</span>
<span style="color: #666666; font-style: italic;"># it's better to unpack these files and commit the raw source</span>
<span style="color: #666666; font-style: italic;"># git has its own built in compression methods</span>
<span style="color: #000000; font-weight: bold;">*</span>.7z
<span style="color: #000000; font-weight: bold;">*</span>.dmg
<span style="color: #000000; font-weight: bold;">*</span>.gz
<span style="color: #000000; font-weight: bold;">*</span>.iso
<span style="color: #000000; font-weight: bold;">*</span>.rar
<span style="color: #000000; font-weight: bold;">*</span>.tar
<span style="color: #000000; font-weight: bold;">*</span>.zip
&nbsp;
<span style="color: #666666; font-style: italic;"># Logs and databases #</span>
<span style="color: #666666; font-style: italic;">######################</span>
<span style="color: #000000; font-weight: bold;">*</span>.log
<span style="color: #000000; font-weight: bold;">*</span>.sqlite
&nbsp;
<span style="color: #666666; font-style: italic;"># OS generated files #</span>
<span style="color: #666666; font-style: italic;">######################</span>
.DS_Store
ehthumbs.db
Icon
Thumbs.db
.tmtags
tags
vendor.tags
tmtagsHistory
<span style="color: #000000; font-weight: bold;">*</span>.sublime-project
<span style="color: #000000; font-weight: bold;">*</span>.sublime-workspace</pre></td></tr></table></div>

<p>Into this file you should add matches for things like system cache files or system and IDE configuration files.</p>
<p>Once you have this file created you will need to edit your <code>.gitconfig</code> file to add this additional configuration file. This can be done by editing the file manually or by running the command below:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git config</span> <span style="color: #660033;">--global</span> core.excludesfile ~<span style="color: #000000; font-weight: bold;">/</span>.gitignore-global</pre></td></tr></table></div>

<p>That's it! You now have system-wide git ignore rules that will prevent you from needing to duplicate these rules into each project. This alone is a good enough reason to do this; the others are just a bonus.</p>
<p><em>* By unsafe I mean, if you don't appreciate what the command or flag does. I often see newcomers to Git use this shortcut with unexpected results.</em></p</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F&amp;title=Global+Git+Ignore" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F&amp;title=Global+Git+Ignore" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F&amp;title=Global+Git+Ignore" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F&amp;headline=Global+Git+Ignore" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Global+Git+Ignore&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Global+Git+Ignore&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Global+Git+Ignore&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Global+Git+Ignore&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Global+Git+Ignore&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F&amp;title=Global+Git+Ignore&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F11%2F01%2Fglobal-git-ignore%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/11/01/global-git-ignore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RESTFest 2012</title>
		<link>http://techportal.inviqa.com/2012/10/03/restfest-2012/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=restfest-2012</link>
		<comments>http://techportal.inviqa.com/2012/10/03/restfest-2012/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 07:27:08 +0000</pubDate>
		<dc:creator>Ben Longden</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[restfest]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4263</guid>
		<description><![CDATA[I was fortunate enough to be able to attend RESTFest in Greenville, South Carolina on the 13th, 14th and 15th September 2012. RESTFest is an un-conference organised by Mike Amundsen and Benjamin Young, and this is the third year it has run at Greenville. An un-conference invites attendees to talk on any subject they choose [...]]]></description>
				<content:encoded><![CDATA[<p>I was fortunate enough to be able to attend RESTFest in Greenville, South Carolina on the 13th, 14th and 15th September 2012. RESTFest is an un-conference organised by <a href="https://twitter.com/mamund">Mike Amundsen</a> and <a href="https://twitter.com/bigbluehat">Benjamin Young</a>, and this is the third year it has run at Greenville.</p>
<p>An un-conference invites attendees to talk on any subject they choose amongst peers and some of the most experienced people in the community in a very relaxed, informal atmosphere. It provides an opportunity to spend three days immersed in discussions about REST and hear about real world Hypermedia APIs. The idea - everybody talks and everybody listens.</p>
<p><span id="more-4263"></span></p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2012/10/DSC02813.jpg"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/10/DSC02813-300x225.jpg" alt="Excellent conference space provided by Iron Works, in the NEXT Innovation Center, Greenville" title="DSC02813" width="300" height="225" class="alignleft size-medium wp-image-4274" /></a></p>
<h1>Hack day</h1>
<p>Day one was a hack day organised and run by David Zülke. David provided a custom hypermedia type capable of representing a help desk containing users, tickets and comments. He also provided ideas for possible applications that could use the hypermedia type. These ranged from the obvious client / server combination (servers using a custom storage vs servers using an existing ticket storage), to intermediary servers that were capable of enhancing the media type with search capabilities, an automated test client and an XML to JSON proxy.</p>
<p>We split up into teams and 'flew blind' for the first few hours whilst we build up our applications. Once we started getting enough features implemented, we started to be able to interact with each others apps using the common language of the hypermedia type. It was really impressive to see the fruits of the days labours prove to have been worth it - with a quite feature-full help desk application suite having been produced, driven by Hypermedia.</p>
<p>It was particularly pleasing to see a client written in Ruby successfully talking to a server written in PHP using GitHub Issues as a storage medium. The same client could also talk to a second server written on a different platform with its own custom storage engine. A true example of why arguments about language X being better or worse than language Y are left being irrelevant when language neutral constructs are used to bridge the gap between them.</p>
<p>The exercise was a demonstration of the level of interoperability that following the constraints of REST bring to an application system, and the realisation that intermediaries (servers that proxy requests between the client and server end point) can not only cache requests to help an application scale up, but can also enhance the product by decorating the hypermedia type with new link relations and adding extra functionality.</p>
<h1>Talks</h1>
<p>The following two days were filled with 90 minute workshop sessions and lightning talks. Darrel Miller kicked off day two with his presentation on "The 7 R's of Hypermedia", exploring the practical use of Hypermedia through seven scenarios where it can be used within distributed applications: Relations, Resources, Reference Data, Restriction, Re-Distribution, Reduction, and Reactive. <a href='https://vimeo.com/channels/restfest/49484938'>Video</a>.</p>
<p>Pat Cappelaere of the NASA SensorWeb project followed with his work shop on "User Stories and Acceptance Criteria for RESTful Services", demonstrating the RIP (REST Interface Policy) checker, http://rip.jit.su. This is an app that assesses and reports on RESTful services using a continuously updated set of user stories and acceptance criteria to assess the level of compliance of the service against the Richardson maturity model.</p>
<p>The talk and application (RIP) was a great example of the potential of using standard hypermedia types and the benefits of using them in an api over a custom type that only one client is capable of understanding. <a href='https://vimeo.com/channels/restfest/49484939'>Video</a>.</p>
<p>Next up was Mike Amundsen, with his amusing run through of the constraints of REST, "REST-like Wisdom from Celebrity Internet Memes". From Inigo Montoya to Yoda, it was a fun walk through of the do's and don'ts of services on the web and provided an entertaining talk to follow lunch. <a href='https://vimeo.com/channels/restfest/49503453'>Video</a>.</p>
<p>After Mike was the start of the first session of lightning talks - these run from 5 to 15 minutes in length (the longer ones usually due to active conversation after a short presentation introducing the topic). These give people an opportunity to present anything they want, from a recent Hypermedia project they have been involved in to a monitoring system for performance analysis in front of a targeted audience of REST/Hypermedia professionals, an audience that could only be found at an event like this! Great discussion and everyone who presented could take away a lot from the experience.</p>
<p>I presented some options for how to represent the changing state of resources with Hypermedia. This is a topic that keeps cropping up for me and I solve it in a new way, almost every time I come up against it. The social events with the group once the conference day was done also provided opportunity to discuss the lightning talks and new ideas over a beer in a more relaxed atmosphere.</p>
<p>The day rounded off with a keynote presentation from Stuart Charlton titled 'Linking Data and Actions on the Web', in which Stuart introduced ideas for introducing the concept of Linked Behaviour Trees to the design of REST API's. This was a fascinating exploration of advancing the art of RESTful APIs, and left everyones mind reeling - especially after a full day of other great talks on the subject! Definitely one that I will need to watch for a second time to full absorb what was said and i'm looking forward to seeing the video again once it's made available. <a href='https://vimeo.com/channels/restfest/49609290'>Video</a>.</p>
<p>The following day was kicked of by a really great featured talk by Leonard Richardson (creator of the Richardson Maturity Model, which he introduced at a QCon talk in '08), titled 'How to Follow Instructions'. Well worth a watch, even if just for the excerpt on Native Language Bindings; 'Native Language Bindings [for REST APIs] are generally bad. Not like poisonous snakes are bad… but like fast food restaurants in neighbourhoods that don't have grocery stores are bad. They're compensating for a failure earlier in the process. [snip] And it can be really tasty, but just wait six months after you eat one of these every day!'. Very humorous talk from a well respected author and speaker in the industry. <a href="https://vimeo.com/channels/restfest/49609649">Video</a>.</p>
<p>Pat Cappelaere spoke for a second time on 'RESTful Patterns for [OGC] Enterprise Services', a dive into what patterns are used in a network of millions of sensors, both in orbit (satellite) and at ground level, to bring them together and make them accessible to both humans and machines. This followed his earlier talk on RIP, and how the SensorWeb team are using it to drive the definition of the Enterprise Patterns they use today. <a href='https://vimeo.com/channels/restfest/49609650'>Video</a>.</p>
<p>Matt Bishop followed Pat with his talk titled 'HATEOAS Your Cake and Eat It Too', a walk through of how Matt and his team at Elastic Path turned a complex e-commerce process into a Hypertext driven API, and how a true Hypermedia driven api (Level 3 of the Richardson Maturity Model) can only be successful if it's based on real world (reality) concepts rather than the existing services that it's built on. He goes through some of the common misconceptions of what constitutes L3 that they have come up against during their journey towards L3, including "L3 is HTTP used correctly" and "Content-Type is the Hypermedia-Type" where he introduces the concept that the Content-Type (xml or json) is actually different from the Hypermedia-Type (atom / hal / etc). One of the most interesting ideas he introduced was the 'Zoom' functionality of the framework they built - a way of expanding out responses with many directly related resources in a single request to avoid making client to have to make many requests to the server, something that the HAL media type specification supports natively through embedded resources. <a href='https://vimeo.com/channels/restfest/49609648'>Video</a>.</p>
<p>The final featured talk of the conference was by Sam Ramji of Apigee, on 'Architecting for performance with devices &#038; APIs', with some lessons learned from the history of computing on low bandwidth, high latency networks now that we're moving back towards that world with the popularisation of mobile devices. HTTP APIs are the heart of most applications we run on mobile devices so taking consideration of the network on which the data will be transmitted over is essential to the success of the API project. He introduces the idea that from the perspective of the mobile client, the Internet is a database, and that the API is the modern day equivalent of writing stored procedures on the database to optimise it. Sam included some enlightening tips on how 3G devices work, and how a 'chatty' API can cause a serious drain on battery powered mobile devices. <a href='https://vimeo.com/channels/restfest/49609651'>Video</a>.</p>
<p>The remainder of the conference day was filled with lightning talks on a variety of subjects from 'How to be a better Condescender-er' to people introducing new tools they have been developing or working with and new ideas for advancing the art of Restful API design. The lightning talks are all available to watch on the RESTFest <a href='https://vimeo.com/channels/restfest/'>vimeo channel</a>.</p>
<p>All in all it was an excellent three days in Greenville. I personally came away with new ideas and thoughts on the 'right' way of doing things when designing Hypermedia systems and had the chance to meet and talk with many of the people I have known through various online forums.</p>
<h1>In closing</h1>
<p>Thank you to the organisers, Mike Amundsen and Benjamin Young for putting together the event and to the sponsors for making it all possible. The food during the day and social events in the evening were all a great success.</p>
<p>We (<a href="http://inviqa.com">Inviqa</a>) are putting together a training course on creating RESTful Hypermedia Application which will become available from December. It will cover Service Oriented Architecture and a recap of HTTP, the concept and constraints of the REST architectural style and how it's evolving, and of course - the role that Hypermedia plays in all of this - and an opportunity to practice these concepts in a training environment. Get in touch if you want to know more.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F&amp;title=RESTFest+2012" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F&amp;title=RESTFest+2012" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F&amp;title=RESTFest+2012" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F&amp;headline=RESTFest+2012" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=RESTFest+2012&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=RESTFest+2012&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=RESTFest+2012&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=RESTFest+2012&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=RESTFest+2012&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F&amp;title=RESTFest+2012&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F10%2F03%2Frestfest-2012%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/10/03/restfest-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony Live London Ticket Winner Announced</title>
		<link>http://techportal.inviqa.com/2012/09/07/symfony-live-london-ticket-winner-announced/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=symfony-live-london-ticket-winner-announced</link>
		<comments>http://techportal.inviqa.com/2012/09/07/symfony-live-london-ticket-winner-announced/#comments</comments>
		<pubDate>Fri, 07 Sep 2012 14:08:11 +0000</pubDate>
		<dc:creator>Lorna Mitchell</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4254</guid>
		<description><![CDATA[We are delighted to announce that the competition winner is Manuel! Manuel will win a pass to the Symfony Live conference day next week. We hope you have a good time! Thanks to everyone who left a comment on the post, we loved hearing your reasons for wanting to attend. If you would like to [...]]]></description>
				<content:encoded><![CDATA[<p>We are delighted to announce that the competition winner is Manuel! Manuel will win a pass to the Symfony Live conference day next week. We hope you have a good time!</p>
<p>Thanks to everyone who left a comment on the post, we loved hearing your reasons for wanting to attend. If you would like to attend there are still a few places available, so <a href="http://london2012.live.symfony.com/tickets" target="_blank">get your tickets</a> and we'll see you there.</p>
<p>To find out more about the event and keep up to date on the day, make sure you're following <a href="https://twitter.com/#!/SensioLabsUK" title="@SensioLabsUK">@SensioLabsUK</a>. We'll be tweeting news, views and pictures throughout the day.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F&amp;title=Symfony+Live+London+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F&amp;title=Symfony+Live+London+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F&amp;title=Symfony+Live+London+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F&amp;headline=Symfony+Live+London+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Symfony+Live+London+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Symfony+Live+London+Ticket+Winner+Announced&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Symfony+Live+London+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Symfony+Live+London+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Symfony+Live+London+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F&amp;title=Symfony+Live+London+Ticket+Winner+Announced&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F09%2F07%2Fsymfony-live-london-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/09/07/symfony-live-london-ticket-winner-announced/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony Live London: 13th-14th September</title>
		<link>http://techportal.inviqa.com/2012/08/24/symfony-live-london-13th-14th-september/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=symfony-live-london-13th-14th-september</link>
		<comments>http://techportal.inviqa.com/2012/08/24/symfony-live-london-13th-14th-september/#comments</comments>
		<pubDate>Fri, 24 Aug 2012 13:31:00 +0000</pubDate>
		<dc:creator>Lorna Mitchell</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony live]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=4223</guid>
		<description><![CDATA[The first ever Symfony Live London conference will be taking place next month, hosted by our sister company Sensio Labs UK! The two-day event involves one full day of in-depth training, followed by a 2-track, deeply technical conference. (We’ve got a ticket to give away, keep reading!) Workshop Day The workshop day gives you the [...]]]></description>
				<content:encoded><![CDATA[<p>The first ever Symfony Live London conference will be taking place next month, hosted by our sister company Sensio Labs UK! The two-day event involves one full day of in-depth training, followed by a 2-track, deeply technical conference.<br />
(We’ve got a ticket to give away, keep reading!)</p>
<p><a href="http://london2012.live.symfony.com/"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/08/Symfony-Live-banner.jpeg" alt="" title="Symfony Live London 2012" width="215" height="258" class="aligncenter size-full wp-image-4240" /></a><br />
<span id="more-4223"></span></p>
<p><strong>Workshop Day</strong></p>
<p>The <a href="http://london2012.live.symfony.com/training">workshop day</a> gives you the choice of two workshops designed to enable you to get the best out of Symfony whether you are an experienced user, or new to the Symfony world.<br />
The first training course, <strong>Getting Started with Symfony2</strong> will give you an insightful introduction to the framework, from installation to configuration and request management.<br />
The second option for the workshop day is more advanced - <strong>Going Further with Symfony2</strong>. This workshop dives straight into some of the more advanced features of Symfony2, such as mastering the dependency injection container configuration, running automated tests and Doctrine integration.</p>
<p><strong>Conference Day</strong></p>
<p>We’re extremely lucky to have two major project leaders as our keynote speakers. The conference day will start with an opening keynote from Dries Buytaert - the Drupal founder and project lead. Then we’ll close the conference with a session from Fabien Potencier, the founder of Symfony and a major contributor to the project.</p>
<p>The main part of the day will consist of two tracks of very <a href="http://london2012.live.symfony.com/schedule">technical talks</a> from some well known speakers from the Symfony2, Drupal and PHP conference scenes. There are a variety of topics from key elements of the development process (PHPDocumentor, code reviews, Composer, BDD), through essential skills for using Symfony2 (bundles, SonataAdmin) and including considerations for the platform (ElasticSearch, Amazon Web Services).  With all this technical content, the hardest part of the day will be choosing which track to attend.</p>
<p><strong>Symfony Certification</strong></p>
<p>For the first time in the UK, developers will be able to sit the <a href="http://trainings.sensiolabs.com/en/training/symfony-certification">Symfony2 Certification exam</a>.  </p>
<p>For organisations using Symfony, having certified developers on your team really shows the world you don’t compromise on quality when delivering projects. Perhaps more importantly, it also shows you work closely with your developers to improve their skills and engage  with the Symfony community.</p>
<p>For individuals and freelancers, working to improve your skills to the level required to pass the exam will give you a much more robust knowledge of Symfony as it will encourage you to examine areas of the Symfony toolset you may not have used before.  Once you have the acquired the knowledge required passing the exam proves to potential clients and employers that you have worked hard to set yourself out from the crowd.</p>
<p>Distinguish yourself from other Symfony developers and become an official SensioLabs Symfony Certified Developer.</p>
<p><strong>Win a ticket</strong></p>
<p>We have one ticket to give away to our readers. To be in with a chance of winning, simply <strong>leave a comment on this post telling us why you think you should win</strong> the ticket. Make sure you include your email address so we can get in touch if you win! We will randomly draw a winner when we close the competition on September 5th. Want to join us? Then, leave a comment.</p>
<p>Unfortunately we only have one ticket to give away so if you don’t win we’d still love for you to join us at the event. If you’ve not already signed up <a href="http://london2012.live.symfony.com/tickets">tickets are still on sale</a>. Grab one while you can. </p>
<p>To follow the news from the event follow our twitter account <a href="https://twitter.com/sensiolabsuk">@SensioLabsUK</a> or the <a href="https://twitter.com/#!/search/?q=symfony_live&#038;src=savs">#symfony_live</a> hashtag.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F&amp;title=Symfony+Live+London%3A+13th-14th+September" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F&amp;title=Symfony+Live+London%3A+13th-14th+September" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F&amp;title=Symfony+Live+London%3A+13th-14th+September" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F&amp;headline=Symfony+Live+London%3A+13th-14th+September" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Symfony+Live+London%3A+13th-14th+September&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Symfony+Live+London%3A+13th-14th+September&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Symfony+Live+London%3A+13th-14th+September&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Symfony+Live+London%3A+13th-14th+September&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Symfony+Live+London%3A+13th-14th+September&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F&amp;title=Symfony+Live+London%3A+13th-14th+September&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F08%2F24%2Fsymfony-live-london-13th-14th-september%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/08/24/symfony-live-london-13th-14th-september/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Custom Zend Framework Form Elements</title>
		<link>http://techportal.inviqa.com/2012/07/31/custom-zend-framework-form-elements/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=custom-zend-framework-form-elements</link>
		<comments>http://techportal.inviqa.com/2012/07/31/custom-zend-framework-form-elements/#comments</comments>
		<pubDate>Tue, 31 Jul 2012 09:12:34 +0000</pubDate>
		<dc:creator>Gavin Corbett</dc:creator>
				<category><![CDATA[Planet PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Zend Form]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=3884</guid>
		<description><![CDATA[Creating forms in Zend Framework (ZF) is easy, but creating and managing complex forms can get messy! Using config files is perfectly good if you use standard Zend Form elements; it is quick and easy to setup a form in a few minutes however you will have limited control over how the form is rendered. [...]]]></description>
				<content:encoded><![CDATA[<p>Creating forms in Zend Framework (ZF) is easy, but creating and managing complex forms can get messy!  Using config files is perfectly good if you use standard Zend Form elements; it is quick and easy to setup a form in a few minutes however you will have limited control over how the form is rendered. If you want to display your own custom form element correctly in Zend Framework then some configuration is needed in order to achieve this with a config file. An alternative approach is to create some custom objects that extend the base Zend Form object - you can still use the config but also add in your own custom Zend Form elements. <span id="more-3884"></span></p>
<p>If you use a custom form object then all of your form logic can be grouped together.  The object can include data validation with Zend validator (and/or normal PHP validation for more complex validation routines), form data retrieval, form view format and element view rendering.  This has the combined benefit of freeing the controller of any form logic needed for the custom objects and ensures the "skinny controller, fat model" approach can be used, avoiding duplicating logic as each form object is now responsible for its own data.</p>
<p>This article will show you how to create custom form element objects which change the standard view template for an element - the code from all the examples is <a href="https://github.com/gavalar/TP-ZF1-CustomElements" target="_blank">available on github</a> too, if you want to follow along.  The approach shown here enables us to add logic into the element, so that the element behaves the same way in any form. A good example could be a select box that can pre-fill data from a database table and automatically add a Zend Validator to the array.   We'll also cover how you can have total control over the way the form is rendered, by using a view script.  As an example, we'll create an e-commerce checkout where a billing address and delivery address contain exactly the same fields with JavaScript and Zend Validation; our postcode fields will trigger a postcode lookup.</p>
<h3>Creating a Custom Zend Form Object</h3>
<h4>Extending the Zend Form the Right Way</h4>
<p>To gain great functionality on top of ZF, the best way is to extend the framework, creating your own base, then extend that per project, as shown in the code example below.  This way if you want to add a new method to an object then you just need to add it to your own main object, leaving the core Zend object unmodified. For instance if you want every Zend Form to have a <code>getValidatedFormData()</code> method then you can implement it in your base class (and should Zend implement the same functionality later on then you can remove your implementation, or leave it and override theirs).  Hopefully this seems obvious but I am amazed how often I see code that uses only the core Zend objects.<br />
<code><br />
class MyBase_Form extends Zend_Form<br />
{<br />
....<br />
}<br />
</code></p>
<p>Your main base class doesn’t need to do any more than just extend the base Zend Form object; this makes it easier to update all your objects with new methods or override the core Zend methods should you need to do so in the future.  The specific form (in this case <code>Email_Form</code>) should extend your base Zend Form object we just created, so that any and project specific-methods can be added leaving you to re-use your <code>MyBase</code> object.</p>
<p>This level of abstraction may seem slightly "over the top", however it can save you a lot of time later if more changes are needed such as changing the default display from "dt" and "dd" tags to a table layout.  With the abstraction layer, this only needs to be done once and all form objects will be converted.  This approach has the added benefit of easier testing as you only need to test the functionality you are actually writing.</p>
<p>So far, all we have done is set up a form object, now we can configure the form’s elements and more importantly the validation.  Using this approach we keep the validation logic together and, should the elements change, the validation can change to match.  The changes are unit testable and re-useable, and validation will be also available if this form is to be used as a sub-form.</p>
<h4>Adding the Elements</h4>
<p>To add elements to this form, we could use a Zend_Config objects for adding standard elements only, but we get more control by adding the elements manually - so we'll do that!<br />
<code><br />
class MyProject_Form_Address extends MyBase_Form<br />
{<br />
    protected $_action_url = '/[controller]/[action]/';</p>
<p>    public function init()<br />
    {<br />
        parent::init();<br />
        $this-&gt;setAction($this-&gt;action_url)<br />
             -&gt;setAttrib(‘id’, ‘project_form’)<br />
             -&gt;setMethod(‘post’);</p>
<p>        $billing = new Zend_Form_Element_Textarea('billing_address', array(<br />
            'label' =&gt; 'Billing Address:',<br />
        ));<br />
        $billing-&gt;setRequired();</p>
<p>        $del_diff = new Zend_Form_Element_Checkbox('different_delivery_address', array(<br />
            'label' =&gt; 'Deliver to different address:',<br />
        ));  </p>
<p>        $delivery = new Zend_Form_Element_Textarea('delivery_address', array(<br />
            'label' =&gt; 'Delivery Address:',<br />
        ));  </p>
<p>        $submit = new Zend_Form_Element_Submit('submit', array(<br />
            'label' =&gt; 'Send:',<br />
        ));  </p>
<p>        $this-&gt;addElement($billing, 'billing_address')<br />
             -&gt;addElement($del_diff, 'different_delivery_address')<br />
             -&gt;addElement($delivery, 'delivery_address')<br />
             -&gt;addElement($submit, 'submit');<br />
    }<br />
}<br />
</code></p>
<p>As you can see from the above example, we have used standard objects but we have added attributes to specific elements in the form; this can be further extended by using the decorators (something we will cover later in this tutorial).</p>
<p><a href="http://techportal.inviqa.com/wp-content/uploads/2012/07/form2.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/form2.png" alt="" width="381" height="170" class="alignnone size-full wp-image-4212" /></a></p>
<h3>Validating the Form</h3>
<p>For validation what place is better to check whether this form is valid than the form itself?  If a field is required only when a certain condition is true, you could check this every time in your controller.  Alternatively you could extend the <code>isValid()</code> functionality and use any properly-extended <code>Zend_Validation_Abstract</code> object on any of the form elements.</p>
<p><code><br />
public function isValid($value, $context = null)<br />
{    <br />
    $valid = parent::isValid($value, $context);<br />
    if ($this-&gt;isDeliveryAddressDifferent()) {<br />
        $this-&gt;getElement('delivery_address')-&gt;setRequired();<br />
        return parent::isValid($value, $context);<br />
    }<br />
    return $valid;<br />
}<br />
</code></p>
<p>As you can see the isValid function now checks to see if the form element is checked and then set's the delivery address to be required and revalidates the form, this way the form is more dynamic.</p>
<h3>Getting the Data from the Object</h3>
<p>There is the standard way of getting data from the object by getting the raw data array by using the <code>getValues()</code>, however there is a better way: create custom "getters".  By using getters, you can add more logic if it is needed, but the biggest benefit is that it will make your code much more readable - and of course again unit testing will be easier.</p>
<p>As you can see this way of getting the inputted data is simple to do, and it will make your code much more extendable and maintainable.</p>
<pre>
public function isDeliveryAddressDifferent()
{
    if ($this-&gt;getValue('different_delivery_address') == 1) {
        return true;
    }
    return false;
}

public function getAddressLine1()
{
    return $this-&gt;getValue('line_1');
}
</pre>
<h3>Changing the Way the Form is Rendered</h3>
<p>As with most of Zend Framework, you can use as much or little of the standard framework as you like.  In particular let's look at ways of changing how the form is rendered, beyond simply adding a stylesheet.  Sometimes you need something more than the standard "dd" and "dt" output, perhaps to output as a table or have full control over the view template for a given form or sub-form.  This can be done by adding to the <code>init()</code> method.</p>
<pre>
public function init()
{
    $this-&gt;setDisableLoadDefaultDecorators(true);
    $this-&gt;setDecorators(array(
        array('ViewScript', 
            array('viewScript' =&gt; 'form/_form.phtml')),
            'Form'
    ));
}
</pre>
<p>The full path for this script would be application/views/scripts/form/_form.phtml</p>
<h3>Creating a Custom Form Element</h3>
<p>Extending <code>Zend_Form</code> objects is good practice but there is very little that you can’t do with Zend_Config.  However when you come to add your own custom elements, this approach will really pay dividends.  So now I will show you how to extend the standard form elements to make your own, such as creating a select / radio / checkbox set of elements from a database resultset, or using a Javascript library to create a date time field with custom view helpers, adding standard Zend_Validtors that it has to pass before the element is valid.  In this tutorial, I will be extending a text box to make a standard email textbox, and pulling data from a database to pre-populate a select box.</p>
<h4>Extending the Zend Form Element Object</h4>
<p>Take a look at the following example; we simply add two validators when we initialise the object:</p>
<pre>
class MyBase_Form_Element_Email extends Zend_Form_Element_Text
{
    public function init()
    {
        $this-&gt;addValidator('EmailAddress')
             -&gt;addFilter('StringToLower');

        return parent::init();
    }
}
</pre>
<p>Now we've done this, those validators are automatically added everywhere this element is used.  This means that your form needs to do no more than this: when you create the form, just give the name of the element you created rather than the standard text field.</p>
<h3>Connecting to a Database for Pre-populated Elements.</h3>
<p>The example below might look a little more complicated, but we will approach it step by step.  The hardest part is getting the data from the database, which shouldn't be too tricky (you could refactor this so that the data is pulled from a data object however for this tutorial I will just use the standard <code>Zend_Db_Adapter</code>).  Here we are creating a select element but, by changing the parent object, it could equally be a set of radio options form or even a set of checkboxes instead.  N.B. There is a obvious SQL injection issue here, as you know you should validate ALL input, for simplicity I have not added this but I do recommend that you implement something on all SQL variables.  Here's the code example first, then we'll step through each bit below:</p>
<pre>
class MyBase_Form_Element_SelectFromDB extends Zend_Form_Element_Select
{
    // First element in the select box
    protected $_select = array(
        '=== Please Select ===',
    );

    public function __construct($spec, $options)
    {
        parent::__construct($spec, $options);

        $this-&gt;addOptionsFromDatabase(Zend_Registry::get('db'), $options)
             -&gt;setRegisterInArrayValidator(true);
    }

    public function addOptionsFromDatabase(Zend_Db_Adapter_Abstract $db, $options)
    {
        $table = $options['table'];
        $columns = $options['columns'];

        $sql = sprintf('SELECT `%s` as id, `%s` as name FROM `%s`', $columns[0], $columns[1], $table);

        $row_data = $db-&gt;fetchAll($sql . ';');

        foreach ($row_data as $row) {
            $this-&gt;_select[$row['id']] = sprintf($this-&gt;_pattern, $row['name'], $row['id']);
        }
        $this-&gt;addMultiOptions($this-&gt;_select);

        return $this;
    }
}
</pre>
<p>First, take a look at the constructor. We try and make the element as flexible as possible and as we don't know which columns, table or even database this element would be communicating with, we need a way of getting that from the calling object.  As in all <code>Zend_Form_Element</code>s there already is a second parameter which does different things depending on element, so we will utilise this and append our details to this array parameter, specifically for the database.  In this example I use a rudimentary array but you can always refactor this to take an object, for example.</p>
<p>As part of the initial object construction, we populate the <code>Zend_Form_Element_Select</code> option array from the database; this also adds the <code>Zend_Validate_InArray</code> to prevent undesired details being entered into the form. </p>
<p>Next we shall look at getting the data from the database.  This method mostly constructs the valid SQL, which I assume you are familiar with.  This method loops through all of the database rows, then converts from a multi-dimensional array into a single-dimension array with the key from the database as the index.  The text will be displayed in the form that the element has rendered.</p>
<h3>Creating a Custom View Helper</h3>
<p>There are times when you would like to use a standard element but with a custom view, e.g. a postcode lookup with javascript validation, or a date field.  I will show you a quick way of doing javascript validation that will accept any input and add an OK button next to the element.  There are two files that need to be created: a form object which extends the standard element, and the view helper.</p>
<pre>
class MyBase_Form_Element_Email extends Zend_Form_Element_Text
{
    public $helper = 'formEmail';
}
</pre>
<p>As you can see this object doesn't need to do any more than extend the standard object and change the view helper.</p>
<p>Now lets create the view helper:  It is important to notice that the filename is <code>FormEmail.php</code> and the method name is <code>formEmail</code> – this is taken from the <code>$helper</code>.  So <code>Form{$helper}.php</code> and <code>form{$helper}</code>.</p>
<pre>
class MyBase_View_Helper_FormEmail extends Zend_View_Helper_FormText
{
    public function formEmail($name, $value = null, $attribs = null)
    {
        $info = $this-&gt;_getInfo($name, $value, $attribs);
        extract($info);

        $xhtml = $this-&gt;formText($name, $value, $attribs) .
                 '<span>view-&gt;escape($id) . '" style="display:none;"&gt;OK</span>';

        $xhtml .= '
        
             $("#' . $this-&gt;view-&gt;escape($id) . '").blur(function() {
                if($("#' . $this-&gt;view-&gt;escape($id) . '").val() != "") {
                    $("span.' . $this-&gt;view-&gt;escape($id) . '").show();
                } else {
                    $("span.' . $this-&gt;view-&gt;escape($id) . '").hide();
                }
            });
        ';

        return $xhtml;
    }
}
</pre>
<p>This example is fairly simple and you would refactor to move as much logic as you could into the CSS, and create a JS with a function call taking in the <code>id</code> from the form element (which should be unique).</p>
<p><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/form2.png" alt="" width="381" height="170" class="alignnone size-full wp-image-4212" /></p>
<p>As you can see, the approach outlined here makes your controllers very easy to maintain, but more importantly the objects that know the most about the input from the user now contain the validation and filter logic - and so it can be reused and extended easily.  Check out the github repository which you can find here <a href="https://github.com/gavalar/TP-ZF1-CustomElements" title="ZF1-CustomElements">ZF1-CustomElements</a>, this is a fully working example of the above code, which also includes the pre-filling of the select from a database table.  Hopefully this has given you some ideas for creating more manageable forms in your ZF1 projects, do let me know in the comments what you think!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F&amp;title=Custom+Zend+Framework+Form+Elements" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F&amp;title=Custom+Zend+Framework+Form+Elements" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F&amp;title=Custom+Zend+Framework+Form+Elements" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F&amp;headline=Custom+Zend+Framework+Form+Elements" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Custom+Zend+Framework+Form+Elements&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Custom+Zend+Framework+Form+Elements&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Custom+Zend+Framework+Form+Elements&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Custom+Zend+Framework+Form+Elements&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Custom+Zend+Framework+Form+Elements&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F&amp;title=Custom+Zend+Framework+Form+Elements&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F31%2Fcustom-zend-framework-form-elements%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/07/31/custom-zend-framework-form-elements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Do You Need A Multiregion Website Deployment?</title>
		<link>http://techportal.inviqa.com/2012/07/09/do-you-need-a-multiregion-website-deployment/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=do-you-need-a-multiregion-website-deployment</link>
		<comments>http://techportal.inviqa.com/2012/07/09/do-you-need-a-multiregion-website-deployment/#comments</comments>
		<pubDate>Mon, 09 Jul 2012 08:18:52 +0000</pubDate>
		<dc:creator>Adam Smith</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[availablity zone]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[ops]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=3819</guid>
		<description><![CDATA[In this age of cloud computing, it has become far easier to choose, or even move, the geographical location of your web server. It has also brought high-availability solutions such as hosting simultaneously in multiple locations into the reach of a even very modest applications. But where is the best place to host your site? [...]]]></description>
				<content:encoded><![CDATA[<p>In this age of cloud computing, it has become far easier to choose, or even move, the geographical location of your web server.  It has also brought high-availability solutions such as hosting simultaneously in multiple locations into the reach of a even very modest applications.  But where is the best place to host your site?  And are the improvements worth the effort of distributing your servers across the world?  </p>
<p>Armed with a few simple tools, you can come a long way to answering these questions fairly quickly.<span id="more-3819"></span></p>
<p>To begin, let's tackle the first question first.  Where is the best place to host a site?  As with most things, the answer is "it depends".  In the simplest case, all of your site's users are geographically close to one another, so you should host your site as close to them as possible.  There are a number of anecdotal examples that show reducing load times for a web page can improve user satisfaction and even sales conversion rates.  Thanks to Canadian company Strange Loop Networks, some of the key headlines from these reports have been collated into a <a href="http://www.strangeloopnetworks.com/assets/images/visualizing_web_performance_poster.jpg" target="_blank">single poster</a>.  So if you are lucky enough to have all your users together and you're not hosting close to them, do it now for a quick win.</p>
<p>If your site doesn't fall into the "all my users are in the same place" category, the best way to find out where to host is to benchmark.  My tool of choice for this is the API provided at <a href="http://webpagetest.org" target="_blank">webpagetest.org</a>.  This is an open source project, so you can download the source and set up your own version, but there is also a hosted version available to use for free, just with limits on the number of requests one person can make per day.  In order to use the hosted version you must first contact the site to request an access key, but once you've acquired that, the API itself is extremely simple to interact with.  </p>
<h3>Preparing the Setup</h3>
<p>In order to run speed tests, you first need a test server setup.  When running through this process myself I was trying to establish a good place to host servers for the <a href="http://www.wfp.org/" target="_blank">UN's World Food Programme</a>.  Inviqa have been tasked with re-architecting the API that underlies their online fundraising efforts.  The API must be responsive globally, but there is a particular focus on keeping the administration tasks performed in Asia quick.</p>
<p>Four potential server locations were identified, each was one of Amazon's EC2 regions.  A server instance was booted in each of the four locations using a standard EC2 image.  No modifications were made to the server, other than to place an identical 7KB PNG image, taken from one of the client's existing websites, into a web accessible folder.  Tests were then run, in the manner outlined below, against each of these four instances from nine locations around the world.</p>
<div id="attachment_3869" class="wp-caption alignnone" style="width: 310px"><a href="http://techportal.inviqa.com/wp-content/uploads/2012/07/sample-image-e1342539100191.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/sample-image-e1342539100191-300x62.png" alt="" title="image for testing" width="300" height="62" class="size-medium wp-image-3869" /></a><p class="wp-caption-text">the image used for testing</p></div>
<p>You can find the code for all the code examples in this article on github at: <a href="https://github.com/ams2435/WebTest" target="_blank">https://github.com/ams2435/WebTest</a></p>
<h3>Running the Tests</h3>
<p>Using functions built directly in to PHP, we can communicate with the API in a very simple manner.  The <code>file_get_contents()</code> function is capable of reading directly from a URL and the API we're interacting with takes all of its parameters from the query string, so we can grab data with just one function call.  This is a quick and dirty solution to the problem, but it works well for this example.  </p>
<p>The parameters we will pass to the API are:</p>
<table>
<tr>
<th>Parameter</th>
<th>Description</th>
<th>Value used</th>
</tr>
<tr>
<td>f</td>
<td>The format of the response</td>
<td>xml</td>
</tr>
<tr>
<td>k</td>
<td>The access key for the API</td>
<td>The access key we obtained to access the API</td>
</tr>
<tr>
<td>fvonly</td>
<td>Tell the API whether we only require a “first view” of the test URL.  The API can run a “second view” of the same URL for each test, which will show us the load times after any browser caching has taken place</td>
<td>1, for these tests we are not interested in finding out the speed of the cached version</td>
</tr>
<tr>
<td>runs</td>
<td>How many times to repeat the test </td>
<td>5</td>
</tr>
<tr>
<td>location</td>
<td>The location and speed profile for the test runs</td>
<td>Various locations, each with a DSL speed profile – the equivalent of using a 1.5Mbps broadband connection.<br />
The full list of locations can be obtained at http://www.webpagetest.org/getLocations.php</td>
</tr>
<tr>
<td>url</td>
<td>The URL to test</td>
<td>Various URLs representing each test server</td>
</tr>
</table>
<p></p>
<p>Since we are requesting our result in XML format, we will also want to convert the returned string using the <code>simplexml_load_string()</code> function.  Putting this together gives us the following code snippet:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> _runLocation<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$location</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$xml</span> <span style="color: #339933;">=</span> <span style="color: #990000;">simplexml_load_string</span><span style="color: #009900;">&#40;</span>
        <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'http://www.webpagetest.org/runtest.php?'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'f=xml'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'&amp;fvonly=1'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'&amp;runs=5'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'&amp;location='</span><span style="color: #339933;">.</span><span style="color: #000088;">$location</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'.DSL'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'&amp;k=PERSONAL-API-KEY'</span>
            <span style="color: #339933;">.</span><span style="color: #0000ff;">'&amp;url='</span><span style="color: #339933;">.</span><span style="color: #000088;">$url</span>
        <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$xml</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">statusCode</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'200'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$xml</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">testId</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>You can see from the above that we are sending off the request to the API and receiving a <code>testId</code> in response.  This is due to the asynchronous nature of the web test API; the test will not have actually been completed yet. We can use the returned <code>testId</code> to ask for the results once the test has completed, so we need to store this somewhere so that we know what results we still need to gather.</p>
<p>You may already have noticed that the above code is wrapped in a protected function, this function is called from the following piece of code:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WebTest_Database_Connection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_locations <span style="color: #b1b100;">as</span> <span style="color: #000088;">$location</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_urls <span style="color: #b1b100;">as</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$testId</span> <span style="color: #339933;">=</span>  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_runLocation<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$location</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'INSERT INTO Runs 
                    VALUES (&quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$testId</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;,
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$url</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;, 
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$location</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;, 
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d G:i:s'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;,
                          0)
                     '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>                
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>We are simply storing the IDs returned from the <code>_runLocation()</code> function into a database, along with the URL, location and date of the run.  You can see from the code that we're running through two nested foreach statements so we can perform the tests in a number of location/URL combinations and then compare the results.  The two functions shown are simply wrapped up in a <code>WebTest_Runner</code> class that also has an <code>addLocation()</code> function which stores each location that is passed to it for use in the above loop.  The constructor to the class also takes an array of URLs to test.  This leaves the triggering of tests looking as simple as this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$runner</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WebTest_Runner<span style="color: #009900;">&#40;</span>
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'http://test-url-1.com'</span><span style="color: #339933;">,</span>
                <span style="color: #0000ff;">'http://test-url-2.com'</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$runner</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addLocation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Korea'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$runner</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addLocation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'China'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$runner</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addLocation</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Australia'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$runner</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>The code shown here triggers six tests using the web test API, one for each of the URLs in each of the locations specified.  We will then have a testId in our database for each of these tests.  Remember though that we have asked for five runs for each test, so our six test ids will actually relate to 30 individual speed tests.  </p>
<h3>Gathering the Results </h3>
<p>The next thing we have to do is obtain those test results now the tests have completed.  This is how we can do that:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">simplexml_load_string</span><span style="color: #009900;">&#40;</span>
        <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span>
            http<span style="color: #339933;">:</span><span style="color: #666666; font-style: italic;">//www.webpagetest.org/xmlResult/'.$testId.'/')</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>This will return us either the test results we have asked for, or if the results are not yet available, an error code.  We can continue to poll the API for these results as many times as we like, but in order to perform any analysis of the results it is better to store them in our own database.  The following function does just that:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> gatherResults<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WebTest_Database_Connection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$runs</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT * FROM Runs WHERE ResultsGathered = 0'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$runs</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchAllRows</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$runRow</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$run</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> WebTest_Result<span style="color: #009900;">&#40;</span><span style="color: #000088;">$runRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'TestId'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$loads</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$run</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAllLoads</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$loads</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$loads</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$runNumber</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$load</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'INSERT INTO Results 
                        VALUES (
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$runRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'TestId'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;, 
                           '</span><span style="color: #339933;">.</span><span style="color: #000088;">$runNumber</span><span style="color: #339933;">.</span><span style="color: #0000ff;">', 
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$run</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;,
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$run</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLocation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;, 
                          &quot;'</span><span style="color: #339933;">.</span><span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d G:i:s'</span><span style="color: #339933;">,</span><span style="color: #000088;">$load</span><span style="color: #339933;">-&gt;</span><span style="color: #990000;">date</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;,
                           '</span><span style="color: #339933;">.</span><span style="color: #000088;">$load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadTime</span><span style="color: #339933;">.</span>
                        <span style="color: #0000ff;">')'</span>
                         <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'UPDATE Runs 
                    SET ResultsGathered = 1 
                    WHERE TestId = &quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$runRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'TestId'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This function simply loops through all the existing testIDs we have not yet collected results for, and fetches the results.  It then stores those results in a local database, looping through each of the five runs per test id and storing them all individually.  Finally this function marks each result set we successfully download and process as having had its results gathered.  The API access shown in the previous code snippet is happening here inside the <code>WebTest_Result</code> class.</p>
<p>Once this process has been repeated a number of times, you will have built up enough test data to be able to start analysing it.  As the data is stored in an SQL database, we have the full power of SQL to analyse the results.  Making use of the <code>MIN()</code>, <code>MAX()</code> and <code>AVG()</code> functions of SQL will give results that should begin to show a picture of how your site is responding from different locations.</p>
<p>The results below are those gathered by Inviqa for the re-architecting project.</p>
<p>The times shown are the full browser load time for the image, including DNS time, connection time, data transfer time and rendering time. This is clearly not a real world test, but since we have the same simple setup in each location, it is sufficient when simply comparing the different locations. The results were collected at intervals over a three-day period and average load times in milliseconds were recorded for each location.</p>
<div id="attachment_3870" class="wp-caption alignnone" style="width: 310px"><a href="http://techportal.inviqa.com/wp-content/uploads/2012/07/response-times-e1342539222232.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/response-times-e1342539222232-300x237.png" alt="" title="response-times" width="300" height="237" class="size-medium wp-image-3870" /></a><p class="wp-caption-text">Server response times by location (click for a bigger version)</p></div>
<table>
<tr>
<th></th>
<th>
Tokyo Server
</th>
<th>
US West<br />
(Northern California) Server
</th>
<th>
EU West Server
</th>
<th>
US East Server
</th>
</tr>
<tr>
<td>
Sydney, Australia
</td>
<td>
600
</td>
<td>
855
</td>
<td>
1217
</td>
<td>
981
</td>
</tr>
<tr>
<td>
Jiangsu, China
</td>
<td>
1124
</td>
<td>
1536
</td>
<td>
3634
</td>
<td>
1888
</td>
</tr>
<tr>
<td>
Geneva, Switzerland
</td>
<td>
1213
</td>
<td>
896
</td>
<td>
537
</td>
<td>
692
</td>
</tr>
<tr>
<td>
Seoul, South Korea
</td>
<td>
736
</td>
<td>
802
</td>
<td>
1223
</td>
<td>
1056
</td>
</tr>
<tr>
<td>
London, England
</td>
<td>
1038
</td>
<td>
725
</td>
<td>
454
</td>
<td>
598
</td>
</tr>
<tr>
<td>
Los Angeles, USA
</td>
<td>
757
</td>
<td>
450
</td>
<td>
905
</td>
<td>
602
</td>
</tr>
<tr>
<td>
New York, USA
</td>
<td>
874
</td>
<td>
537
</td>
<td>
601
</td>
<td>
329
</td>
</tr>
<tr>
<td>
Sao Paolo, Brazil
</td>
<td>
1265
</td>
<td>
989
</td>
<td>
1036
</td>
<td>
749
</td>
</tr>
<tr>
<td>
Singapore
</td>
<td>
580
</td>
<td>
894
</td>
<td>
1442
</td>
<td>
1148
</td>
</tr>
</table>
<p></p>
<p>The first thing to notice is that the results back up our basic assumption that you should host as close to your users as possible.  It is clear that should all of your users be in Singapore, the best of the tested locations is the closest (Tokyo).  However, it isn't always as simple as the actual distance, due to the way the data trunk cables are laid out across the world.  Straight line distance between Seoul, South Korea and the EU West data centre in Ireland is approximately 9,000km, the distance from Seoul to the US East data centre in Virginia is in excess of 11,000km, however, as the results above show, the latency to US East from Seoul is actually lower than that to EU West.  If you wish to delve deeper into the trunk cable locations, a map can be seen at: <a href="http://www.submarinecablemap.com/" target="_blank">http://www.submarinecablemap.com/</a>. The map shows you the different potential routes data can take across oceans, something I have found interesting to look at on more than one occasion.</p>
<h3>Selecting a Server Setup</h3>
<p>Once you have collected comparable results for the locations you're interested in, it's time to select a server setup.  </p>
<h4>Sticking with a Single Location</h4>
<p>The simplest solution is to pick a single location that offers a good speed compromise for all your users.  You can see from the results that in some cases the additional expense and complexity of geographically distributing your application would bring a speed increase of fractions of a second, which isn't much of a return on your investment.  I would suggest that if you're targeting users in London and Los Angeles, rather than hosting in both EU West and US West, taking a 150ms hit from both locations and hosting in US East is a better option. After all, if you find once the application is up and running that 150ms is a deal breaker, you can always move to a more distributed approach at that point.  This approach may not follow the <a href="http://www.google.co.uk/about/corporate/company/ux.html" target="_blank">Google advice that every millisecond counts</a>, but not everyone has the resources that Google have to implement complex and expensive solutions, and there are other effective ways to speed up a site before resorting to a multi-region setup.</p>
<h4>Making it More Robust</h4>
<p>Despite picking one location, you don't have to put all your server eggs in one data centre basket.  If you decide to go with one of the Amazon regions, you will find they are all split into “Availability Zones”. An Availability Zone within a region is a completely separate data centre; Amazon offers a load-balancing service which will balance your load across these two data centres.  Then if one Availability Zone becomes unavailable, all of your load will transparently go to the other zone, making it very easy to create a highly-available solution with a level of redundancy that is far more difficult and expensive to achieve without a cloud hosting provider.  In order to distribute an application across different Availability Zones, it is usually necessary to do some data replication.  Within each region, all of Amazon's Availability Zones have high-speed connections to each other, meaning that doing this kind of data replication quickly is entirely possible.  The diagram below shows a potential server setup across two availability zones.  You can see from the diagram that the web servers should make all of their database writes to a single master in one of the zones, however, all the reads will be done from a database in the same availability zone.  </p>
<div id="attachment_3871" class="wp-caption alignnone" style="width: 280px"><a href="http://techportal.inviqa.com/wp-content/uploads/2012/07/availability-zones-e1342539241974.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/availability-zones-e1342539241974-270x300.png" alt="" title="availability-zones" width="270" height="300" class="size-medium wp-image-3871" /></a><p class="wp-caption-text">Example server setup across Availability Zones</p></div>
<p>In this setup, if Availability Zone 2 becomes unavailable, nothing needs to be done for the application to continue running.  If Availability Zone 1 becomes unavailable, the database slave must be promoted to be the master, but then the rest of the setup will continue working as expected.  If you're using both a MySQL database and EC2, you might even want to look at the <a href="http://aws.amazon.com/rds/" target="_blank">Amazon RDS offering</a>.  RDS can do this data replication across availability zones for you with virtually zero maintenance effort, including automatic slave promotion and recovery.</p>
<h4>Utilising a Content Delivery Network</h4>
<p>No matter where you decide to locate your servers, there are other tricks you can employ to  improve page load times.  A good place to start is to employ a content delivery network (CDN).  This is essentially distributing across many different locations, but only static resources are distributed.  It is very often the case that the slowest part of a page load is receiving all the images, JavaScript and CSS files associated with the page.  By adding these resources to a CDN, the user will load them from the nearest location to them and see a performance increase, but you haven't had to do anything complicated to make the application truly multi-region.  There are many different providers offering CDN solutions, they work by using a DNS trick to route the client to the fastest responding location for a domain name.  This means you could set “images.mydomain.com” as the root address of your CDN, then reference all the images in your site with that subdomain; they will then always load from the fastest location for each user.</p>
<p>In addition to employing a CDN for your own static resources, if the resources are common resources, for example the base <code>jquery.js</code> file, loading it from a public CDN will offer the potential benefit of a user already having a cached copy before theyvisit your site for the first time – this really is a free performance boost as it's difficult to ask for better than a locally-cached copy of a resource in terms of speed.  This works due to many different sites using the exact same URL for the resource, so as far as the browser is concerned it has already loaded it.  Google's public libraries are very popular for this, a full list of those available can be seen at <a href="https://developers.google.com/speed/libraries/devguide">https://developers.google.com/speed/libraries/devguide</a>.</p>
<h4>Full Multi-region Implementation</h4>
<p>If you have a compelling reason to go for a full multi-region setup, it is possible to use the same principles that CDNs employ to direct your users to the nearest server setup you have.  The technique is called “latency-based routing”.  There are a number of providers of such routing, and a recent entry into the market by Amazon, as part of its Route 53 DNS offering, is likely to make the practice more common.  The advantage of using Amazon's Route 53 service for this is how simple it is to integrate with the other Amazon services.  To implement latency based routing, you set your application up in as many different locations as you require and then tell the routing service where all of your locations are.  When a user hits your master URL, the location that will serve the user the quickest is automatically calculated, and the user is directed to that location.</p>
<div id="attachment_3879" class="wp-caption alignnone" style="width: 310px"><a href="http://techportal.inviqa.com/wp-content/uploads/2012/07/locations-e1342539257906.png"><img src="http://techportal.inviqa.com/wp-content/uploads/2012/07/locations-e1342539257906-300x170.png" alt="" title="locations" width="300" height="170" class="size-medium wp-image-3879" /></a><p class="wp-caption-text">Users are directed to the quickest location when employing latency-based routing with servers distributed around the world</p></div>
<p>The real difficulty with setting up your application this way is trying to share the data between all the locations – it is not simply enough to assume that a user will always hit the same location.  Even if your locations never go down, someone might need to get at their data while they are travelling, or something could happen to a key piece of infrastructure that suddenly makes a different location respond quicker to a user.  You can see from the diagram above just how complicated the synchronisation of data could be.  For the four server locations that have been selected, represented by large dots on the diagram, six different synchronisation paths exist.  It is this synchronisation of data that makes full multi-region setups incredibly complex.  While it is possible to set up a master-slave replication in the same way we would to have the application work across multiple availability zones, the network latency is likely to be far too much of a limiting factor; any speedup that had been achieved by hosting multi-region will be lost.  It is therefore necessary to utilise a master-master replication policy, which tends to require a much greater level of maintenance and is very easy to get wrong!</p>
<h4>Keeping a Master Region</h4>
<p>Maintaing a master region is a less daunting route to creating a multi-region setup.  This is very much like having a single location setup, but with some extra server power making sure that the really important transactions are kept speedy.  This approach relies heavily on having an asynchronous architecture within your application.  The key here is making it appear to the end user as though the actions have been completed quickly, even if they haven't yet been completed.  Rather than waiting for a set of database queries to run before returning a response to the user, respond immediately to say the request is being handled.  You can then push the request onto a queue, which the master location will pick up and process.  While this doesn't eliminate the need to communicate across the world on each request, the user is not waiting for that communication to take place, thus keeping the experience fast and keeping satisfaction high.  </p>
<p>A major drawback of this solution is ending up with an inconsistent experience for users.  While most requests can easily be queued for actioning later, some things cannot wait.  If a user wants to pay for a product, we can't ask them to wait a few minutes while we catch up before taking the credit card details!  This means that these immediately-required processes will have slower response times than the rest of the application, due to having to make the user wait for the requests to travel to the master region.  Still, with some clever usage of caching, this solution can be really attractive.  If you truly have a requirement for global distribution of servers, this option strikes a nice compromise between complexity and performance.</p>
<h3>Conclusion</h3>
<p>We began our journey with two questions to answer.  Hopefully I've been able to show you that picking a location to host your site is fairly simple once you know where your users are.  The thing I'd most like you to take away from reading this article is that selecting the location for your server is an important decision.  There is a vast range of different providers and locations that you could pick, and selecting the right one could make a huge difference to your end users.</p>
<p>Is it worth distributing your servers across the world?  I think in most cases the answer to this question is no.  It's important to make your site work as fast as possible; sales can be increased and users made happy by even modest improvements to response times.  However, the added complexity and cost of distributing your site across the world must be considered carefully.  If you will be selling a product specifically to customers in the UK, do you need the website that sells it to run just as quickly for users in Australia?  If you have a compelling case for a multi-region deployment, keeping a single master region is my advice.  Slave front-ends in locations that need speeding up and a content delivery network to distribute your static content will keep your users happy most of the time.</p>
<p>Finally, if you've never run a speed test against your site using <a href="http://webpagetest.org">webpagetest.org</a> or a similar service, I urge you to do it at least once.  I've only really talked about the page load times reported by the API here, but the web interface is excellent for running one-off tests.  The wealth of information and recommendation the site is able to offer is well worth the couple of minutes it takes to type your site's URL into a text box and wait for the test to run.</p>
<h3>Code Samples</h3>
<p>Remember that all the code examples in this article are available on github at: <a href="https://github.com/ams2435/WebTest" target="_blank">https://github.com/ams2435/WebTest</a></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F&amp;title=Do+You+Need+A+Multiregion+Website+Deployment%3F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F&amp;title=Do+You+Need+A+Multiregion+Website+Deployment%3F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F&amp;title=Do+You+Need+A+Multiregion+Website+Deployment%3F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F&amp;headline=Do+You+Need+A+Multiregion+Website+Deployment%3F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F&amp;title=Do+You+Need+A+Multiregion+Website+Deployment%3F&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F07%2F09%2Fdo-you-need-a-multiregion-website-deployment%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/07/09/do-you-need-a-multiregion-website-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conference Report: MongoDB UK</title>
		<link>http://techportal.inviqa.com/2012/06/28/conference-report-mongodb-uk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=conference-report-mongodb-uk</link>
		<comments>http://techportal.inviqa.com/2012/06/28/conference-report-mongodb-uk/#comments</comments>
		<pubDate>Thu, 28 Jun 2012 13:15:22 +0000</pubDate>
		<dc:creator>John Cleary</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[london]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mongouk]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=3847</guid>
		<description><![CDATA[The 4th annual UK conference for MongoDB developers was hosted by 10gen at the Mermaid Conference Centre in London's Blackfriars. With four tracks running throughout the day - both technical and non-technical, in addition to an "ask the experts" drop-in track, choosing which talks to visit was always going to be a challenge! Keynote Eliot [...]]]></description>
				<content:encoded><![CDATA[<p>The 4th annual UK conference for MongoDB developers was hosted by 10gen at the Mermaid Conference Centre in London's Blackfriars. With four tracks running throughout the day - both technical and non-technical, in addition to an "ask the experts" drop-in track, choosing which talks to visit was always going to be a challenge!<br />
<span id="more-3847"></span></p>
<h3>Keynote</h3>
<p><b>Eliot Horowitz, Co-Founder and CTO 10gen</b></p>
<p>The Keynote from Horowitz was excellent and pitched just right. There were around 530 delegates at the conferences this year, and with MongoDB still being a relatively new tool, many will have been attending for the first time (myself included). The talk covered the history and rapid growth of MongoDB as a database as well as 10gen as a company. The company was set up back in 2007 by Eliot and Dwight, and for the first 2 years it was just these two guys. Four years later 10gen now has 140 staff - 17 in Europe alone (most of whom appeared to be at the conference!)</p>
<p>Eliot also covered some of the key design considerations behind MongoDB.  These included being easy to setup, easy to scale, and doing the right thing right out of the box. Having used MongoDB in a production environment I can testify that these claims are true.</p>
<h3>Schema Design by Example </h3>
<p><b>Christian Kvalheim, 10gen</b></p>
<p>Christian gave a useful account of the importance of schema design with reference to performance and scalability, the detail of which is beyond the scope of this article.   For me, however, two key points came out of this talk. </p>
<p>The first of these is that although it's important to have a good design for performance reasons, it is possible (and in principle straight-forward) to change the design over time. The speaker gave some very good examples of this. </p>
<p>The second interesting point is that noSQL Design Patterns are emerging, which can only be a good thing. With new technology such as this, it's often tempting to wade in and start playing around with the fun stuff.  However, as professionals we should always be looking for reusable solutions. I have no doubt that the blogosphere will see articles about noSQL Design Patterns in the months ahead.</p>
<h3>MongoDB on Innovation Projects / Products</h3>
<p><b>Noberto Leite, Telefonica R&amp;D</b></p>
<p>It is refreshing to know that not all the talks at this conference were technical. As much as I love geekery, it's also great to hear how other companies are using MongoDB and what they are using it for. Although Telefonica have only been using MongoDB for little over a year, Noberto was able to give plenty of examples of the kinds of projects they had undertaken. Of particular interest was a project which had originally been developed using Oracle at the back end, and had taken two years to complete. The system was slow and deemed not fit for purpose so it had to be rebuilt from scratch, this time using MongoDB. The new system was around 15 times faster and only took 3 months to build. Definitely a win for MongoDB!</p>
<h3>MongoDB for Online Advertising at AOL</h3>
<p><b>Jonathan Reed, AOL</b></p>
<p>Back in the main auditorium, Jonathan Reed from AOL explained how they built an analytics engine for their online advertising arm Advertising.com. They store huge amounts of global user-tracking data across multiple regions. Interestingly they employed a clever sharding tactic whereby the data was sharded by region, but replicated to the neighbouring regions. This approach allowed for very fast local writes, but still gave the failover if the regional node was unavailable. Overall this was a very interesting talk that demonstrated the power and flexibility of MongoDB.</p>
<h3>Ask the Experts</h3>
<p>During the lunch break I spoke to a couple of the exhibitors including Cloud Foundry and Equal Experts. 10gen were also offering an "Ask the Experts" drop-in session where you can....well...ask the experts! I grabbed the opportunity to ask a few high-level questions about MongoDB. I was interested to know what the typical use cases are for MongoDB. I got the usual response of archiving, logging, high volume, high availability but interestingly they also came back with "any application where you may need to quickly change the type of data you store". Hmmmm - isn't that anything built using Agile techniques? </p>
<p>This led to my next question – what percentage of new apps being built today should be considering MongoDB for some or all of their data persistence? In my head I was expecting to hear a figure like 10%, but the response surprised me. Although not committing to a figure, when I suggested 50% they didn't flinch. As the day went on I became less and less surprised by that figure.</p>
<p><a href="http://www.flickr.com/photos/mongodb/7416221006/" title="MongoDB UK 2012 Conference by mongodb, on Flickr"><img src="http://farm9.staticflickr.com/8028/7416221006_b0e5472281_n.jpg" width="320" height="212" alt="MongoDB UK 2012 Conference"></a></p>
<h3>The New Aggregation Framework</h3>
<p><b>Ross Lawley, 10gen</b></p>
<p>One of the most exciting additions for developers in the upcoming 2.2 release is the new Aggregation Framework. Once you've seen it you'll understand why. Not only is it around 25 times faster than the equivalent map-reduce functions, but you can run multiple aggregations simultaneously. If you've ever experienced the pain of trying to craft a map-reduce function, you'll be pleased to know that the aggregation framework is very simple to use. Ross ran an excellent talk taking us from the simplest <code>$count</code> and <code>$sum</code> functions, right through to document-specific functions such as <code>$unwind</code>. The real beauty of the framework is how functions can be chained together in what are known as a pipelines, similar to the way you might perform sub-selects in SQL.</p>
<p>I spoke to Ross briefly afterwards and his belief was that the aggregation framework would eventually replace map-reduce altogether due to its flexibility, speed and ease of use.</p>
<h3>Six Months of MongoDB at Nokia Bristol</h3>
<p><b>Tom Coupland, Nokia</b></p>
<p>Another non-technical talk (I told you there were a few) catalogued the experience of one team's adoption of MongoDB. The background to this story was that the team were spending too many of their days dealing with ORM-related issues and had come to the conclusion that far too much of their time was spent doing things other than delivering features. They assembled a crack team of "devops" people to get buy-in and build knowledge across departments from the very beginning. Furthermore, they threw all of these interested parties into the same room, hooked one computer up to a projector and designed the architecture and schemas as a team! What an amazing way to get everyone up-to-speed and invested at the same time.</p>
<h3>Why the Schema Diagram is Ruining Enterprise Computing</h3>
<p><b>Sean Reilly, Equal Experts</b></p>
<p>Having spoken to Sean earlier in the day, I decide to go along to this talk to see what it was all about. Sean is a very entertaining speaker and knows how to convey his message. The gist of the talk was that if you have a schema diagram there are 3 things you should not do with it.</p>
<ol>
<li>Mistake a schema diagram (which is a model of the persistence layer) for a model of the application.</li>
<li>Share the schema diagram with anyone outside your team.</li>
<li>Put it on a wiki where it can be seen by everyone.</li>
</ol>
<p></p>
<p>Why not? Because as soon as you do that, someone will login to your database and read your data. This all sounds reasonable ... until one day you decide to make a tiny change to your data model. It's at this point you will be told that you can't because someone else is reading from it and it will break everything! Sounds like a nightmare, but the solution is thankfully rather simple. The answer is force everyone to use an API to access your data. At one point Sean got the whole room to chant "The schema diagram is an implementation detail which you do not need to know". Brilliant!</p>
<p>Sean also produced two marvellous text-to-speech videos that had the whole room in stitches. They depicted the "without an API" and "with an API" scenarios. As soon as these videos are available online I'll post a link in the comments below.</p>
<h3>Mobilize Your MongoDB! Developing iPhone and Android Apps in the Cloud</h3>
<p><b>Marek Jelen, OpenShift</b></p>
<p>These days it seems as if every man and his dog are offering cloud hosting and/or PaaS - and Red Hat are no exception. Marek bravely did a live demo of building an Android app powered by a Ruby back-end all hosted on the OpenShift platform. Barring a couple of minor DNS gremlins, Marek got the whole platform up and running during the talk. OpenShift is a pretty sweet platform and with the backing of Red Hat, its bound to make a big splash in the PaaS pool.</p>
<h3>Sharding Best Practices</h3>
<p><b>Daniel Roberts, 10gen</b></p>
<p>What was perhaps surprising about this talk is that Daniel opened with a list of alternatives to sharding. The logic being that although sharding is amazing and offers huge potential for linear scaling, it also adds complexity to your architecture, and to some extent your code. If you can solve your performance issues by either a redesign of your schema, by adding an index or through buying better hardware, you can at the very least postpone the need to shard your collection.</p>
<p>Following on from that, the speaker looked at some of the best practices in sharding (the clue was in the title I guess), including the idea of choosing a sharding key based on region to give local writes, which can greatly improve performance. If you were just on the brink of sharding some or all of your database, then this talk would have been perfect for you. With a talk of this nature it could have been tricky to hold the audiences' attention for a full 40 minutes, but Daniel's deep understanding of the topic coupled with his accessible presentation style made this talk whiz by.</p>
<h2>Thank You and Road Map</h2>
<p><b>Eliot Horowitz, Co-Founder and CTO 10gen</b></p>
<p>Eliot wrapped up the day whilst holding a pint in his hand. He set the tone for the evening ahead (a five bar pub crawl). As Eliot put it "I'm having a drink now so you can too".  Indeed many delegates did listen to the wrap-up whilst sipping beer . </p>
<p>The CTO of 10gen reminded us that although they are all still hard at work fixing bugs and adding features, we should still continue to hassle them with request for the stuff we wanted. The next release, due any day now, will include the aggregation framework, time-to-live collections (where documents can be told when to expire - great for caches et al), in addition to some pretty clever internal stuff that will improve concurrency, reduce fragmentation and generally make everything faster – wow!</p>
<p>On the shortlist for future releases include the long-awaited full text search, more concurrency, online compaction, internal compression and some more security options such as LDAP auditing. </p>
<h3>Summary</h3>
<p>This was my first MongoDB conference – in fact it was my first database conference full stop. To some extent I did not know what to expect. Actually that's a complete lie! I totally expected back-to-back technical talks and hands on sessions. And if that's what you go to a MongoDb conference for then you wouldn't have been disappointed. However, there was much more besides. </p>
<p>Something else that was mentioned by many of the speakers (no, not just the ones from 10gen) was how great the documentation and support were - both the paid-for support from 10gen and the active community blogs and forums. </p>
<p>The opening and closing talks by Eliot Horowitz showed us how far we've come and where we're heading. Although MongoDB has been around for a few years now, the first release that was considered production-ready only came out in April 2011. Looking at the “Who's Who” of MongoDB users; AOL, Nokia, MTV, Foursquare – the list goes on, on thing is for sure - it's is not a fad. MongoDB is here to stay!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F&amp;title=Conference+Report%3A+MongoDB+UK" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F&amp;title=Conference+Report%3A+MongoDB+UK" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F&amp;title=Conference+Report%3A+MongoDB+UK" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F&amp;headline=Conference+Report%3A+MongoDB+UK" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Conference+Report%3A+MongoDB+UK&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Conference+Report%3A+MongoDB+UK&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Conference+Report%3A+MongoDB+UK&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Conference+Report%3A+MongoDB+UK&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Conference+Report%3A+MongoDB+UK&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F&amp;title=Conference+Report%3A+MongoDB+UK&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F28%2Fconference-report-mongodb-uk%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/06/28/conference-report-mongodb-uk/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tips for Vagrant and Chef</title>
		<link>http://techportal.inviqa.com/2012/06/26/tips-for-vagrant-and-chef/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tips-for-vagrant-and-chef</link>
		<comments>http://techportal.inviqa.com/2012/06/26/tips-for-vagrant-and-chef/#comments</comments>
		<pubDate>Tue, 26 Jun 2012 07:30:26 +0000</pubDate>
		<dc:creator>Nick Peirson</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[chef]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[knife]]></category>
		<category><![CDATA[puppet]]></category>
		<category><![CDATA[virtualisation]]></category>

		<guid isPermaLink="false">http://techportal.inviqa.com/?p=3807</guid>
		<description><![CDATA[For those of you cooking up a storm with Vagrant and Chef, these tips might help when creating your VMs (Virtual Machines). These are things that we've discovered and found useful while working on projects at Inviqa. If we thought they were useful, we thought you might too! Keep Your Base Boxes Up To Date [...]]]></description>
				<content:encoded><![CDATA[<p>For those of you cooking up a storm with <a href="http://vagrantup.com/" title="Vagrant" target="_blank">Vagrant</a> and <a href="http://www.opscode.com/chef/" title="Chef" target="_blank">Chef</a>, these tips might help when creating your VMs (Virtual Machines). These are things that we've discovered and found useful while working on projects at Inviqa. If we thought they were useful, we thought you might too!</p>
<p><span id="more-3807"></span></p>
<h2>Keep Your Base Boxes Up To Date</h2>
<p>If you're working on a long-lived project using Vagrant boxes, chances are you set up your base box, spent some time getting it configured how you liked, then forgot about it. If part of your provisioning process is to bring packages up to date, then the longer your project runs, chances are the longer this step takes, due to getting more updates. If you rarely rebuild your box you probably won't notice this, but if you regularly 'destroy' and 'up your box, this can be reduced by updating your base box to include these updates. New developers to your project will also thank you for not spending hours watching updates scroll past, or maybe they won't - if they were hoping for an extra coffee break ;)</p>
<p>To take this even further, you could use <a href="https://github.com/jedi4ever/veewee" title="VeeWee" target="_blank">VeeWee</a> to build a custom box with all the packages pre-installed, further shortening the provisioning step.</p>
<h2>Vagrantfile - not just static configuration!</h2>
<p>One realisation we came to on a couple of projects independently, and have since discussed and refined, is the the Vagrantfile is executed rather than just read. This happens early in the start up process, so it's a quick way to check that resources are available rather than waiting for half an hour while your VM builds and provisions, only to find that you forgot to place your custom widget config in your dooberry directory and, apart from the tweets you read in the lull, you've just lost the last half an hour.</p>
<p>This is very useful where you have multiple VMs on a project and want to share config between them without duplicating the config in each block:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">Vagrant::Config</span>.<span style="color:#9900CC;">run</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'UNIQUE_KEY'</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#9966CC; font-weight:bold;">then</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;The UNIQUE_KEY environment variable must be set to a unique
value within the project, i.e. your username&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">exit</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  nfs_status = <span style="color:#006600; font-weight:bold;">&#40;</span>ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'WINDOWS'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> ? <span style="color:#0000FF; font-weight:bold;">false</span> : <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">#Share the code from host</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">share_folder</span> <span style="color:#996600;">&quot;Sites&quot;</span>, <span style="color:#996600;">&quot;/mnt/Sites&quot;</span>, <span style="color:#996600;">&quot;#{ENV['HOME']}/Sites&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:nfs</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> nfs_status
  <span style="color:#008000; font-style:italic;">#Put some cached files on the host to save downloading on rebuild</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">share_folder</span> <span style="color:#996600;">&quot;chef-cache&quot;</span>,
                         <span style="color:#996600;">&quot;/var/chef/cache&quot;</span>,
                         <span style="color:#996600;">&quot;#{ENV['HOME']}/Sites/tmp/chef/cache&quot;</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">share_folder</span> <span style="color:#996600;">&quot;chef-file-store&quot;</span>,
                         <span style="color:#996600;">&quot;/srv/chef/file_store&quot;</span>,
                         <span style="color:#996600;">&quot;#{ENV['HOME']}/Sites/tmp/chef/file-store&quot;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">#Common config shared between multiple VMs</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> shared_chef_config<span style="color:#006600; font-weight:bold;">&#40;</span>chef<span style="color:#006600; font-weight:bold;">&#41;</span>
    chef.<span style="color:#9900CC;">chef_server_url</span> = <span style="color:#996600;">&quot;https://api.opscode.com/organizations/inviqa&quot;</span>
    chef.<span style="color:#9900CC;">validation_key_path</span> = <span style="color:#996600;">&quot;~/Sites/inviqa/tools/chef/.chef/inviqa.pem&quot;</span>
    chef.<span style="color:#9900CC;">validation_client_name</span> = <span style="color:#996600;">&quot;inviqa&quot;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Set the environment for the chef server</span>
    chef.<span style="color:#9900CC;">environment</span> = <span style="color:#996600;">&quot;development&quot;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Put the client.rb in /etc/chef so chef-client can be run w/o specifying</span>
    chef.<span style="color:#9900CC;">provisioning_path</span> = <span style="color:#996600;">&quot;/etc/chef&quot;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># logging</span>
    <span style="color:#008000; font-style:italic;"># chef.log_level = :debug</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> set_node_name<span style="color:#006600; font-weight:bold;">&#40;</span>chef, node_name<span style="color:#006600; font-weight:bold;">&#41;</span>
    chef.<span style="color:#9900CC;">node_name</span> = <span style="color:#996600;">&quot;#{ENV['CLIENT_KEY_NAME']}-#{node_name}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">#Web VM</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">define</span> <span style="color:#ff3333; font-weight:bold;">:web</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>web_config<span style="color:#006600; font-weight:bold;">|</span>
    web_config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">network</span> <span style="color:#ff3333; font-weight:bold;">:hostonly</span>, <span style="color:#996600;">&quot;192.168.10.50&quot;</span>
    web_config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">provision</span> <span style="color:#ff3333; font-weight:bold;">:chef_client</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>chef<span style="color:#006600; font-weight:bold;">|</span>
      shared_chef_config chef
      set_node_name<span style="color:#006600; font-weight:bold;">&#40;</span>chef, <span style="color:#996600;">&quot;web&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      chef.<span style="color:#9900CC;">add_role</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;web&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">#API VM</span>
  config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">define</span> <span style="color:#ff3333; font-weight:bold;">:api</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>api_config<span style="color:#006600; font-weight:bold;">|</span>
    api_config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">network</span> <span style="color:#ff3333; font-weight:bold;">:hostonly</span>, <span style="color:#996600;">&quot;192.168.10.51&quot;</span>
    api_config.<span style="color:#9900CC;">vm</span>.<span style="color:#9900CC;">provision</span> <span style="color:#ff3333; font-weight:bold;">:chef_client</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>chef<span style="color:#006600; font-weight:bold;">|</span>
      shared_chef_config chef
      set_node_name<span style="color:#006600; font-weight:bold;">&#40;</span>chef, <span style="color:#996600;">&quot;api&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      chef.<span style="color:#9900CC;">add_role</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;api&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<h2>knife_ec2 - Not the Sharpest Tool in the Box</h2>
<p>I've been doing some work with chef and EC2 and have found a few idiosyncrasies that can make it <em>challenging</em> to use. It works really well for what it does, firing up EC2 instances and bootstrapping chef onto them. Where I ran into problems was trying to script EC2 instances to start using <code>knife ec2 server create</code>. I'd gotten fed up of typing a command line as long as my arm and, as is sensible, put the defaults into my knife.rb config file. Once I was happy with how it was working, I sprinkled a few of these commands judiciously through a script and ran it. These calls to knife were config driven, so they had the full command line with different options to start different AMIs, different AMIs in different regions along with various other things.</p>
<p>To my surprise, all these options were blissfully ignored in favour of my config file.</p>
<p>This behaviour was so unexpected that it took me a little while to spot it. I was busily debugging my script thinking I'd made a typo somewhere, or was loading the wrong config. Hopefully, forewarned will be forearmed and you won't fall into this trap, unlike the many others who have previously when I raised it on the chef mailing list.</p>
<p>If you want to keep an eye on it, there is a <a href="http://tickets.opscode.com/browse/CHEF-1772" title="command line argument switches should override configuration file information in knife.rb" target="_blank">bug raised against it</a> on the Chef bug tracker. Time permitting, I hope to brush up on my Ruby skills and pitch in to help on this, rather than just moaning about what is otherwise a great knife plugin, but I'm happy for someone else to get there first.</p>
<h2>Does Your Source Control Match Your Deployed Recipes?</h2>
<p>When working with chef, you quickly find out the pitfalls of having changes made through the opscode GUI and changes being pushed to your organisation via knife. With good discipline you can push all changes from files via knife and commit the changes back to source control. However, we all know <em>other</em> developers who are not as rigorous as <em>us</em>. If you don't this may be you, dear reader, and it's time to mend your ways.</p>
<p>Whether you're a lone developer trying to implement good practices, or working on a larger project where you're trying to <del datetime="2012-06-25T19:00:31+00:00">enforce</del> encourage them, <a href="http://bmarini.github.com/health_inspector/" target="_blank">health_inspector</a> is a useful tool to do this.</p>
<p>It allows a quick comparison between your local repository and your chef server to check that your files are in sync. It's a relatively young project, so may be a little rough round the edges, but the developer is active and responded quickly when I identified a few bugs, fixing them quickly and providing a new release.</p>
<p>When discussing this with a colleague, he mentioned a useful knife plugin for bringing out of sync chef repos back into sync, <a href="https://github.com/Fotolia/knife-align" target="_blank">knife-align</a>. The guys behind that have also developed <a href="https://github.com/Fotolia/knife-consistency" target="_blank">knife-consistency</a> which looks to do a similar job to health_inspector in a knife plugin. I've not had a chance to look at it either of these yet, but being aware of all the tools at hand puts you in a better position to solve the problem, should it arise.</p>
<h2>Over to You!</h2>
<p>Are you doing something interesting with Vagrant and/or Chef?  While we've been using these tools for a while now, we're still refining our approach and sharing our findings between projects. By sharing them with you, hopefully you'll figure out new things to do and share them with us. If you've got any interesting techniques or improvements on those listed above, please comment as we're always looking for new and interesting uses for technology.</p>
<p><i>If this sounds like the sort of thing you're interested in doing, Inviqa are hiring across the UK, so drop us a line at <a href="mailto:careers@inviqa.com">careers@inviqa.com</a> and come and contribute.</i></p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F&amp;title=Tips+for+Vagrant+and+Chef" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F&amp;title=Tips+for+Vagrant+and+Chef" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F&amp;title=Tips+for+Vagrant+and+Chef" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F&amp;headline=Tips+for+Vagrant+and+Chef" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Tips+for+Vagrant+and+Chef&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Tips+for+Vagrant+and+Chef&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Tips+for+Vagrant+and+Chef&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Tips+for+Vagrant+and+Chef&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Tips+for+Vagrant+and+Chef&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F&amp;title=Tips+for+Vagrant+and+Chef&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F06%2F26%2Ftips-for-vagrant-and-chef%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/06/26/tips-for-vagrant-and-chef/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>DPC Ticket Winner Announced</title>
		<link>http://techportal.inviqa.com/2012/05/11/dpc-ticket-winner-announced/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=dpc-ticket-winner-announced</link>
		<comments>http://techportal.inviqa.com/2012/05/11/dpc-ticket-winner-announced/#comments</comments>
		<pubDate>Fri, 11 May 2012 10:28:38 +0000</pubDate>
		<dc:creator>Lorna Mitchell</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[competition]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[dpc12]]></category>
		<category><![CDATA[winner]]></category>

		<guid isPermaLink="false">http://techportal.ibuildings.com/?p=3786</guid>
		<description><![CDATA[We are delighted to announce that our competition winner is Christian Schorn! Christian wins a pass which gives him access to the conference sessions for both DPC (Dutch PHP Conference) and DMC (Dutch Mobile Conference). Thanks to everyone who left awesome comments on the post, we loved hearing your stories! If you didn't win, we [...]]]></description>
				<content:encoded><![CDATA[<p>We are delighted to announce that our competition winner is Christian Schorn! Christian wins a pass which gives him access to the conference sessions for both DPC (Dutch PHP Conference) and DMC (Dutch Mobile Conference).</p>
<p>Thanks to everyone who left awesome comments on the post, we loved hearing your stories! If you didn't win, we still have some places available, so <a href="http://dpc12.paydro.net">buy your tickets </a>and we'll see you there!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F&amp;title=DPC+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F&amp;title=DPC+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F&amp;title=DPC+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F&amp;headline=DPC+Ticket+Winner+Announced" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=DPC+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=DPC+Ticket+Winner+Announced&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=DPC+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=DPC+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=DPC+Ticket+Winner+Announced&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F&amp;title=DPC+Ticket+Winner+Announced&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F11%2Fdpc-ticket-winner-announced%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/05/11/dpc-ticket-winner-announced/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Conference Report: Whisky Web</title>
		<link>http://techportal.inviqa.com/2012/05/09/conference-report-whisky-web/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=conference-report-whisky-web</link>
		<comments>http://techportal.inviqa.com/2012/05/09/conference-report-whisky-web/#comments</comments>
		<pubDate>Wed, 09 May 2012 10:16:40 +0000</pubDate>
		<dc:creator>Marco De Bortoli</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[whiskyweb]]></category>

		<guid isPermaLink="false">http://techportal.ibuildings.com/?p=3775</guid>
		<description><![CDATA[Whisky Web is a brand new, fresh conference and the 2012 edition was the inaugural event, with hopefully many more to follow. This event has some familiar names from the PHP community behind it, Juozas "Joe" Kaziukėnas and his helpers Michael Maclean, Max Manders, Dale Harvey and Paul Dragoonis. The opening keynote from Josh Holmes [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://whiskyweb.co.uk" target="_blank">Whisky Web</a> is a brand new, fresh conference and the 2012 edition was the inaugural event, with hopefully many more to follow. This event has some familiar names from the PHP community behind it, <a href="http://juokaz.com/" target="_blank">Juozas "Joe" Kaziukėnas</a> and his helpers <a href="http://mgdm.net/" target="_blank">Michael Maclean</a>, <a href="http://maxmanders.co.uk/" target="_blank">Max Manders</a>, <a href="http://arandomurl.com/" target="_blank">Dale Harvey</a> and <a href="http://www.ppi.io/" target="_blank">Paul Dragoonis</a>.</p>
<p>The opening keynote from <a href="http://www.joshholmes.com/" target="_blank">Josh Holmes</a> was about learning how to fail, because everyone has to fail, not once but many times, because it's only by failing that we learn. So please never be afraid to make mistakes and never be afraid to ask for help. That's a great way to grow up personally and professionally in this industry.</p>
<p>In contrast, <a href="http://blog.wombert.de/" target="_blank">David Zuelke</a>'s closing keynote was deeply technical. He talked about RESTful web services and how to implement them. What I liked was the fact that in contrast to the current trend, where it seems JSON is the only answer to data transfer across web services and systems, David pushed heavily towards XML and the fact that XML is more descriptive and comprehensive than a JSON data structure. He made the important point that while XML can easily represent a JSON set of data, the opposite is not necessarily true.<br />
<span id="more-3775"></span></p>
<h3>1st talk - Estimation, or "How To Dig Your Own Grave"</h3>
<p><a href="http://merewood.org/" target="_blank">Rowan Merewood </a>is not only one of my colleagues but also one of my favourite speakers. He pointed out the most common attitudes towards estimation within companies in the past, and how this affects the estimation process and the likely consequences. He then gave some solutions, some different perspectives, explained how agile can help and why.</p>
<p>During the questions section this talk higlighted how managers, as well as developers, are interested in attending these events. I think this is a good indicator that the two worlds may yet converge  to a common point of understanding.</p>
<h3>2nd Talk - Essential Node.js For Web Developers</h3>
<p><a href="http://amundsen.com/" target="_blank">Mike Amundsen</a> has all my appreciation for delivering a really comprehensive talk about Node.js. He demonstrated practical usage of Node.js in the web ecosystem, using it to render web pages and forms.   He also gave insight on how to deal with getting and posting requests and even how to handle file uploads and downloads and content streaming. This talk drew on the personal experience of one person and transformed it to motivate people to have a deeper look at Node.js and its capabilities.  Thumbs up for Mike and for Node.js.</p>
<h3>3rd Talk - The Emperor's New Clothes</h3>
<p><a href="http://kevinjohngallagher.com/" target="_blank">Kevinjohn Gallagher</a>'s talk was a very good one, but at the same time probably the one I liked the least, simply because his topic was huge and we ended up overlooking and passing very quickly through some slides that in my opinion deserved more time and attention. In an era where everyone talks about new methodology, innovation, HTML5, responsive design and everything other thing that pops into your head when you think about what are the current technical hypes, Kevinjohn explained how this rush to a brave new world is not always helpful. He presented evidence showing that often,  this tendency to upgrade and change technologies is quite unnecessary.  It does not benefit the end user, it's a huge investment for a company, and sometimes it is done just for the "fun" of it.</p>
<h3>4th Talk - Lessons Learned From Testing Legacy Code</h3>
<p><a href="http://jmertic.wordpress.com/" target="_blank">John Mertic</a> covered another very interesting topic that has touched me personally in the last few years of my career. Generally, when you go to conferences or you work abroad or you do consultancy you meet either of two scenarios: The first scenario is that of the cool people talking about testing and best practices. The second, more common, scenario is where unit test coverage is thin, where  the software is badly designed, and the basic principles of object orientation are just a dream! John refreshed our knowledge and skills on what the available tools are; how, when and why to use them in order to achieve good quality results. I'm sure this session was enlightening for many people because so much of what he covered seems unknown to so many developers.</p>
<h3>5th Talk - Is Your App Ready For The (Hybrid) Cloud?</h3>
<p><a href="http://blog.feryn.eu/" target="_blank">Thijs Feryn</a> is a proactive and engaging speaker, on the stage he tries to take the audience aboard with him in his adventure through the slides. He works for a hosting provider so getting in touch with architectural solutions and distributed systems seems to be a daily task. During his talk he described some of the cloud solutions that the current market has to offer. He talked about Amazon's Web Services, Microsoft's Azure platform, Orchestra's infrastructure and many more - giving a detailed overview of the pros and cons of every solution, depending on the requirements of your project. The Q&#038;A phase of this talk was full of interesting thoughts and possible solutions to investigate.</p>
<h3>Wrap up</h3>
<p>Attending a conference is absolutely key for any developer's professional career, knowledge and personal development, the return on your investment is very high and I cannot recommend strongly enough to people to attend a conference!  This particular conference had a nice format: one day of talks and one hackathon day.</p>
<p>At the social event on Friday, the conference was true to its name - we had a whisky tasting night.  This was the cherry on the cake and it allowed me to taste for the first time in my life a type of gin which I liked!</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F&amp;title=Conference+Report%3A+Whisky+Web" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F&amp;title=Conference+Report%3A+Whisky+Web" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F&amp;title=Conference+Report%3A+Whisky+Web" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F&amp;headline=Conference+Report%3A+Whisky+Web" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=Conference+Report%3A+Whisky+Web&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=Conference+Report%3A+Whisky+Web&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=Conference+Report%3A+Whisky+Web&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=Conference+Report%3A+Whisky+Web&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=Conference+Report%3A+Whisky+Web&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F&amp;title=Conference+Report%3A+Whisky+Web&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F05%2F09%2Fconference-report-whisky-web%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/05/09/conference-report-whisky-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DPC Radio: Keynote - The Art of the User Experience: making beautiful, delightful, fun things</title>
		<link>http://techportal.inviqa.com/2012/04/27/dpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=dpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things</link>
		<comments>http://techportal.inviqa.com/2012/04/27/dpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 08:22:40 +0000</pubDate>
		<dc:creator>dpcradio</dc:creator>
				<category><![CDATA[DPCRadio]]></category>
		<category><![CDATA[Aral Balkan]]></category>
		<category><![CDATA[dpc11]]></category>
		<category><![CDATA[inspiring]]></category>
		<category><![CDATA[keynote]]></category>
		<category><![CDATA[user experience]]></category>

		<guid isPermaLink="false">http://techportal.ibuildings.com/?p=3398</guid>
		<description><![CDATA[Aral Balkan We are the makers of the new everyday things. We design and develop the virtual pens, telephones, newspapers, calendars, and door-handles that people interact with every single day. We are the virtual architects and the products that we design and develop have the power to determine whether people have a good day or [...]]]></description>
				<content:encoded><![CDATA[<p><strong>Aral Balkan</strong></p>
<p>We are the makers of the new everyday things. We design and develop the virtual pens, telephones, newspapers, calendars, and door-handles that people interact with every single day. We are the virtual architects and the products that we design and develop have the power to determine whether people have a good day or a bad day.</p>
<p>In this session, Aral Balkan will outline the important role that user experience design plays in the making of virtual products and inspire you to see that it is your job – regardless of whether you make web sites, mobile apps, intranet systems, or ticket machines – to make this new world that we are crafting together not only usable and accessible but beautiful, fun, inspiring, pleasurable, delightful, and – dare I say – magical.</p>
<div class="lightsocial_container"><a class="lightsocial_a" href="http://digg.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F&amp;title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/digg.png" alt="Digg This" title="Digg This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.reddit.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F&amp;title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/reddit.png" alt="Reddit This" title="Reddit This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F&amp;title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/stumbleupon.png" alt="Stumble Now!" title="Stumble Now!" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://buzz.yahoo.com/buzz?targetUrl=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F&amp;headline=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/yahoo_buzz.png" alt="Buzz This" title="Buzz This" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dzone.com/links/add.html?title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dzone.png" alt="Vote on DZone" title="Vote on DZone" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.facebook.com/sharer.php?t=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;u=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/facebook.png" alt="Share on Facebook" title="Share on Facebook" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://delicious.com/save?title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/delicious.png" alt="Bookmark this on Delicious" title="Bookmark this on Delicious" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.dotnetkicks.com/kick/?title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetkicks.png" alt="Kick It on DotNetKicks.com" title="Kick It on DotNetKicks.com" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://dotnetshoutout.com/Submit?title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/dotnetshoutout.png" alt="Shout it" title="Shout it" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F&amp;title=DPC+Radio%3A+Keynote+-+The+Art+of+the+User+Experience%3A+making+beautiful%2C+delightful%2C+fun+things&amp;summary=&amp;source=" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/linkedin.png" alt="Share on LinkedIn" title="Share on LinkedIn" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://www.technorati.com/faves?add=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/technorati.png" alt="Bookmark this on Technorati" title="Bookmark this on Technorati" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="http://twitter.com/home?status=Reading+http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/twitter.png" alt="Post on Twitter" title="Post on Twitter" /></a>&nbsp;&nbsp;<a class="lightsocial_a" href="https://plus.google.com/share?url=http%3A%2F%2Ftechportal.inviqa.com%2F2012%2F04%2F27%2Fdpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things%2F" ><img class="lightsocial_img" src="http://techportal.inviqa.com/wp-content/plugins/light-social/gplus-16.png" alt="Google Plus" title="Google Plus" /></a>&nbsp;&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://techportal.inviqa.com/2012/04/27/dpc-radio-keynote-the-art-of-the-user-experience-making-beautiful-delightful-fun-things/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://dpcradio.s3.amazonaws.com/2011_013.mp3" length="55836439" type="audio/mpeg" />
			<itunes:keywords>Aral Balkan,dpc11,inspiring,keynote,user experience</itunes:keywords>
	<itunes:subtitle>Aral Balkan We are the makers of the new everyday things. We design and develop the virtual pens, telephones, newspapers, calendars, and door-handles that people interact with every single day. We are the virtual architects and the products that we des...</itunes:subtitle>
		<itunes:summary>Aral Balkan
We are the makers of the new everyday things. We design and develop the virtual pens, telephones, newspapers, calendars, and door-handles that people interact with every single day. We are the virtual architects and the products that we design and develop have the power to determine whether people have a good day or a bad day.

In this session, Aral Balkan will outline the important role that user experience design plays in the making of virtual products and inspire you to see that it is your job – regardless of whether you make web sites, mobile apps, intranet systems, or ticket machines – to make this new world that we are crafting together not only usable and accessible but beautiful, fun, inspiring, pleasurable, delightful, and – dare I say – magical.</itunes:summary>
		<itunes:author>techPortal</itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:duration>58:08</itunes:duration>
	</item>
	</channel>
</rss><!-- Dynamic page generated in 4.445 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-20 18:01:08 -->
