<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7481875957453356650</id><updated>2012-02-02T16:19:53.165-08:00</updated><category term='simplicity'/><category term='tools'/><category term='threads'/><category term='personal'/><category term='speaking'/><category term='books'/><category term='apple'/><category term='boost'/><category term='music'/><category term='games'/><category term='midi'/><category term='accu'/><category term='toys'/><category term='enigma'/><category term='audio'/><category term='iphone'/><category term='xcode'/><category term='ios'/><category term='git'/><category term='becoming better'/><category term='vim'/><category term='code'/><category term='learning'/><category term='c++'/><category term='writing'/><category term='uganda'/><title type='text'>Pete Goodliffe</title><subtitle type='html'>Pete's (quite specific) random stream of consciousness</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default?start-index=101&amp;max-results=100'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>199</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7683854925575078856</id><published>2012-01-11T09:53:00.000-08:00</published><updated>2012-01-11T09:53:44.474-08:00</updated><title type='text'>Writing: Coping With Complexity</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-LNVnuk4E_3o/Tw3MKyZTzJI/AAAAAAAACyM/Jy3TNLXhvTo/s1600/cvu-cover-small.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/-LNVnuk4E_3o/Tw3MKyZTzJI/AAAAAAAACyM/Jy3TNLXhvTo/s200/cvu-cover-small.png" width="142" /&gt;&lt;/a&gt;&lt;/div&gt;The January issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s CVu magazine is landing on doormats now.&amp;nbsp;It contains the latest instalment in my &lt;b&gt;Becoming a Better Programmer&lt;/b&gt; column. This one's called &lt;b&gt;Coping With Complexity&lt;/b&gt;. It an interesting wee treatise on managing (and fighting)&amp;nbsp;complexity in our&amp;nbsp;software.&lt;br /&gt;&lt;br /&gt;It's got sticks. And blobs. And people.&lt;br /&gt;&lt;br /&gt;I have to say, this month's issue is a bumper one - you never get a feel for this when reviewing the PDF &lt;a href="http://en.wikipedia.org/wiki/Galley_proof"&gt;galley proofs&lt;/a&gt;. Well done all involved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7683854925575078856?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7683854925575078856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7683854925575078856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7683854925575078856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7683854925575078856'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2012/01/writing-coping-with-complexity.html' title='Writing: Coping With Complexity'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-LNVnuk4E_3o/Tw3MKyZTzJI/AAAAAAAACyM/Jy3TNLXhvTo/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8587686511877360593</id><published>2012-01-05T05:21:00.000-08:00</published><updated>2012-01-05T05:26:03.095-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Installing Groove Agent 3 (Update from Version 1) on Mac OS Lion</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://bornemark.se/ga/img/ga3.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="161" src="http://bornemark.se/ga/img/ga3.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;It all seemed so simple.&lt;/i&gt; I wanted to install my trusty copy of &lt;a href="http://www.steinberg.net/en/products/vst/grooveagent3_product.html"&gt;Groove Agent 3&lt;/a&gt; on a new Mac OS Lion box. The license is on my &lt;a href="http://www.elicenser.net/en/"&gt;eLicenser&lt;/a&gt; already. So it should just be a quick insert-DVD-and-install job.&lt;br /&gt;&lt;br /&gt;Shouldn't it?&lt;br /&gt;&lt;br /&gt;Of course not.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;#Fail...&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I've been using Groove Agent for years now. My version 3 DVD was an &lt;i&gt;upgrade disk&lt;/i&gt; from the original version 1. If you run that DVD's installer it says you have to have version 1 installed to upgrade. That seems fair enough.&lt;br /&gt;&lt;br /&gt;Except you &lt;i&gt;can't&lt;/i&gt; install Version 1 on Lion; it is an old PPC application, and Lion doesn't support &lt;a href="http://en.wikipedia.org/wiki/Rosetta_(software)"&gt;Rosetta&lt;/a&gt; any more.&lt;br /&gt;&lt;br /&gt;It's a deadly circle; I now legitimately own some (not inexpensive) software that I can't install. Pete is not a happy bunny.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Attempt 1: tech support&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I sent a tech support email through my Steinberg account. Not with much hope, I have to admit.&lt;br /&gt;&lt;br /&gt;That was ages ago. What do you think happened?&lt;br /&gt;&lt;br /&gt;Yup, you're right. Not even got a &lt;i&gt;"we've got your message and it's in a queue"&lt;/i&gt;&amp;nbsp;reply.&lt;br /&gt;&lt;br /&gt;Thanks, Steinberg. Thanks a bunch.&lt;br /&gt;&lt;br /&gt;But where there's a will, there's a way...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Attempt 2: Check for updates on the website&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.steinberg.net/en/support/downloads/groove_agent_3.html"&gt;Groove Agent 3 support site&lt;/a&gt; has a few update installers available (which, naturally, need the full program installed first to be able to update).&lt;br /&gt;&lt;br /&gt;There is also a new "full installer" for the Mac to replace the DVD's installer for first-time users. This shows great promise.&lt;br /&gt;&lt;br /&gt;Once downloaded, I run the installer. &lt;i&gt;"Insert the Content DVD"&lt;/i&gt; it asks (impolitely). OK, again this is fair enough. The content is enormous, and is on the DVD already so I shouldn't need to download that again. It also proves that I own the product I'm installing.&lt;br /&gt;&lt;br /&gt;I insert my Groove Agent 3 DVD into the machine. The installer doesn't recognise it. No message. No hint. No continue button. It just sits there.&lt;br /&gt;&lt;br /&gt;Of course, it's looking for the "Groove Agent Installation DVD" not the "Groove Agent &lt;b&gt;Update&lt;/b&gt; Installation DVD". Swines.&lt;br /&gt;&lt;br /&gt;Absolute swines.&lt;br /&gt;&lt;br /&gt;But where there's a will, there's a way...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Attempt 3: Trick the installer&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Being a techie I wonder. I wonder how rubbish they really are... Is the installer just looking for a DVD called a certain name?&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ln -s "/Volumes/Groove Agent Update DVD" &amp;nbsp;"/Volumes/Groove Agent DVD"&lt;/span&gt;&lt;/blockquote&gt;Run the installer again.&lt;br /&gt;&lt;br /&gt;Success!!!&lt;br /&gt;&lt;br /&gt;The installer runs, it copies over the content from the DVD and there's my Groove Agent 3 sitting there, ready to run.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Goodliffe: 1, Steinberg: 0, (Steinberg Customer Support: -5)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;But, we're not there quite yet&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I fire up Cubase, pull in the virtual instrument, and a window pops up asking me to locate the content files. That's the content that the installer just installed. Into a standard place. Didn't it think to look there itself? Sheesh.&lt;br /&gt;&lt;br /&gt;That's OK, I'll just use the file browser dialogue that appears to load it.&amp;nbsp;Except that the content is automatically installed into &lt;i&gt;"&lt;b&gt;/Library/&lt;/b&gt;Application Support/Steinberg/Groove Agent".&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Notice that first bit. Yes, &lt;i&gt;"/Library"&lt;/i&gt;. The folder that Apple now &lt;b&gt;HIDES&lt;/b&gt; from users in Lion so they can't fry in innards of their OS. I physically can't navigate to the content. Genius.&lt;br /&gt;&lt;br /&gt;The trick, of course, is to launch Finder, open the "Go" menu, and hold down the &lt;a href="http://en.wikipedia.org/wiki/Command_key"&gt;Command key&lt;/a&gt;. At this point "Library" magically appears in the middle of the menu's list of places you can go to. Select that folder. Navigate to the right directory in the Finder window that appears, and then drag the target directory into the patiently waiting application's file open dialogue.&lt;br /&gt;&lt;br /&gt;What a palaver.&lt;br /&gt;&lt;br /&gt;But that's it, I now &lt;i&gt;definitely&lt;/i&gt; have Groove Agent 3 installed and running.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Whinge&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Of course, I have a &lt;i&gt;clue&lt;/i&gt; what's going on inside my computer, and was able to engineer this solution based on my experience and a selection of educated guesses. Goodness only knows what the average user would be able to make of this situation.&lt;br /&gt;&lt;br /&gt;(Hopefully this blog post will help someone in time. Let me know if it does!)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Endnote&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;It seems that every time I want to sit down an use my computer to make music, the computer wants some love, wants its nappy changed, or wants feeding first.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;i&gt;New driver required! Update available! Incompatibility detected!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Technology really&amp;nbsp;can&amp;nbsp;get in the way of being creative.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8587686511877360593?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8587686511877360593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8587686511877360593' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8587686511877360593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8587686511877360593'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2012/01/installing-groove-agent-3-update-from.html' title='Installing Groove Agent 3 (Update from Version 1) on Mac OS Lion'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2451681143638146826</id><published>2012-01-03T09:59:00.000-08:00</published><updated>2012-01-03T09:59:04.700-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Speaking: BCS Newcastle</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-EH3kMh5jt6A/R_SWHBodA-I/AAAAAAAAAA4/F8-RD393lIE/s1600/pete.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="198" src="http://3.bp.blogspot.com/-EH3kMh5jt6A/R_SWHBodA-I/AAAAAAAAAA4/F8-RD393lIE/s200/pete.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;I will be speaking at &lt;a href="http://newcastle.bcs.org/events/public/2011-12/developing-applications-for-the-iphone-ipad-and-other-ios-devices"&gt;BCS Newcastle&lt;/a&gt; on the 25th January. I'll be giving my iOS development talk; a quick start in developing applications for iPhone, iPad, and iPod Touch.&lt;br /&gt;&lt;br /&gt;Here's the synopsis:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;The iPhone, iPad and their iOS relatives are becoming an increasingly popular and important platform. More and more developers are looking into what the platform can offer and how to harness its power for their products.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;In this presentation, an experienced iOS developer provides a boot-strap in iPhone development. The talk is an overview of how to get started as an iPhone developer. You will gain an understanding of the platform, the tools, and the core technologies, including:&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;The main languages: Objective C/C++&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Using the Xcode IDE, and various deployment/testing tools&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Common iPhone/Mac OS design patterns, idioms, and practices&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Becoming a native: how to “think in iPhone”&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;An overview of the libraries and facilities that exist&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;Limitations of the development environment.&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;i&gt;We’ll see the pros and cons of iPhone development. You will leave with an understanding of how to deploy your applications on the device, and whether it is the right platform for you to target.&lt;/i&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2451681143638146826?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2451681143638146826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2451681143638146826' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2451681143638146826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2451681143638146826'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2012/01/speaking-bcs-newcastle.html' title='Speaking: BCS Newcastle'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-EH3kMh5jt6A/R_SWHBodA-I/AAAAAAAAAA4/F8-RD393lIE/s72-c/pete.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4178650775045484160</id><published>2012-01-03T09:22:00.000-08:00</published><updated>2012-01-03T09:22:54.372-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Speaking: ACCU 2012</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://accu.org/content/images/conferences/2012/accu2012web.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://accu.org/content/images/conferences/2012/accu2012web.png" /&gt;&lt;/a&gt;&lt;/div&gt;I will be speaking at the ACCU 2012 conference in Oxford, UK this April.&lt;br /&gt;&lt;br /&gt;I'm giving two presentations this year, both this year on version control:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://accu.org/index.php/conferences/accu_conference_2012/accu2012_sessions#Version%20control%20done%20right"&gt;Version Control Done Right&lt;/a&gt;, and&lt;/li&gt;&lt;li&gt;&lt;a href="http://accu.org/index.php/conferences/accu_conference_2012/accu2012_sessions#Getting%20into%20git"&gt;Getting into Git&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Version control is never a laugh a minute topic, but I plan on these talks being&amp;nbsp;&lt;i&gt;interesting&lt;/i&gt; as well as informative. There will be the requisite amount of jumping, tomfoolery and general barefooted nonsense that regular attendees have come to expect.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This year's ACCU conference programme looks very strong, with understandable focus on C++ since the ink is still drying on the newest version of the language standard. But it still covers a broad range of topics, so there's something for everyone.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you care about programming and live in proximity of Englandshire, I &lt;i&gt;strongly&lt;/i&gt; suggest you check out this conference. It's one of the highlights of my programming year.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4178650775045484160?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4178650775045484160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4178650775045484160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4178650775045484160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4178650775045484160'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2012/01/speaking-accu-2012.html' title='Speaking: ACCU 2012'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8598617520645156590</id><published>2011-12-05T02:56:00.001-08:00</published><updated>2011-12-05T03:06:58.023-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Skip Lists: A C++ STL-style implementation</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.congressexchange.com/20%20foor%20container.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="165" src="http://www.congressexchange.com/20%20foor%20container.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;Recently someone mentioned an interesting container type to me, the &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Skip_list"&gt;skip list&lt;/a&gt;&lt;/b&gt;.&amp;nbsp;It piqued my interest and so, naturally, I wanted to play around with it. It's been a while since I last wrote an &lt;a href="http://en.wikipedia.org/wiki/Standard_Template_Library"&gt;STL&lt;/a&gt;-style container, so I thought I'd attempt to write an STL-compatible skip list implementation. &lt;i&gt;Fun times.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;And so I present to you my latest code offering, the C++ STL-style &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;skip_list&lt;/b&gt;&lt;/span&gt; container. Grab it from the GitHub project &lt;a href="https://github.com/petegoodliffe/skip_list"&gt;here&lt;/a&gt;. Or read on for further information...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Skipping the list&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The skip list is an interesting data structure. You could (simplistically) consider it a hybrid of a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::list&lt;/span&gt; and a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::set&lt;/span&gt;; it's a list-like data structure than provides good insertion, removal and search performance. As ever, the trick to good search speed is to trade off some memory to improve traversal performance.&lt;br /&gt;&lt;br /&gt;Traditionally the skip list is an extension of a standard forwards-only linked list. Wikipedia has a &lt;a href="http://en.wikipedia.org/wiki/Skip_list"&gt;pretty good page&lt;/a&gt; on the structure. Check it out if you want more gory details.&lt;br /&gt;&lt;br /&gt;Atop a standard linked it, it maintains a set of higher-order linked lists that act as indexes into the main structure below. These provide faster access to the middle of the list. This provides efficiency on a par with a balanced binary tree (i.e. what a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::set&lt;/span&gt; is usually implemented in terms of). Insertion, removal and search operations are typically O(log N). Remember: a standard linked list (which you'd have to manually keep in order) would have all those operations take O(N).&lt;br /&gt;&lt;br /&gt;The particularly interesting detail about the skip list implementation is the algorithm used to determine the allocation of nodes to higher-order lists. Rather than use a fixed balancing scheme, or inspecting the data as it's added and comparing against the existing structure, we assign nodes to levels &lt;i&gt;probabilistically&lt;/i&gt; - always adding them to the main list, and then (with decreasing levels of probability) adding them to the high levels lists, too.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;My implementation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I chose to implement a bi-directional skip list, so each node in my version retains a back-pointer to the previous node. This makes the list more useful in general, and ensures that it's a drop-in replacement for &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::list&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Like&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; std::set&lt;/span&gt;, my version takes a template &lt;i&gt;Comparison&lt;/i&gt; functor (typically &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::less&lt;/span&gt;) so you can tailor the ordering of data in your container. I also, naturally, support custom allocators, and provide all "the usual" STL container operations.&lt;br /&gt;&lt;br /&gt;I have tested the code on:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Mac OS using Xcode 4.2&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Windows usigin Visual Studio 2008&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Linux using gcc 4.4&lt;/li&gt;&lt;/ul&gt;I have benchmarked the performance of my &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;skip_list&lt;/span&gt; container. Because of the probabilistic nature of the container, sometimes it will perform better than other times when given random test data.&lt;br /&gt;&lt;br /&gt;The memory consumption is almost exactly the same as&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; std::set&lt;/span&gt; in general, and it tends to allow faster forwards and reverse iteration. Depending on the way the wind is blowing, large node insertion/removal operations can be dramatically faster (taking a little as 25% of the time of &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;std::set&lt;/span&gt; for the same data) or a bit slower (I've seen up to ~110%).&lt;br /&gt;&lt;br /&gt;The source archive contains my benchmarking code, so feel free to try it yourself.&lt;br /&gt;&lt;br /&gt;The GitHub project for skip_list is&amp;nbsp;&lt;a href="https://github.com/petegoodliffe/skip_list"&gt;https://github.com/petegoodliffe/skip_list&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Future plans&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I have not yet provided C++11 "move" or initialiser_list operations, so that would be an interesting addition.&lt;br /&gt;&lt;br /&gt;I could extend the data structure to provide O(log N) random access (e.g. indexing and random access iteration), too, at the expense of one more integer value in each node. That would be an interesting extension to consider - probably as a parallel variant of the existing container.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Future writings&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If there's enough interest, I might start a new blog series on writing an STL-like container based on this implementation. There was a lot of interest in my previous series describing an STL-style circular buffer. Since this is a meatier data structure, the case study would be more useful.&lt;br /&gt;&lt;br /&gt;Let me know if you'd like this!&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8598617520645156590?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8598617520645156590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8598617520645156590' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8598617520645156590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8598617520645156590'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/12/skip-lists-c-stl-style-implementation.html' title='Skip Lists: A C++ STL-style implementation'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7756806284321634425</id><published>2011-11-24T02:13:00.001-08:00</published><updated>2011-11-24T02:15:42.197-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>PGMidi moved and updated</title><content type='html'>&lt;a href="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov6-hover.svg?1315858549" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov6-hover.svg?1315858549" /&gt;&lt;/a&gt;My popular PGMidi library for MIDI input/output on iOS has moved from Gitorious to a &lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;new location on GitHub&lt;/a&gt;. (This was requested many times, and who am I to disappoint?)&lt;br /&gt;&lt;br /&gt;Please update your repos accordingly.&lt;br /&gt;&lt;br /&gt;Over the next few days, I'll also be adding a few new tweaks and features to the project, so stay tuned.&lt;br /&gt;&lt;br /&gt;Thanks for all the kind comments and feedback about the code - I'm really glad it's useful. Please do let me know if you've incorporated it in your own project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7756806284321634425?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7756806284321634425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7756806284321634425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7756806284321634425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7756806284321634425'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/11/pgmidi-moved-and-updated.html' title='PGMidi moved and updated'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6756658761601486058</id><published>2011-11-23T01:06:00.001-08:00</published><updated>2011-11-25T00:46:12.495-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: How To Pick Your Programming Language</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-lQU2Y5DoMaI/Tsy3eJyhwaI/AAAAAAAACyA/657YECLJ9eU/s1600/cvu-cover-small.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-lQU2Y5DoMaI/Tsy3eJyhwaI/AAAAAAAACyA/657YECLJ9eU/s200/cvu-cover-small.png" width="142" /&gt;&lt;/a&gt;&lt;/div&gt;The November issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;a href="http://accu.org/index.php/aboutus/aboutjournals"&gt;C Vu&lt;/a&gt; magazine is out now. It contains the latest instalment in my&lt;b&gt; Becoming a Better Programmer&lt;/b&gt; column. This one's called &lt;b&gt;How To Pick Your Programming Language&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;It's a masterwork that uses ancient dark arts (and frivolous flow chart technology) to help you select the programming language that best suits you.&lt;br /&gt;&lt;br /&gt;Best read with a pinch of salt!&lt;br /&gt;&lt;br /&gt;I quite like the artwork I produced for this month's cover, and have finally remembered to align the &lt;i&gt;{cvu}&lt;/i&gt; drop shadow correctly, something that's been bugging me for months. (I doubt anyone else would even have noticed it)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6756658761601486058?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6756658761601486058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6756658761601486058' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6756658761601486058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6756658761601486058'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/11/writing-how-to-pick-your-programming.html' title='Writing: How To Pick Your Programming Language'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-lQU2Y5DoMaI/Tsy3eJyhwaI/AAAAAAAACyA/657YECLJ9eU/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8781109897066391238</id><published>2011-11-16T04:11:00.001-08:00</published><updated>2011-11-23T01:15:31.995-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Xcode 4 keyboard/mouse shortcuts</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-HNp7-de7zwY/TsOpS0Fx4TI/AAAAAAAACx0/3ESOfy7d5x8/s1600/xcode.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-HNp7-de7zwY/TsOpS0Fx4TI/AAAAAAAACx0/3ESOfy7d5x8/s200/xcode.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;(I'm posting this here mostly so I don't lose it, although I'm sure it'll be useful to other Xcode 4 users out there.)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;There are a couple of really handy Xcode mouse click modifier key combinations that I can &lt;i&gt;never&lt;/i&gt; remember when I want them (kind of like a Super Street Fighter &lt;a href="http://www.gamepro.com/article/features/208887/street-fighter-iv-strategy-guide-all-moves-combos-tips-and-secrets-for-sfiv/"&gt;key combo&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;In particular, you can click on symbols in the code editor and have them open in this editor, in the alt editor, in a new window, or... even... with a (ugly looking) popup asking you where to open (e.g. in a new tab).&lt;br /&gt;&lt;br /&gt;Here's the lowdown:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Xcode 4 editor symbol clicks&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Modifiers&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Click&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;What happens&lt;/b&gt;&lt;br /&gt;⌘⎇^&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;+ single&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Open in alt editor&lt;br /&gt;⌘⎇⇧&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;+ single&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Select where to open (with popup)&lt;br /&gt;&lt;br /&gt;⌘&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;+ single&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Open in this editor&lt;br /&gt;⌘&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;+ double&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Open in this new editor window&lt;br /&gt;⎇&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;+ single&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Show help popup&lt;br /&gt;⎇&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;+ double&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Show help in organiser&lt;br /&gt;&lt;br /&gt;⌘⎇⇧&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;Make alt editor counterpart again (super useful)&lt;br /&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Key (what the silly symbols mean)&lt;/span&gt;&lt;/b&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote class="tr_bq"&gt;⌘&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Command (cmd)&lt;br /&gt;⎇&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Option (alt)&lt;br /&gt;^&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Control (ctrl)&lt;br /&gt;⇧&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Shift&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8781109897066391238?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8781109897066391238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8781109897066391238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8781109897066391238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8781109897066391238'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/11/xcode-4-keyboardmouse-shortcuts.html' title='Xcode 4 keyboard/mouse shortcuts'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-HNp7-de7zwY/TsOpS0Fx4TI/AAAAAAAACx0/3ESOfy7d5x8/s72-c/xcode.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6327349433494415890</id><published>2011-11-11T07:44:00.001-08:00</published><updated>2011-11-23T01:14:09.715-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>It's the thought that accounts</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-rYUis6SizLo/Tr1Cw1KnnsI/AAAAAAAACxo/b-kDByVGsao/s1600/accountability-cartoon.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-rYUis6SizLo/Tr1Cw1KnnsI/AAAAAAAACxo/b-kDByVGsao/s320/accountability-cartoon.png" width="265" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;i&gt;Thinking well is wise; planning well, wiser; doing well, wisest and best of all.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;i&gt;– Persian Proverb&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I run. Every week. It's my waistline, you see. Perhaps it's aguilt thing, but I do feel I need to do something to keep it undercontrol. &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Now,let's be clear: I'm no masochist. Exercise is &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;not&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;my favourite thing in the world. Far from it. It definitely ranksabove hot pokers being stuck in my eyes. Marginally. But there areplenty of things I'd rather do with my evenings. Many of them involvesitting down, preferably with a glass of wine.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;ButI know that I &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;should&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;run. It's good for me.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Is that fact alone enough to ensure I go regularly, every week,for the full distance? With no slacking or slowing of the pace?&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;It is not. &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I dislike exercise and would gladly employ the weakest of excusesto get out of a run. “Oh no, my running shorts have a loosethread.” “Oh no, I have a runny nose.” “Oh no, I'm a bittired.” “Oh no, my leg has fallen off."&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;(Ok,some excuses &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;are&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;betterthan others.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;What unseen force coaxes me to continue running regularly whenguilt alone can't drag me out the door? What magical power leads meon where willpower fails?&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Accountability. &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I run with a friend. That person knows when I'm slacking, andencourages me out of the house even when I don't fancy it. They turnup at the door, as we'd arranged before my lethargy set in. I performthe same kind of service back. I’ve lost count of the times that Iwouldn't have run, or would have given up half-way round had I nothad someone there, watching me and running alongside me. &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;And, as a by-product we enjoy the run more for the company andshared experience. &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Sometimeswe &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;both&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;don't feel like going on the run. Even if we admit it to each other,we won't let the other person off the hook. We encourage each otherto push through the pain. And, once we've run, we're always glad wedid it, even if it didn't feel like a great idea at the time. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Stretch the metaphor&lt;/h1&gt;Some metaphors are tenuous literary devices, written to entertain,or for use as contrived segues. Some are so oblique as to bedistracting, or form such a bad parallel as to be downrightmisleading. &lt;br /&gt;However, I believe this picture of accountability is directlyrelevant to the quality of our code. &lt;br /&gt;&lt;br /&gt;For all the good it does technical writers, speakers, and codeprophets like myself to talk about producing good, well-crafted code,and as much as the luminaries like Uncle Bob Martin extol the(genuine) virtues of “clean” code, and Fowler explains why weneed well-factored code, it matters not one jot if, in the heat ofthe workplace, we can't put it into practice. If the harsh realitiesof the codeface cause us to shed our development morals and resort tohacking at code like uninformed idiots, what have we achieved?&lt;br /&gt;&lt;br /&gt;We can complain about the poor state of our codebases, but who canwe look at to blame?&lt;br /&gt;&lt;br /&gt;We need to bake into our development regimen ways to avoid thetemptation for shortcuts, bodges and quick-fixes. We need somethingto lure us out of the trap of thoughtless design, sloppy, easysolutions and half-baked practices. The kind of thing that costs useffort to do, but that in retrospect we're always glad we &lt;i&gt;have&lt;/i&gt;done.&lt;br /&gt;&lt;br /&gt;The spirit is willing, but when the deadline looms, all too oftenthe flesh is weak. &lt;br /&gt;&lt;br /&gt;How do you think we'll achieve this?&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Accountability counts&lt;/h1&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Iknow that in my career to date, the single most import thing that hasencouraged me to work to the best of my abilities has been&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;accountability,&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;to a team of great programmers. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;It's the other coders that make me look good. It's those othercoders that have &lt;i&gt;made&lt;/i&gt; me a better programmer. &lt;br /&gt;&lt;div class="tip-western"&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;Being accountable to other programmers for thequality of your work will dramatically improve the quality of yourcoding.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;That is a single simple, but powerful idea.&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Code++&lt;/h1&gt;To ensure you're crafting excellent code, you need people who arechecking it every step of the way. People who will make sure you'reworking to the best of your ability, and are keeping up to thequality standard of the project/team you're working on. &lt;br /&gt;&lt;br /&gt;This needn't be some bureaucratic big-brother process, or aregimented personal development plan that feeds back directly intoyour salary. In fact, it had better not be. A lightweight,low-ceremony system of accountability, involving no forms, lengthyreviewing sessions or formal reviews is far superior, and will yieldmuch better results.&lt;br /&gt;&lt;br /&gt;Most important is to simply recognise the need for such a thing;to realise that you must be accountable to other people for thequality of your code to encourage you to work at your best. Torealise that actively putting yourself into that vulnerable positionof accountability is not a sign of weakness, but a valuable way togain feedback and improve your skills.&lt;br /&gt;&lt;br /&gt;How accountable do you feel that you currently are for the qualityof the code you produce? Is anyone challenging you to produce highquality work, to prevent you from slipping into bad, lazy practices?&lt;br /&gt;Accountability is worth pursuing not only in the quality of ourcode output, but also in the way we learn, and how we plan ourpersonal development. It's even beneficial in matters of characterand personal life (but that's a whole other magazine's column).&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Making it work&lt;/h1&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Thereare some simple ways to build accountability for the quality of codeinto your development process. In one development team we found itparticularly useful when the all coders agreed on a simple rule: &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;allcode passed two eyes before entering source control&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;.With this as a peer-agreed rule, it was &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;ourchoice&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;to be accountable to one another, rather then some managerial diktatpassed down from faceless suits on high. Grass-roots buy-in was keyto this success of the scheme. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;To satisfy the rule, we employed pair programming and/or alow-ceremony one-on-one code review, keeping each checked-in changesmall to make the scheme manageable. Knowing another person was goingto scrutinise your work was enough to foster a resistance to sloppypractise and to improve the general quality of our code. &lt;br /&gt;&lt;div class="tip-western"&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;Ifyou know that someone else &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;will&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;read and comment on your code, you're more likely to write good code.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;This practice genuinely improved the quality of the team, too. Weall learnt from one another, and shared our knowledge of the systemaround. It encouraged a greater responsibility for and understandingof the system. &lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;We also ended up with closer collaboration as a result, enjoyedworking with each other, and had more fun writing the code as aconsequence of this scheme. The accountability lead to a pleasant,more productive workflow. &lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Setting the standard&lt;/h1&gt;When building developer accountability into your daily routine itis worth spending a while considering the benchmark that you'reaiming for. Ask yourself the following questions:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Howis the quality of your work judged? How do people &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;currently&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;rate your performance? What is the yardstick they use to gauge it'squality? How do you think they &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;should&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;rate it?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The software works, that's good enough.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;It was written fast, and released on schedule (internal quality is not paramount).&lt;br /&gt; &lt;/li&gt;&lt;li&gt;It was well-written, and can be maintained easily in the future.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Some combination of the above.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Which is seen as most important?&lt;br /&gt;&lt;br /&gt;Who currently judges your work? Who is the audience for your work?Is it only seen by yourself? Your peers? Your superiors? Yourmanager? Your customer? How are they qualified to judge the qualityof your handiwork?&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Who&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;should&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;be the arbiter of your work quality? Who really knows how well you’veperformed? How can you get them involved? Is it as simple as askingthem? Does their opinion have any bearing on the company's currentview of your work's quality?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Which aspects of your work should be placed under accountability?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The lines of code you produce?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;The design?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;The conduct and process you used to develop it?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;The way you worked with others?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;The clothes you wore when you did it?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Which aspect matters the most to you at the moment? Where do youneed the most accountability and encouragement to keep improving?&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;The next steps&lt;/h1&gt;If you think that this is important, and something you shouldstart adding to your work:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Agree that accountability is a good thing. Commit to it.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Find someone to become accountable to. Consider making it a reciprocal arrangement; perhaps involve the entire development team.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Consider implementing a simple scheme like the one described above in your team, where every line of code changed, added or removed must go past two sets of eyes.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Agree on how you will work out the accountability – small meetings, end of week reviews, design meetings, pair programming, code reviews, etc.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;Commit to a certain quality of work, be prepared to be challenged on it. Don't be defensive.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;If this happens team-wide, or project-wide then ensure you have everyone's buy-in. Draft a set of team standards or group code of conduct for quality of development.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Also, consider approaching this from the other side: can you helpsomeone else out with feedback, encouragement, and accountability? Could you become another programmer's moral software compass?&lt;br /&gt;&lt;br /&gt;Often this kind of accountability works better in pairs of peers,rather than in a subordinate relationship.&lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Conclusion&lt;/h1&gt;Accountability between programmers requires a degree of bravery;you have to be willing to accept criticism. And tactful enough togive it well. But the benefits can be marked and profound in thequality of code you create. &lt;br /&gt;&lt;h1 class="western" lang="pl-PL"&gt;Questions&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;How are you accountable to others for the quality of your work?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;What should you be held accountable for?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;How do you ensure the work you do today is as good as previous work?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;How is your current work teaching you and helping you to improve?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;When have you been glad you kept quality up, even when you didn't feel like it?&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;Does accountability only work when you &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;chose&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt; to enter into an accountability relationship, or can it effectively be something you are &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;i&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt;required&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span style="text-decoration: none;"&gt;&lt;span style="font-weight: normal;"&gt; to do?&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6327349433494415890?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6327349433494415890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6327349433494415890' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6327349433494415890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6327349433494415890'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/11/its-thought-that-accounts.html' title='It&apos;s the thought that accounts'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-rYUis6SizLo/Tr1Cw1KnnsI/AAAAAAAACxo/b-kDByVGsao/s72-c/accountability-cartoon.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2576928984761460954</id><published>2011-10-09T15:54:00.000-07:00</published><updated>2011-11-23T01:14:40.477-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>My latest iOS app: The Mahjong Score Book</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-nSfpp8BZ8jI/TpIkxrv8JbI/AAAAAAAACxY/Uhv44GRQIH8/s1600/Screen+Shot+2011-10-09+at+23.48.03.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-nSfpp8BZ8jI/TpIkxrv8JbI/AAAAAAAACxY/Uhv44GRQIH8/s1600/Screen+Shot+2011-10-09+at+23.48.03.png" /&gt;&lt;/a&gt;My latest iOS app is out now (thanks to the iOS 5 SDK having&amp;nbsp;&lt;i&gt;finally&lt;/i&gt; gone GM). It's called the &lt;b&gt;Mahjong Score Book&lt;/b&gt;&amp;nbsp;and, as the name suggests, is designed to help Mahjong players keep tabs on their scoring in Mahjong games.&lt;br /&gt;&lt;br /&gt;Of course, once you have your scores captured inside a wee computer, there's more exciting things we can do with them. So the app allows you to:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;keep records of all the games you've ever played, with a very clear visual presentation, associated with the date played&lt;/li&gt;&lt;li&gt;draw pretty graphs of game progress&lt;/li&gt;&lt;li&gt;adopt different rule sets (limit hand value, maximum wins as east wind, etc)&lt;/li&gt;&lt;li&gt;export games to databases, as images, or text files&lt;/li&gt;&lt;li&gt;automatically roll dice to determine starting positions&lt;/li&gt;&lt;li&gt;associate notes with each game&lt;/li&gt;&lt;li&gt;and much more.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;If you're interested, then check it out &lt;a href="http://itunes.apple.com/us/app/mahjong-score-book/id460176463?ls=1&amp;amp;mt=8"&gt;in iTunes here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I appreciate that it's a niche app. It simply something I wrote to fulfil a personal need. Of course, &lt;i&gt;someone&lt;/i&gt; else out there is going to find it useful, too. And so I've polished it, honed it, and produced a really very slick app.&lt;br /&gt;&lt;br /&gt;I wrote Mahjong Score Book app back in the summer whilst on holiday, playing Mahjong with friends. It serviced its purpose well then and many times since, and I've learnt a few new iOS techniques whilst polishing off the application.&lt;br /&gt;&lt;br /&gt;I'm sure that it won't make me millions, but I'm very proud of what I've produced in a relatively short time. If you know someone who plays Mahjong then please point them at it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2576928984761460954?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2576928984761460954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2576928984761460954' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2576928984761460954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2576928984761460954'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/10/my-latest-ios-app-mahjong-score-book.html' title='My latest iOS app: The Mahjong Score Book'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-nSfpp8BZ8jI/TpIkxrv8JbI/AAAAAAAACxY/Uhv44GRQIH8/s72-c/Screen+Shot+2011-10-09+at+23.48.03.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-1218466243864182094</id><published>2011-09-21T02:26:00.000-07:00</published><updated>2011-11-23T01:15:44.465-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: Using older SDKs with newer Xcode versions</title><content type='html'>When you update Xcode versions, the installer automatically removes any old SDKs you have lying around, and replaces them with the latest version.&lt;br /&gt;&lt;br /&gt;This is fine behaviour, as the most recent SDKs remain backwards compatible. You can set your project to target older iOS versions. If you do this, the newer SDK features are disabled for you.&lt;br /&gt;&lt;br /&gt;However, there &lt;i&gt;are&lt;/i&gt; times when you need to use an older SDK.&lt;br /&gt;&lt;br /&gt;For example, I am running the latest Xcode with a beta iOS 5 SDK installed. Since this was originally installed on a clean machine, I didn't set the beta install to use a parallel directory and leave the "release version" of the developer tools intact - they simply weren't installed. (Making a parallel install is, in general, the best practice when installing a beta Xcode/SDK set).&lt;br /&gt;&lt;br /&gt;Fear not. You can still get your newer Xcode to build with an older SDK, without downgrading your Xcode or making a parallel install:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Close any running Xcode instance you have open.&lt;/li&gt;&lt;li&gt;Locate the install DMG for an old version of Xcode (e.g. Xcode_3.2.5_and_ios_sdk_4.2_final.dmg, they name them so well) and open it.&lt;/li&gt;&lt;li&gt;&lt;i&gt;Do not&lt;/i&gt; run the installer!&lt;/li&gt;&lt;li&gt;Open the &lt;i&gt;Packages&lt;/i&gt;&amp;nbsp;directory in that disk image. It is a hidden directory. Try this terminal incantation: "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;open /Volumes/Xcode\ and\ iOS\ SDK/Packages&lt;/span&gt;"&lt;/li&gt;&lt;li&gt;Locate the iPhoneOS and iPhoneSimulator SDKs for the version you want. Run just those &lt;i&gt;pkg&lt;/i&gt; files. (e.g. I ran the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;iPhoneSDK4_2.pkg&lt;/span&gt; and it's matching&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; iPhoneSimulatorSDK4_2.pkg&lt;/span&gt;)&lt;/li&gt;&lt;li&gt;Make sure you specify the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Developer&lt;/span&gt; directory as your install location. If you don't, the SDKs will be installed in your root directory, under the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Platforms&lt;/span&gt; directory; you'll have to manually copy them into &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Developer/Platforms&lt;/span&gt; yourself.&lt;/li&gt;&lt;li&gt;Now, re-open Xcode. If the SDKs installed in the right locations, they will be selectable in your project now.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-1218466243864182094?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/1218466243864182094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=1218466243864182094' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1218466243864182094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1218466243864182094'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/09/ios-using-older-sdks-with-newer-xcode.html' title='iOS: Using older SDKs with newer Xcode versions'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8305430924590611006</id><published>2011-09-20T15:40:00.000-07:00</published><updated>2011-11-23T01:15:23.743-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>How to set up Jenkins CI on a Mac</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://agentdero.cachefly.net/continuousblog/newlogo/headshot.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://agentdero.cachefly.net/continuousblog/newlogo/headshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;In this post I will describe how to get a &lt;i&gt;running&lt;/i&gt; &lt;a href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt; server set up on your Mac. Like most free software ("free" as in price and "free" as in freedom), Jenkins is very capable, very functional, and mostly documented. But it didn't quite work out of the box.&lt;br /&gt;&lt;br /&gt;As with many such projects, you get far more than you pay for. But you can end up spending more than you expect.&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;There aren't enough step-by-step how-to guides. And there aren't many documents that help you out when things go wrong. There is a great community behind Jenkins, though, which does help. And plenty of people moaning and blogging. Now I'm adding to that noise.&lt;/div&gt;&lt;br /&gt;It took me a few days to get the setup working properly. Hopefully this story-&lt;i&gt;cum&lt;/i&gt;-howto will save you some of that effort.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Prologue&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;All good developers know that a &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;continuous integration&lt;/a&gt;&amp;nbsp;(CI) server is a &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;linchpin&lt;/a&gt; of the development effort. I joined a large software project without one, and made loud noises that we needed one. And so, it naturally fell to me to set up.&lt;br /&gt;&lt;br /&gt;It's been some time since I set up a CI server. Previously, I've used ViewTier's&amp;nbsp;&lt;a href="http://www.viewtier.com/products/parabuild/index.htm"&gt;Parabuild&lt;/a&gt;. It was more than adequate. But times have moved on. Although I still have a licence for it, the cools kids are hanging around at other parties these days.&lt;br /&gt;&lt;br /&gt;Jenkins (the &lt;a href="http://jenkins-ci.org/content/hudsons-future"&gt;recent fork&lt;/a&gt; of &lt;a href="http://hudson-ci.org/"&gt;Husdon&lt;/a&gt;) seems well-regarded, popular, and to have a good development and support community. It's also open source, so seemed the right way to go. Plenty of people have sung it's praises to me in the past, and that kind of thing counts for a lost.&lt;br /&gt;&lt;br /&gt;Our requirements for the builds were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;to build two products from the same codebase on Mac OSX&lt;/li&gt;&lt;li&gt;to build two products from the same codebase on Windows&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Both of these need 32-bit and 64-bit versions.&lt;br /&gt;&lt;br /&gt;That's already a reasonable configuration matrix, and highlighted why we needed CI in place. A developer would check in a tweak that they'd built on one configuration. All the other config could easily get broken without anyone noticing for a while.&lt;br /&gt;&lt;br /&gt;So: Jenkins to the rescue.&lt;br /&gt;&lt;br /&gt;Almost.&lt;br /&gt;&lt;br /&gt;I purchased a small Mac Mini to use as a build server. I downloaded a copy of Jenkins (free, whoop!), installed the &lt;a href="http://developer.apple.com/mac"&gt;Mac dev tools&lt;/a&gt; (free, whoop!) bought (and installed) &lt;a href="http://www.parallels.com/products/desktop/"&gt;Parallels&lt;/a&gt;, Windows 7, and the Visual Studio toolchain (not quite as free), and sat down for a small configuration session.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Getting your project ready for a CI build&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Before setting up your build on an CI server, you should first create a simple script that builds &lt;b&gt;everything&lt;/b&gt; from a clean checkout. Then check that script into the repository, to be versioned alongside the software itself.&lt;br /&gt;&lt;br /&gt;For our project, I already had that in place. The script cleaned, built, versioned and packaged the software in one step.&lt;br /&gt;&lt;br /&gt;Such scripts are clearly useful for deployment on a CI server, and also for making official software releases by hand, whether or not you release from the CI server builds. It's a record of the recipe needed to build a release.&lt;br /&gt;&lt;br /&gt;With a fixed recipe like this in place, every software release can be guaranteed to be good and reproducible.&lt;br /&gt;&lt;br /&gt;That's &lt;a href="http://www.dummies.com/store/product/Beginning-Programming-For-Dummies-4th-Edition.productCd-0470088702.html"&gt;development 101&lt;/a&gt;.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Installing Jenkins on the Mac&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://jenkins-ci.org/"&gt;Jenkins website&lt;/a&gt; has a handy Mac installer that you can download. (In retrospect, I'm not sure if this was more hassle than it was worth, but this is the route I obviously sought to go down.)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;b&gt;STEP 1: Install Jenkins&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;Download the Mac installer and run it.&lt;br /&gt;&lt;br /&gt;This installer creates a system &lt;a href="http://en.wikipedia.org/wiki/Launchd"&gt;launch daemon&lt;/a&gt; that fires up Jenkins when your machine boots. This runs in the background even if you haven't logged in, making a true stand-alone build server installation.&lt;br /&gt;&lt;br /&gt;However, if you have a fresh Lion install you don't yet have Java.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;b&gt;STEP 2: Install Java&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;Try to run a Java app. Any app. The OS may fumble around for a while looking for Java. If you're lucky, it'll download and install it automatically. Otherwise, install it by hand.&lt;br /&gt;&lt;br /&gt;And of course, now, Jenkins "just works".&lt;br /&gt;&lt;br /&gt;Not.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuring Jenkins on the Mac&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The Jenkins war (&lt;a href="http://en.wikipedia.org/wiki/WAR_file_format_(Sun)"&gt;web application archive&lt;/a&gt;) is unpacked into &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Users/shared/Jenkins&lt;/span&gt;. The application runs from there. All configuration is stored there. The source code checkouts and builds go in there. It's the center of your Jenkins universe.&lt;br /&gt;&lt;br /&gt;A launch daemon &lt;a href="http://en.wikipedia.org/wiki/Property_list"&gt;plist&lt;/a&gt; is installed in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Library/LaunchDaemons&lt;/span&gt;. It runs a script &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Library/Application Support/jenkins-runner.sh&lt;/span&gt; as the user "&lt;i&gt;daemon&lt;/i&gt;" (a system specific user that runs background processes - it is not shown on the login screen, nor does it have a home directory).&lt;br /&gt;&lt;br /&gt;This installation has all the hallmarks of a runnable system. You can now point your browser to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;http://localhost:8080&lt;/span&gt; and start configuring the Jenkins server. The lights are most definitely on. But no one's home yet. As we're about to see...&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;i&gt;STEP 3: Set up Jenkins to build a Mac project&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;I was a good soldier with a simple shell script that built and packaged my application. If you don't have this, write one now. To build Mac projects, you'll need some cunning invocation of &lt;a href="http://www.manpagez.com/man/1/xcodebuild/"&gt;xcodebuild&lt;/a&gt; and probably &lt;a href="http://www.manpagez.com/man/1/packagemaker/"&gt;packagemaker&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This single script is a critical step in configuring your build job. Whilst it is possible to place multiple build commands into the Jenkins task itself, it's far better to keep them under source control in a script checked in to your codebase (if you need to ask why then you probably need to go to a more basic tutorial!).&lt;br /&gt;&lt;br /&gt;Configure Jenkins to check out your repository, to react to appropriate build triggers (e.g. manual build requests through the UI, automatic detection of the repository changing, or other triggers) and to run the appropriate scripts to kick off the build.&lt;br /&gt;&lt;br /&gt;Then press "&lt;i&gt;Build Now&lt;/i&gt;" to start your first build.&lt;br /&gt;&lt;br /&gt;In all probability Jenkins will crash and burn.&amp;nbsp;But don't tear your hair out just yet. You'll be needing it for later on.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fix Jenkins so it works&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Welcome to the nether-world of almost working builds.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&lt;i&gt;STEP 4: Configure the Java heap size&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;My project is large. It includes lots of third party libraries, including the vastness that is &lt;a href="http://www.boost.org/"&gt;Boost&lt;/a&gt; and many other comparable-size libraries. There are also several SDKs that are shipped as large binaries (with versions for each platform and 32/64 bit). That's a lot of data to shovel around.&lt;br /&gt;&lt;br /&gt;Jenkins choked trying to check out this monster. It would collapse with Java heap exhaustion errors before it even got to triggering a build. Goodness only knows why a large heap is required to check files out of a subversion repository, but the solution can only be to increase the heap size to remove the bottleneck.&lt;br /&gt;&lt;br /&gt;By default, Java allocates a very conservative default heap size to running applications; I believe its 256M or &amp;nbsp;so on 32-bit Mac OS.&lt;br /&gt;&lt;br /&gt;On the Mac, this can be changed using the "Java Preferences" application (found in the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Applications/Utilities&lt;/span&gt; folder). The trick is to adjust the Java launch command line (hit &lt;i&gt;Options...&lt;/i&gt;) to include the comand-line sneeze: "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;-Xmx1024M&lt;/span&gt;" (or whatever heap size you want). However, this didn't seem to affect the Jenkins Java process launched through launchd.&lt;br /&gt;&lt;br /&gt;To set the heap size in that context, you have to adjust the launch script itself. You can place the command line switch into the&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt; jenkins-runner.sh&lt;/span&gt; file directly. However, the file does have provision to load the heap size parameter from a configuration plist. This plist does not exist by default, but you can create/edit it with the following incantation:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo defaults write /Library/Preferences/org.jenkins-ci heapSize 1024M&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will write a file &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Library/Preferences/org.jenkins-ci.plist &lt;/span&gt;(note that you must &lt;i&gt;not&lt;/i&gt; specify the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;plist&lt;/span&gt; file extension to the defaults command).&lt;br /&gt;&lt;br /&gt;To make the system use this new heap size, you can't just restart Jenkins (either gracefully within the web interface, or by "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;kill -9&lt;/span&gt;"-ing the process. You can't even use "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo launchctl {stop,start} org.jenkins-ci&lt;/span&gt;".&lt;br /&gt;&lt;br /&gt;You &lt;i&gt;could&lt;/i&gt; reboot. Or, more cleanly, you have to force launchd to reload of the configuration for the launch daemon using &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;launchctl&lt;/span&gt; by unloading, and then reloading the daemon. It's the reloading that'll force the new configuration to take hold. (It took me a while to figure that one out!)&lt;br /&gt;&lt;br /&gt;With an increased heap, Jenkins will fall over less. In my case, I got through a whole checkout.&lt;br /&gt;&lt;br /&gt;But once Jenkins manages to check out the project and run the build script, you're still not quite done...&lt;br /&gt;&lt;br /&gt;My script called &lt;i&gt;xcodebuild&lt;/i&gt; to invoke Xcode from the command line to build the various configurations of the project. This script worked fine when run directly from the command line. However, when running within Jenkins it would bomb out with quite unfathomable errors - e.g.&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;NSAssertion&lt;/span&gt;s triggered from deep within the Xcode IDE codebase. Or it would just enter a hibernation state; lock-up completely, performing no work, but generating no error.&lt;br /&gt;&lt;br /&gt;The reason for the strangeness is that xcodebuild &lt;i&gt;doesn't work&lt;/i&gt; when run as a user that has no home directory, like &lt;i&gt;daemon&lt;/i&gt;. It throws its toys out of the pram in as baroque a manner as it can muster.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;b&gt;STEP 5: Create a "jenkins" user&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;So, to solve this we can either have Jenkins run as one of the existing users, or - more cleanly - create a new user specifically for jenkins.&lt;br /&gt;&lt;br /&gt;To do this:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a user called "&lt;i&gt;jenkins&lt;/i&gt;" from Control Panel. If you care particularly, you might want to create a "hidden" user; follow the instructions here: &lt;a href="http://hints.macworld.com/article.php?story=20080127172157404"&gt;http://hints.macworld.com/article.php?story=20080127172157404&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Stop jenkins again: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo launchctl unload -w /Library/LaunchAgents/org.jenkins-ci.plist&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Edit &amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/Library/LaunchAgents/org.jenkins-ci.plist&lt;/span&gt;, change the username entry from &lt;i&gt;daemon&lt;/i&gt; to &lt;i&gt;jenkins&lt;/i&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Change all permissions on the existing jenkins files: "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo chown -R jenkins /User/Shared/jenkins&lt;/span&gt;" "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo chgrp -R staff /User/Shared/Jenkins&lt;/span&gt;"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Restart Jenkins: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo launchctl load -w /Library/LaunchAgents/org.jenkins-ci.plist&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Re-start the build. Sit and wait.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Job done&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;From memory, that was the set-up steps required to get builds to work on a Mac from a fresh Jenkins install. These things aren't really covered by the install guides. They're obvious once you know them. Hindsight is great like that.&lt;br /&gt;&lt;br /&gt;Plenty of people followed my whining on Twitter with disbelief, saying that Jenkins "just works" for them. Others suggested moving over to Hudson instead, but I imagine I'd've had the same issues there.&lt;br /&gt;&lt;br /&gt;Perhaps I'm unusual, and this stuff does &lt;i&gt;just work&lt;/i&gt; for everyone else. If that's not the case, then I hope this rant proves useful.&lt;br /&gt;&lt;br /&gt;As a postscript, I now have my Jenkins server working well. I have configured a Windows client, running under a Parallels virtual machine on the same computer. It's not the fastest build server when both run together, but it's passable.&lt;br /&gt;&lt;br /&gt;There are definitely some rough edges and features lacking from Jekins, but I can't complain at the price. And there are plenty of excellent plugins that really do make it a very capable build server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8305430924590611006?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8305430924590611006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8305430924590611006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8305430924590611006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8305430924590611006'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/09/how-to-set-up-jenkins-ci-on-mac.html' title='How to set up Jenkins CI on a Mac'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6138240432777933750</id><published>2011-09-15T02:09:00.000-07:00</published><updated>2011-11-23T01:15:56.477-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Smarter, Not Harder</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-RgAzlfq5zYQ/TnHAIDuxnkI/AAAAAAAACxE/bJRd071TQTw/s1600/cvu-small.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/-RgAzlfq5zYQ/TnHAIDuxnkI/AAAAAAAACxE/bJRd071TQTw/s200/cvu-small.png" width="142" /&gt;&lt;/a&gt;&lt;/div&gt;The September issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s&lt;b&gt; C Vu&lt;/b&gt; magazine is out now. It contains the latest instalment in my &lt;b&gt;Becoming a Better Programmer&lt;/b&gt; column. This one's called &lt;b&gt;Smarter, Not Harder&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;In it I investigate how high-quality developers use their skill and experience to be maximally productive. I describe useful tactics to help you solve problems more easily and get the job done in the most effective way. In short: how to pick your battles.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6138240432777933750?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6138240432777933750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6138240432777933750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6138240432777933750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6138240432777933750'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/09/writing-smarter-not-harder.html' title='Writing: Smarter, Not Harder'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-RgAzlfq5zYQ/TnHAIDuxnkI/AAAAAAAACxE/bJRd071TQTw/s72-c/cvu-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6989790440981355020</id><published>2011-09-06T02:39:00.000-07:00</published><updated>2011-11-23T01:16:12.471-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Many-festos</title><content type='html'>&lt;div style="font-style: normal; margin-left: 1in; text-align: right;"&gt;&lt;span style="font-family: Helvetica, sans-serif;"&gt;Confusionof goals and perfection of means seems, in my opinion, tocharacterise our age.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: normal; margin-left: 1in; text-align: right;"&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica, sans-serif;"&gt;&lt;b&gt;Albert Einstein&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: normal; margin-left: 1in; text-align: right;"&gt;&lt;span class="Apple-style-span" style="font-family: Helvetica, sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;It's becoming an epidemic! They'respringing up everywhere. We've got them coming our of our ears. It'sas if you can't write a line of code, kick off a development process,or even think about the act of coding without signing up to one.&lt;/div&gt;&lt;div style="font-style: normal;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hzts1RTH5MA/TmXpWKkSVCI/AAAAAAAACxA/MyedEddmPPI/s1600/Picture.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-hzts1RTH5MA/TmXpWKkSVCI/AAAAAAAACxA/MyedEddmPPI/s320/Picture.png" width="232" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;With all these manifestos for softwaredevelopment, our profession is in danger of becoming more aboutpolitics than the actual art, craft, science, and trade of softwaredevelopment.&lt;/div&gt;&lt;div style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;Of course, a large and important partof professional software development is the &lt;i&gt;people problem&lt;/i&gt;.And that necessarily involves politics, to some extent. But we'remaking even the foundational coding principles a political battle. Isthis for the best? Or is it just a fashionable, sound-bite-sized wayto get your point across, and to try to garner support for your pethobby-horse?&lt;/div&gt;&lt;div style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;These “development” manifestos areoften too ambiguous for people to sign up to in any meaningful way.They're so general that they simply &lt;i&gt;must&lt;/i&gt; be right. Akin to adevelopment horoscope, if you will. Very few of them break newground, or introduce anything genuinely radical. And, sadly, when amanifesto becomes popular we see factions form around it, leading to disputes about what the manifesto really stands for. Whole debatesspring up around the exegesis of the particular manifesto items.&lt;/div&gt;&lt;div style="font-style: normal;"&gt;Software religion is alive and well.&lt;/div&gt;&lt;div style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;Whether or not manifestos are a goodidea, they seem to be springing up for any conceivable purpose. So,in order to stem the flow, and make it easier for future softwareactivists who'd like to pen their own manifesto, here I present theone, the overarching, generic software development manifesto.&lt;span style="font-family: Courier, monospace;"&gt;Manifesto&lt;pet_subject&gt;&lt;/pet_subject&gt;&lt;/span&gt;,if you like.&lt;/div&gt;&lt;h1 class="western" lang="pl-PL"&gt;A generic manifesto for softwaredevelopment&lt;/h1&gt;&lt;div style="font-style: normal;"&gt;We, the undersigned, have an opinionabout software development. We are concerned about the future of ourprofession, and our passion leads us to draw the followingconclusions:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;We believe in&lt;/i&gt;&lt;span style="font-style: normal;"&gt;   a fixed set of immutable ideals&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-left: 0.49in;"&gt;&lt;i&gt;over&lt;/i&gt;&lt;span style="font-style: normal;"&gt;   tailoring our approach to each specific situation.&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe in&lt;/i&gt;  concentrating on and discussing only the things that interest us&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;over  &lt;/i&gt;  thebigger problem.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe in&lt;/i&gt;  our opinion&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;over&lt;/i&gt;   theopinions and experiences of others.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe in&lt;/i&gt;  arbitrary black-and-white mandates&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;over&lt;/i&gt;   real-worldscenarios with complex issues and delicate resolutions.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe that&lt;/i&gt; when our approach is hard to follow&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;then&lt;/i&gt;    itonly shows how much more important it is.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe in &lt;/i&gt; crafting an arbitrary set of commandments&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;over &lt;/i&gt;  therealisation that it's just &lt;i&gt;never&lt;/i&gt; that simple.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;&lt;i&gt;We believe in&lt;/i&gt;  trying to establish a movement to promote our view&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;i&gt;over&lt;/i&gt;   somethingthat will be genuinely useful.&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;We believe that&lt;/i&gt;&lt;span style="font-style: normal;"&gt; we are better developers than those who don't agree with us&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-left: 0.49in;"&gt;&lt;i&gt;because&lt;/i&gt;&lt;span style="font-style: normal;"&gt;  they don't agree with us.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-style: normal; margin-left: 0.49in;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-style: normal;"&gt;That is, we believe we're doing theright thing. And if you don't you're wrong. And if you don't do whatwe do, you're doing it wrong.&lt;/div&gt;&lt;h1 class="western" lang="pl-PL"&gt;OK, OK&lt;/h1&gt;&lt;div style="font-style: normal;"&gt;Alright. I'll admit it. I exaggeratedfor effect. And my tongue &lt;i&gt;is&lt;/i&gt; in my cheek. Mostly.&amp;nbsp;&lt;/div&gt;&lt;h1 class="western" lang="pl-PL"&gt;References&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Agile Manifesto &lt;a href="http://agilemanifesto.org/"&gt;http://agilemanifesto.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Craftsmanship Manifesto  &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;http://manifesto.softwarecraftsmanship.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Refactoring Manifesto &lt;a href="http://refactoringmanifesto.org/"&gt;http://refactoringmanifesto.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The SOA Manifesto &lt;a href="http://www.soa-manifesto.org/"&gt;http://www.soa-manifesto.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The GNU Manifesto &lt;a href="http://www.gnu.org/gnu/manifesto.html"&gt;http://www.gnu.org/gnu/manifesto.html&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Software Testing Manifesto &lt;a href="http://www.softwaretestingmanifesto.org/"&gt;http://www.softwaretestingmanifesto.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Library Software Manifesto &lt;a href="http://techessence.info/manifesto/"&gt;http://techessence.info/manifesto/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The OpenCloud Manifesto &lt;a href="http://www.opencloudmanifesto.org/"&gt;http://www.opencloudmanifesto.org/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Mozilla Manifesto &lt;a href="http://www.mozilla.org/about/manifesto"&gt;http://www.mozilla.org/about/manifesto&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Cluetrain Manifesto &lt;a href="http://www.cluetrain.com/"&gt;http://www.cluetrain.com/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The End-User Manifesto &lt;a href="http://alistair.cockburn.us/User+Manifesto"&gt;http://alistair.cockburn.us/User+Manifesto&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Experience Design Manifesto &lt;a href="http://www.brazandre.com/manifesto/"&gt;http://www.brazandre.com/manifesto/&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;The Hacker Manifesto &lt;a href="http://en.wikipedia.org/wiki/Hacker_Manifesto"&gt;http://en.wikipedia.org/wiki/Hacker_Manifesto&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 class="western"&gt;Questions&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;What foundational development “principles” do you hold dear?  &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;Do you sign up to, or align yourself with, development streams like “agile”, “craftsmanship” and so on? How closely do you agree with each of the items in their manifesto?&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;What do you think these manifestos do have to offer the development community?&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;What kinds of harm might they &lt;i&gt;really&lt;/i&gt; be able do, if any?&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div style="font-style: normal;"&gt;Or do you keep your head down and ignore this kind of thing? &lt;i&gt;Should&lt;/i&gt; you actually follow these software fashions and fads to maintain personal development?&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6989790440981355020?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6989790440981355020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6989790440981355020' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6989790440981355020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6989790440981355020'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/09/confusionof-goals-and-perfection-of.html' title='Many-festos'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-hzts1RTH5MA/TmXpWKkSVCI/AAAAAAAACxA/MyedEddmPPI/s72-c/Picture.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4539836278806029887</id><published>2011-08-12T02:12:00.000-07:00</published><updated>2011-08-12T02:25:16.686-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Pushing a git repository into an existing subversion repository</title><content type='html'>&lt;div&gt;I worked on a project using &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; as the version control system. Eventally I needed to share it with other developers, who had an existing corporate &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; repository. They didn't want to be bogged down in the minutae of learning a new version control system.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I had to push the code in my git repo up to the svn repo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two options:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Take a baseline of the code and just comit that to svn, losing all version history. It's simple; it's quick; it works. Ten points for getting the job done. No points for elegance. And minus several thousand points for losing revision history.&lt;/li&gt;&lt;li&gt;Serialise the development history in git and use that to re-vivify the history within Subversion. Many, many, points for doing the right thing. Minus quite a few for the faff it takes to work out how to do it.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;Clearly, (2) is the way to go.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For your delight, this is how I finally managed to do it. Hopefully it'll help you avoid similar head scratching and Googling.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:130%;"&gt;&lt;b&gt;How to push a git repository into svn&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Obviously, we'll want to invoke the &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html"&gt;git-svn&lt;/a&gt; command. The trick is how to arrange your git repo so that it's tracking the subversion repository correctly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 1: Create the landing point in the svn repo&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;svn mkdir svn://DEST/repo/projectname/{trunk,branches,tags}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's worth noting that in this example, I was happy to just clone the mainline of development, and ignore any git branches.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you can infer, the corporate svn repo has many top-level directories that are all themselves "mini-repos". This is why I had to push the git history into an existing svn repo, rather than just create a new svn repo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 2: Create a git svn clone tracking svn&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;git svn clone svn://DEST/repo/projectname/trunk dest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now we have a git repo that tracks the destination svn landing point for the import operation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 3: Track the git repo we want to import&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;cd dest&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;git remote add -f source /path/to/git/source/repo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, if you inspect the git history (for this I used the excellent &lt;a href="http://gitx.laullon.com/"&gt;GitX (L)&lt;/a&gt; ), you'll see a whole series of commits from the original git repo and, disconnected from this, the master HEAD plus a &lt;b&gt;git-svn&lt;/b&gt; HEAD pointing to the original (single) svn commit we cloned.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 4: Rebase the original git repo onto git-svn&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's where the secret magic lies. I seems like there are many ways to go from here. This was the only one I found to work. Of course, I tried many ways that failed. Once I found one that worked, I stopped trying. So if there's a better way I'd love to hear it, but this seems to work well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;git rebase --onto remotes/git-svn --root source/master&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At this point, I realised that my git history wasn't strictly linear; I had worked on a few machines, so the history of trunk wove arond a bit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This meant that what I had expected to be a straightforward operation (that's what you'd expect with a SVN hat on) required a few rebase fix-ups along the way:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  gvim foo # fix merge conflict&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  git add foo&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  git rebase --continue&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;# ... rinse and repeat&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;These were required because branches in the source repo from work on different machines that got merged together to form the "source" trunk line of development didn't flatten into a rebase without a few tweaks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In general, the conflicts were small and weren't hard to fix.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 5: Admire your work&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;git log&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You should now see that the entire master development line of the source git repo has been replayed into the master of your working repo, stacked on top of the git-svn point.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Again, GitX (L) helped to visualise this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 6: Push up to svn&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now that we've arranged everything above git-svn, it's a simple case of:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;git svn dcommit&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To push the changes up into svn.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://pauldaniels.co.uk/"&gt;Now that's magic&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4539836278806029887?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4539836278806029887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4539836278806029887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4539836278806029887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4539836278806029887'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/08/pushing-git-repository-into-existing.html' title='Pushing a git repository into an existing subversion repository'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6970773647923393477</id><published>2011-07-22T08:26:00.000-07:00</published><updated>2011-07-22T12:41:13.335-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Xcode: Determining the current SDK version in a script</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-eIFv7xY-6uY/TimZdSYeX9I/AAAAAAAACtc/j8It9ZFnPuA/s1600/duck.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 177px; height: 200px;" src="http://3.bp.blogspot.com/-eIFv7xY-6uY/TimZdSYeX9I/AAAAAAAACtc/j8It9ZFnPuA/s200/duck.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5632201537433264082" /&gt;&lt;/a&gt;In an iOS XCode project, I needed a shell script target (aka "External Build Tool" target) that invokes other scripts which in turn build stuff using Xcode. &lt;a href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern"&gt;Curiously recursive&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, I needed to pass that script the current iOS SDK version being used so it could arrange its own build malarkey, and get all its SDK ducks in a row.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is &lt;i&gt;no&lt;/i&gt; environment variable for that defined by Xcode. Bah. The closest you get is the current deployment target version, which appears in &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$IPHONEOS_DEPLOYMENT_TARGET&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That seems like rather a large omission.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You do get given &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$SDKROOT&lt;/span&gt; which is a &lt;i&gt;file path&lt;/i&gt; to the current SDK. But that's not quite the same thing as a simple version number.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Never, fear, shell gibberish to the rescue. This is what I came up with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;SDK_VERSION=$(echo $SDKROOT | sed -e 's/.*iPhone\(OS\)*\(Simulator\)*\([0-9]*.[0-9]*\).sdk/\3/')&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you know a better way to do this, I'd love to know.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6970773647923393477?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6970773647923393477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6970773647923393477' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6970773647923393477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6970773647923393477'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/07/xcode-determining-current-sdk-version.html' title='Xcode: Determining the current SDK version in a script'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-eIFv7xY-6uY/TimZdSYeX9I/AAAAAAAACtc/j8It9ZFnPuA/s72-c/duck.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-1315047866928988019</id><published>2011-07-19T06:56:00.000-07:00</published><updated>2011-07-20T01:48:54.961-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>C++: Declaring a pointer to a template method</title><content type='html'>Busy writing some template gibberish, we needed to make a healthy trade in pointers to template-member-functions. Of template classes. (&lt;i&gt;Where the template function parameters themselves were pointers to template methods on template classes, but let's not worry about that detail right now&lt;/i&gt;).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It took a little run-up to get the C++ syntax right, so I present it here for your viewing pleasure.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All code tested against g++ 4.2.1 only.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Case 1: Normal pointer to member&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's just remind ourselves of the syntax for a simple pointer to (normal, non-template) member function:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note: I've gratuitously changed the &amp;lt; &amp;lt; stream operators into "--" just to get the syntax through blogger's composer window. Sorry about that. I pray that no other C++ syntax was sacrificed in this publishing exercise&lt;/div&gt;&lt;div&gt;&lt;pre&gt;class Target1&lt;br /&gt;{&lt;br /&gt; public:&lt;br /&gt;   void Method(int a)&lt;br /&gt;   {&lt;br /&gt;     std::cout -- "Target1(" -- a -- ")\n";&lt;br /&gt;   }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void PointerToNormalMemberFunction()&lt;br /&gt;{&lt;br /&gt; Target1 target;&lt;br /&gt; // This is how we construct a normal pointer to member function&lt;br /&gt; &lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;void (Target1::*oneParam)(int) = &amp;amp;Target1::Method;&lt;/span&gt;&lt;br /&gt; (target.*oneParam)(1);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Relatively simple.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Case 2: A pointer to template member function&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the first incursion of templates. If you're looking at a template method, this is how you'd declare your pointers to it:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;class Target2&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; template &amp;lt;typename T&amp;gt;&lt;br /&gt; void Method(T a)&lt;br /&gt; {&lt;br /&gt;   std::cout -- "Target2("--a--")\n";&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void PointerToTemplateMemberFunction()&lt;br /&gt;{&lt;br /&gt; Target2 target;&lt;br /&gt;&lt;br /&gt; // This is how we construct a pointer to a template member function&lt;br /&gt; // See how the template type of the method is mentioned at the end of the method name.&lt;br /&gt; void (Target2::*oneParamTemplateInt)(int)     = &amp;amp;Target2::Method&lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;&amp;lt;int&amp;gt;&lt;/span&gt;;&lt;br /&gt; void (Target2::*oneParamTemplateFloat)(float) = &amp;amp;Target2::Method&lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;&amp;lt;float&amp;gt;&lt;/span&gt;;&lt;br /&gt; (target.*oneParamTemplateInt)(2);&lt;br /&gt; (target.*oneParamTemplateFloat)(2.5);&lt;br /&gt;&lt;br /&gt; // However, the compiler can deduce the template type of the method&lt;br /&gt; void (Target2::*shorterInt)(int)     = &amp;amp;Target2::Method;&lt;br /&gt; void (Target2::*shorterFloat)(float) = &amp;amp;Target2::Method;&lt;br /&gt; (target.*shorterInt)(3);&lt;br /&gt; (target.*shorterFloat)(3.5);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Note that you can chose whether or not to specify the template types of the method when you assign it to your member-function pointer. The compiler can deduce these for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Case 3: Pointer to template methods with more than one template parameter&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is not significantly different from the above, we just extend the types in the pointer-to-member.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;class Target3&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; template &amp;lt;typenameT&amp;gt;&lt;br /&gt; void Method(T1 a, T2 b)&lt;br /&gt; {&lt;br /&gt;   std::cout -- "Target3("--a--","--b--")\n";&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void PointerToTemplateMemberFunctionWithTwoParameters()&lt;br /&gt;{&lt;br /&gt; Target3 target;&lt;br /&gt;&lt;br /&gt; // This is how we construct a pointer to a template member function&lt;br /&gt; // with multiple template parameters. Just like above, really.&lt;br /&gt; void (Target3::*oneParamTemplateIntFloat)(int,float)   = &amp;amp;Target3::Method&lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;&amp;lt;int,float&amp;gt;&lt;/span&gt;;&lt;br /&gt; void (Target3::*oneParamTemplateFloatInt)(float,int) = &amp;amp;Target3::Method&lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;&amp;lt;float,int&amp;gt;&lt;/span&gt;;&lt;br /&gt; (target.*oneParamTemplateIntFloat)(4,4.5);&lt;br /&gt; (target.*oneParamTemplateFloatInt)(4.5,4);&lt;br /&gt;&lt;br /&gt; // Again, the compiler can deduce the type of the methods&lt;br /&gt; void (Target3::*shorterIntFloat)(int,float)   = &amp;amp;Target3::Method;&lt;br /&gt; void (Target3::*shorterFloatInt)(float,int) = &amp;amp;Target3::Method;&lt;br /&gt; (target.*shorterIntFloat)(5,5.5);&lt;br /&gt; (target.*shorterFloatInt)(5.5,5);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Again, note, the compiler can generally deduce the correct template method without you having to specify the template parameter types.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Case 4: Pointer to template methods in a template class.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now it's getting sillier - a pointer to a template method in a template class. the syntax does still make sense, it just depends how far down the rabbit hole you want to go.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;template&amp;lt;typename TYPE&amp;gt;&lt;br /&gt;class Target4&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; Target4(const TYPE &amp;amp;value) : value(value) {}&lt;br /&gt; TYPE value;&lt;br /&gt;&lt;br /&gt; template &amp;lt;typename T&amp;gt;&lt;br /&gt; void OneParam(T a)&lt;br /&gt; {&lt;br /&gt;    std::cout -- "Target4::OneParam("--value--","--a--")\n";&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; template &amp;lt;typename T1, typename T2&amp;gt;&lt;br /&gt; void TwoParam(T1 a, T2 b)&lt;br /&gt; {&lt;br /&gt;    std::cout -- "Target4::TwoParam("--value--","--a--","--b--")\n";&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void PointerToTemplateMemberInTemplateClass()&lt;br /&gt;{&lt;br /&gt; Target4&amp;lt;char&amp;gt; target('c');&lt;br /&gt;&lt;br /&gt; &lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;void (Target4&amp;lt;char&amp;gt;::*oneParam)(float) = &amp;amp;Target4&amp;lt;char&amp;gt;::OneParam&amp;lt;float&amp;gt;&lt;/span&gt;;&lt;br /&gt; (target.*oneParam)(6.5);&lt;br /&gt;&lt;br /&gt; // Again, we can miss off the last template types&lt;br /&gt; &lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;void (Target4&amp;lt;char&amp;gt;::*shorter)(float) = &amp;amp;Target4&amp;lt;char&amp;gt;::OneParam&lt;/span&gt;;&lt;br /&gt; (target.*shorter)(6.75);&lt;br /&gt;&lt;br /&gt; // Two parameters just extends the scheme&lt;br /&gt; void (Target4&amp;lt;char&amp;gt;::*twoParam)(float,int) = &amp;amp;Target4&amp;lt;char&amp;gt;::TwoParam;&lt;br /&gt; (target.*twoParam)(6.8,6);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Case 5: Using a pointer to a template method of a template class inside the template class itself&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want to make use of a pointer to template method within a template class, you simply cannot specify the template method's parameter types. The compiler considers this a syntax error. So you have to rely on the compiler deducing the correct template method instantiation. (See &lt;i&gt;edit&lt;/i&gt; below.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the case of this example, it copes fine. In more complex cases, it may hurt less if your call template method overloads different names.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;template&amp;lt;typename TYPE&amp;gt;&lt;br /&gt;class Target5&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; Target5(const TYPE &amp;amp;value) : value(value) {}&lt;br /&gt; TYPE value;&lt;br /&gt;&lt;br /&gt; template &amp;lt;typename T&amp;gt;&lt;br /&gt; void OneParam(T a)&lt;br /&gt; {&lt;br /&gt;   std::cout -- "Target5::OneParam("--value--","--a--")\n";&lt;br /&gt;&lt;br /&gt;   typedef void (Target5&amp;lt;E&amp;gt;::*MethodTypeToCall)(T);&lt;br /&gt;   // Here, the compiler picks the right overload&lt;br /&gt;   &lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;MethodTypeToCall toCall = &amp;amp;Target5&amp;lt;E&amp;gt;::Private&lt;/span&gt;;&lt;br /&gt;   // In this case, the compiler does not let us write the following line (parse error):&lt;br /&gt;   //MethodTypeToCall toCall = &amp;amp;Target5&amp;lt;E&amp;gt;::Private&amp;lt;t;;&lt;br /&gt;   (this-&amp;gt;*toCall)(a);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; template &amp;lt;typename T1, typename T2&amp;gt;&lt;br /&gt; void TwoParam(T1 a, T2 b)&lt;br /&gt; {&lt;br /&gt;   std::cout -- "Target5::TwoParam("--value--","--a--","--b--")\n";&lt;br /&gt;&lt;br /&gt;   typedef void (Target5&amp;lt;E&amp;gt;::*MethodTypeToCall)(T1,T2);&lt;br /&gt;   &lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;MethodTypeToCall toCall = &amp;amp;Target5&amp;lt;E&amp;gt;::Private&lt;/span&gt;; // compiler picks the right overload&lt;br /&gt;   // you can't add the method's template parameters to the end of that line&lt;br /&gt;   (this-&amp;gt;*toCall)(a,b);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;&lt;br /&gt; template &amp;lt;typename T&amp;gt;&lt;br /&gt; void Private(T a)&lt;br /&gt;   { std::cout -- "Target5::Private("--value--","--a--")\n"; }&lt;br /&gt; template &amp;lt;typename T1, typename T2&amp;gt;&lt;br /&gt; void Private(T1 a, T2 b)&lt;br /&gt;   { std::cout -- "Target5::Private("--value--","--a--","--b--")\n"; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void HoldingAPointerToTemplateMemberInTemplateClass()&lt;br /&gt;{&lt;br /&gt; Target5&amp;lt;r&amp;gt; target('c');&lt;br /&gt;&lt;br /&gt; void (Target5&amp;lt;r&amp;gt;::*oneParam)(int) = &amp;amp;Target5&amp;lt;r&amp;gt;::OneParam;&lt;br /&gt; (target.*oneParam)(7);&lt;br /&gt; void (Target5&amp;lt;r&amp;gt;::*twoParam)(float,int) = &amp;amp;Target5&amp;lt;r&amp;gt;::TwoParam;&lt;br /&gt; (target.*twoParam)(7.5,7);&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Edit: it's been pointed to to me that you can name a specific overloaded template method using the following syntax. Add this to your pipe and smoke the whole template shenanigans:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;MethodTypeToCall toCall2 = &amp;amp;Target5&lt;type&gt;::&lt;span class="Apple-style-span"  style="color:#CC0000;"&gt;template&lt;/span&gt; Private&amp;lt;T&amp;gt;;&lt;/type&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This kind of template gibberish is why you &lt;i&gt;know&lt;/i&gt; you love C++.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Simples, init?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The extra thing we added to all this syntactical joy was to have one of the template method's (template) parameter types itself a pointer to a template method on a template class.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It was at this point our brains dribbled out of our ears, and we had to retrace our template syntax steps back up this rabbit hole.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-1315047866928988019?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/1315047866928988019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=1315047866928988019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1315047866928988019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1315047866928988019'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/07/c-declaring-pointer-to-template-method.html' title='C++: Declaring a pointer to a template method'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2527399844662875405</id><published>2011-07-18T07:08:00.000-07:00</published><updated>2011-07-18T07:15:17.904-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: It's The Thought That Accounts</title><content type='html'>&lt;a href="http://accu.org/content/images/journals/CVu233Cover.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 214px; height: 300px;" src="http://accu.org/content/images/journals/CVu233Cover.png" border="0" alt="" /&gt;&lt;/a&gt;The July issue of &lt;a href="http://www.accu.org"&gt;ACCU's&lt;/a&gt; C Vu magazine is out now. It contains the latest instalment in my &lt;b&gt;Becoming a Better Programmer&lt;/b&gt; column. This one's called &lt;b&gt;It's The Thought That Accounts. &lt;/b&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;In it I describe how you can become a better programmer, and how you will be encouraged to write better code, through &lt;i&gt;accountability&lt;/i&gt;. Far from being a dirty word, or some kind of bureaucratic nightmare, developer accountability can be fun, stimulating, enriching, and valuable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You'll also find out about my wine and running predilections.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a great issue of C Vu, with some really interesting articles. If you're a developer who is not already an ACCU member, then I &lt;i&gt;strongly&lt;/i&gt; urge you to join. It's super-cheap and really worthwhile!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll hold you accountable to that...&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2527399844662875405?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2527399844662875405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2527399844662875405' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2527399844662875405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2527399844662875405'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/07/writing-its-thought-that-accounts.html' title='Writing: It&apos;s The Thought That Accounts'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5647570405316769351</id><published>2011-06-24T01:40:00.000-07:00</published><updated>2011-06-24T01:44:12.058-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='becoming better'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Are we there yet? (Becoming a Better Programmer)</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/-onuM7X5kI-8/TgRN3QOqf4I/AAAAAAAACsg/JeA6-8RQZf4/s1600/CVuImage.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 188px; height: 200px;" src="http://2.bp.blogspot.com/-onuM7X5kI-8/TgRN3QOqf4I/AAAAAAAACsg/JeA6-8RQZf4/s200/CVuImage.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5621703846509838210" /&gt;&lt;/a&gt; &lt;p style="font-style: normal"&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;In the name of God, stop a moment, cease your work, look around you. &lt;/i&gt;&lt;b&gt;&lt;i&gt;Leo Tolstoy&lt;/i&gt;&lt;/b&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;A program is made of a number of subsystems. Each of those subsystems is composed of a smaller parts - components, modules, classes, functions, data types, and the like. Sometimes even boxes and lines. Or clever ideas.&lt;/p&gt; &lt;p style="font-style: normal"&gt;The jobbing programmer moves from one assignment to the next; from one task to another. Their working day is composed of a series of construction and maintenance tasks on a series of these software components: composing new parts, stitching parts together, extending, enhancing or mending existing pieces of code.&lt;/p&gt; &lt;p style="font-style: normal"&gt;So our job is simply a string of lots of smaller jobs. It's recursive. Programmers love that that kind of thing.&lt;/p&gt; &lt;h2 class="western"&gt;Are we there yet?&lt;/h2&gt; &lt;p style="font-style: normal"&gt;So there you are: getting the job done. (You think.)&lt;/p&gt; &lt;p style="font-style: normal"&gt;Just like a small child travelling in the back of a car constantly brays “&lt;i&gt;are we there yet?&lt;/i&gt;”, pretty soon you'll encounter the braying manager: “&lt;i&gt;are you done yet?&lt;/i&gt;”&lt;/p&gt; &lt;p style="font-style: normal"&gt;This is an important question. Its essential for a software developer to be able to answer that one simple request: to know what “done” looks like, and to have a realistic idea of how close you are to being “done”. And then to communicate it.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Many programmers fall short here; it's tempting to just keep hacking away until the task seems complete. They don't have a good grasp on whether they're nearly finished or not. They think: &lt;i&gt;There could be any number of bugs to iron out, or unforeseen problems to trip me up. I can't possibly tell if I'm almost done.&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;But that's simply not good enough. Usually, avoiding the question is an excuse for lazy practice, a justification for “coding from the hip”, without forethought and planning. It's not methodical.&lt;/p&gt; &lt;p style="font-style: normal"&gt;It's also likely to create problems for you. I often see people working far too hard:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="font-style: normal"&gt;They are doing more work than  necessary, because they didn't know when to stop.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Without knowing when they'll be  done, they don't actually &lt;i&gt;complete&lt;/i&gt; the tasks they think are  finished. This leads to having to pick things back up later on, to  work out what's missing and how to stitch it in. Code construction  is far slower and harder this way.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;The wrong bits of code get  polished, as the correct goal was never in sight. This is wasted  work.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Developers working too hard are  forced to put in extra hours. You'll not get enough sleep!&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="font-style: normal"&gt;Let's see how to avoid this and to answer “are we there yet” effectively.&lt;/p&gt; &lt;h2 class="western"&gt;Developing backwards: decomposition&lt;/h2&gt; &lt;p style="font-style: normal"&gt;Different programming shops manage their day-to-day development efforts differently. Often this depends on the size and structure of the software team.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Some place a single developer in charge of a large swathe of functionality, give them a delivery date, and ask them for occasional progress reports. Others follow “agile” processes, and manage a backlog of more granular tasks (perhaps phrasing them as &lt;i&gt;stories&lt;/i&gt;), divvying those out to programmers as they are able to move into a new task.&lt;/p&gt; &lt;p style="font-style: normal"&gt;The first step towards defining “done” is to know &lt;i&gt;exactly&lt;/i&gt; what you're working on. If it's a fiendishly large and complex problem, then it's going to be fiendishly complex to say when you'll be done.&lt;/p&gt; &lt;p style="font-style: normal"&gt;It's a far simpler exercise to answer how far through you are through a small, well-understood problem. Obvious, really.&lt;/p&gt; &lt;p style="font-style: normal"&gt;So if you have been allotted a monster task, before you begin chipping away at it, break it down into smaller, understandable parts. Too many people rush headlong into code or design without taking a step back to consider how they will work through it.&lt;/p&gt; &lt;p class="tip-western"&gt;Split large tasks up into a series of smaller, well-understood tasks. You will be able to judge progress through these more accurately.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Often this isn't a complex a task, at least for a top-level decomposition. (You may have to drill down a few times. Do so. But take note: this is an indication that you've been handed a task at far too high a granularity.)&lt;/p&gt; &lt;p style="font-style: normal"&gt;Sometimes such a decomposition is hard to do, and is a significant task itself. Don't let that put you off. If you don't do it up-front for estimation purposes, you'll only end up doing it later on in less focussed ways as you battle to the finish line.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Make sure that at any point in time, you know the smallest unit you're working on; rather than just the big target for your project.&lt;/p&gt; &lt;h2 class="western"&gt;Define done&lt;/h2&gt; &lt;p style="font-style: normal"&gt;You've got an idea of the big picture; you know what you're ultimately trying to build. And you know the particular sub-task you're working on at the moment.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Now, make sure that for whatever task you are working on, you know &lt;i&gt;when to stop&lt;/i&gt;.&lt;/p&gt; &lt;p style="font-style: normal"&gt;To do this, you have to define what “done” is. You have to know what “success” means. What the “complete” software will look like.&lt;/p&gt; &lt;p class="tip-western" align="LEFT"&gt;Make sure you define “done”.&lt;/p&gt; &lt;p style="font-style: normal"&gt;This is important. If you haven't determined when to stop, you'll keep working far past when you needed to. You'll be working harder and longer than you needed to. Or, you won't work hard enough – you'll not get everything done. (Not getting &lt;i&gt;everything&lt;/i&gt; done sounds easier, doesn't it? But it's not... the half-done work will come back to bite you, and will make more work for you later down the line, whether that's bugs, rework, or an unstable product).&lt;/p&gt; &lt;p style="font-style: normal"&gt;Don't start a piece of coding work until you know what success is. If you don't yet know, make your first task determining what “done” is. Only then, get going. With the certainty of knowing where you're headed, you'll be able to work in a focused, directed manner. You'll be able to make informed choices, and to discount unnecessary things that might side-track or delay you.&lt;/p&gt; &lt;p class="tip-western"&gt;If you can't tell when it's done, then you shouldn't start it.&lt;/p&gt; &lt;p style="font-style: normal"&gt;So how does this look in practice? How do you define “done”? Your “done” criteria needs to be:&lt;/p&gt; &lt;p style="margin-left: 0.49in; font-style: normal"&gt;&lt;b&gt;Clear&lt;/b&gt;&lt;/p&gt; &lt;p style="margin-left: 0.98in; font-style: normal"&gt;It must be unambiguous and specific. A list of all the features to be implemented, the APIs added or extended, or the specific faults to be fixed.&lt;/p&gt; &lt;p style="margin-left: 0.98in; font-style: normal"&gt;If, as you get into the task, you discover things that might affect the completion criteria (e.g. you discover more bugs that need fixing, or uncover unforeseen problems) then you must make sure that you reflect this in your “done” criteria.&lt;/p&gt; &lt;p style="margin-left: 0.98in; font-style: normal"&gt;This criteria is usually directly traceable to some software requirements or a user story – if you have them. If this is the case, make sure that this connection is documented.&lt;/p&gt; &lt;p style="margin-left: 0.49in; font-style: normal"&gt;&lt;b&gt;Visible&lt;/b&gt;&lt;/p&gt; &lt;p style="margin-left: 0.98in; font-style: normal"&gt;Make sure that the success criteria is seen by all important parties. This probably includes: your manager, your customers, the downstream teams using your code, or the testers who will validate your work.&lt;/p&gt; &lt;p style="margin-left: 0.98in; font-style: normal"&gt;Make sure everyone knows and agrees on this criteria. And make sure they'll have a way of telling – and agreeing – when you are “done”.&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;The nature of each task will clearly define what “done” means. However you should consider:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="font-style: normal"&gt;How much code must be completed.  (Do you measure this in units of functionality, APIs implemented,  user stories completed?)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How much is design done, and how  it's captured.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Whether any documents or reports  must be generated.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;When it's a coding task, you can mostly clearly demonstrate “being done” by creating an unambiguous test set. Write tests that will show when you've fashioned the full suite of code required.&lt;/p&gt; &lt;p class="tip-western"&gt;Use tests written in code to define when your code is complete and working.&lt;/p&gt; &lt;p style="font-style: normal"&gt;There are some other questions that you may have to consider when you describe what “done” is:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="font-style: normal"&gt;Where is the code delivered to?  (e.g. to version control)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Where is the code deployed to? (Is  it “done” when it's live on a server - or do you deliver  testable product ready for a deployment team to roll out?)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;What are the economics of “done”?  The exact numbers required that may lead to certain tradeoffs or  measurements. For example: how well should your solution scale? It's  not good enough if your software only manages 10 simultaneous users  if 10,000 are required. The more precise your done criteria the  better you understand these economics.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How will you signal that you're  done? When you think you're done how will you let the  customer/manager/QA department know? This probably looks different  for each person. How will you garner agreement that you are indeed  done – who signs-off on your work? Do you just check in, do you  change a project reporting ticket, or do you raise an invoice?&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h2 class="western"&gt;Just do it&lt;/h2&gt; &lt;p style="font-style: normal"&gt;When you've defined “done”, you can work with focus. Work up to the “done” point. Don't do more than necessary.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Stop when your code is good enough – not &lt;i&gt;necessarily&lt;/i&gt; perfect (there may be a real difference between the two states). If the code gets used or worked on an awful lot, it may eventually be refactored to be perfect – but don't polish it yet. This may just be wasted effort. (Beware: this is not an excuse to write &lt;i&gt;bad code&lt;/i&gt;, just a warning against unnecessary over-polishing).&lt;/p&gt; &lt;p class="tip-western"&gt;Don't do more work than necessarily. Work until you're “done”. Then stop.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Having a single, specific goal in mind helps you to focus on a single task. Without this focus it's easy to hack at code randomly trying to achieve a number of things and not managing any of them successfully.&lt;/p&gt; &lt;h2 class="western"&gt;Questions&lt;/h2&gt; &lt;ol&gt;  &lt;li&gt;&lt;p style="font-style: normal"&gt;Do you know when you're current  task will be “done”? What does “done” look like?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Have you decomposed your current  task into a single goal, or a series of simple goals?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Do you decompose your work into  achievable, measurable units?&lt;/p&gt; &lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5647570405316769351?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5647570405316769351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5647570405316769351' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5647570405316769351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5647570405316769351'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/06/are-we-there-yet-becoming-better.html' title='Are we there yet? (Becoming a Better Programmer)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-onuM7X5kI-8/TgRN3QOqf4I/AAAAAAAACsg/JeA6-8RQZf4/s72-c/CVuImage.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8786203958942732368</id><published>2011-06-09T18:26:00.000-07:00</published><updated>2011-06-09T18:35:26.808-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='enigma'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>The Enigma Continues</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/-DD4fltCAols/TfFzs9gz6mI/AAAAAAAACsA/2_RZsHjM0TE/s1600/iTunesArtworkWithBorder.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://2.bp.blogspot.com/-DD4fltCAols/TfFzs9gz6mI/AAAAAAAACsA/2_RZsHjM0TE/s200/iTunesArtworkWithBorder.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5616397426571340386" /&gt;&lt;/a&gt;Version 1.4 of my cool iOS puzzle game, &lt;b&gt;The Enigma Squares&lt;/b&gt;, has been released. Check it out &lt;a href="http://itunes.apple.com/us/app/the-enigma-squares/id433136664?mt=8"&gt;here&lt;/a&gt;. In this version, I present you more than 80 new levels, with a number of fun, a number of fiendish, and a number of speed-trial puzzles.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check it out on &lt;a href="http://itunes.apple.com/us/app/the-enigma-squares/id433136664?mt=8"&gt;iTunes now&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also released a new game. &lt;b&gt;The Enigma Kids&lt;/b&gt; is a family-oriented puzzler. With child-friendly puzzles, great graphics and lots of fun, everyone will enjoy this game.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check out The Enigma Kids &lt;a href="http://itunes.apple.com/us/app/the-enigma-kids/id436627746?mt=8"&gt;on iTunes here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me know what you think!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8786203958942732368?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8786203958942732368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8786203958942732368' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8786203958942732368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8786203958942732368'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/06/enigma-continues.html' title='The Enigma Continues'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-DD4fltCAols/TfFzs9gz6mI/AAAAAAAACsA/2_RZsHjM0TE/s72-c/iTunesArtworkWithBorder.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-338198251192700604</id><published>2011-05-25T06:16:00.000-07:00</published><updated>2011-05-25T06:25:17.941-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Optimising Parallels performance for development</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-u8t4OVMiEK4/Td0BapcJTaI/AAAAAAAACr0/GtaInLQSDrM/s1600/Parallels_logo.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 80px;" src="http://3.bp.blogspot.com/-u8t4OVMiEK4/Td0BapcJTaI/AAAAAAAACr0/GtaInLQSDrM/s200/Parallels_logo.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5610642268085636514" /&gt;&lt;/a&gt;&lt;div&gt;I use the wonderful &lt;a href="http://www.parallels.com/"&gt;Parallels 6&lt;/a&gt; to perform all my Windows development. (I find working on a Mac makes Windows development a lot more bearable - at least for this old Unix-head).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In general, Parallels works superbly (and is &lt;a href="http://www.mactech.com/articles/mactech/Vol.25/25.04/VMBenchmarks/"&gt;reported&lt;/a&gt; &lt;a href="http://www.parallels.com/uk/landingpage/pd6-vs-fusion/?source=g_uk&amp;amp;gclid=CPCBkvOYg6kCFdFX4QodbQtySg"&gt;to&lt;/a&gt; perform &lt;a href="http://osxdaily.com/2010/12/19/vmware-vs-parallels-6/"&gt;a lot better&lt;/a&gt; than VMware, if you &lt;a href="http://www.mactech.com/2011/01/05/virtualization-benchmarks"&gt;believe the hype&lt;/a&gt;). However, for operations like rebuilding a large, complex&lt;a href="http://en.wikipedia.org/wiki/Spaghetti_code"&gt; C++ source tree&lt;/a&gt;, the virtual machine performance lagged a long way behind a native machine. Large compiles can take more than twice the time of a real Windows PC. Clearly, this taxes the host machine hard: hammering CPU, memory, and disk at once.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This problem exhibits on my four core Mac Pro with as many resources as I could throw at the problem, as well as on my more humble MacBook Pro.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I performed a number of experiments to work out how to fix this:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Tweaking the allocated CPU cores, memory, and disk space&lt;/li&gt;&lt;li&gt;Tweaking the settings for the virtual hard drive&lt;/li&gt;&lt;li&gt;Network building from host mac file system&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;None of these made much difference. In fact, I was somewhat surprised that operating on a networked disk was &lt;i&gt;fantastically&lt;/i&gt; slower. That was a shame, as it would be advantageous to share a single source tree with my Xcode development for cross-platform development. (As it happens, I manage this by having a Windows-side git clone of the git repo on the Mac side).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, I've now managed to get my compile times right down. Here's how.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Do bare in mind that these tweaks are in addition to the obvious steps you should take with any machine:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Have as fast a CPU as possible.&lt;/li&gt;&lt;li&gt;Throw as many CPU cores as you can at the problem - builds can be parallelised very easily.&lt;/li&gt;&lt;li&gt;Throw as much memory as you have at your disposal at the problem.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1. Swap the swap&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The factor slowing me down the most turned out to be the Parallels virtual disk that Windows was running on. First, the swap file was hosted on it. So I made a second virtual disk, and pushed the virtual memory off onto it. That made a small, but appreciable difference.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. Only ever use fixed size disks&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In your disk settings, do &lt;i&gt;not&lt;/i&gt; use automatically expanding disks. That's just another overhead for the computer to manage whilst accessing disks. Create a fixed size blob of disk space and run with it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;3. Use a virtual SCSI disk&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the big one. So pay attention at the back.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It seems that Parallels can emulate a SCSI disk far, far faster than it can emulate and IDE disk. However, it defaults to creating IDE disks. I believe that this is to make installation of Windows simpler, as you don't have to fettle with custom SCSI drivers during installation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can't just switch the main disk from IDE to SCSI, though. Windows has a &lt;a href="http://en.wikipedia.org/wiki/Tantrum"&gt;minor eppe&lt;/a&gt; and refuses to run if you do that. I couldn't be bothered to wipe it all and try to reinstall on a new SCSI virtual disk, so I added yet another large SCSI virtual disk for my source trees and checked out onto that disk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Remember: it's a fixed size, non-expanding SCSI disk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With this configuration the build simply screams in comparison to building on the virtual IDE C: drive.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope you find this information useful!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-338198251192700604?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/338198251192700604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=338198251192700604' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/338198251192700604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/338198251192700604'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/optimising-parallels-performance-for.html' title='Optimising Parallels performance for development'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-u8t4OVMiEK4/Td0BapcJTaI/AAAAAAAACr0/GtaInLQSDrM/s72-c/Parallels_logo.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4593116445391978845</id><published>2011-05-13T16:34:00.000-07:00</published><updated>2011-05-13T16:42:27.424-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: The Enigma Squares (1.2)</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-nreC2qW2oWI/Tc3AYKSfgmI/AAAAAAAACrs/QrCikbm9tuo/s1600/Title%25402x.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 70px;" src="http://3.bp.blogspot.com/-nreC2qW2oWI/Tc3AYKSfgmI/AAAAAAAACrs/QrCikbm9tuo/s200/Title%25402x.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5606348632457445986" /&gt;&lt;/a&gt;&lt;b&gt;&lt;a href="http://bit.ly/hDS5z6"&gt;The Enigma Squares&lt;/a&gt;&lt;/b&gt; version 1.2 is available in the App Store now. Amongst other excitement, it adds &lt;a href="http://www.google.co.uk/aclk?sa=L&amp;amp;ai=CAbf3mMHNTZLNFsG-hAePrNFp0oWbkALC_JXoJ-TWrucBCAAQASC5VFC4vMPv-f____8BYLu-nIPQCsgBAakCT49S6WUkuz6qBBlP0Gujr1m8PmLclL8sdZfMV99b3NAWkt7AgAWQTg&amp;amp;sig=AGiWqtw5IK_bPBuRv8FmMhb-BR8WrOrH3w&amp;amp;ved=0CBUQ0Qw&amp;amp;adurl=http://track.searchignite.com/si/cm/tracking/clickredirect.aspx%3Fsicontent%3D0%26sicreative%3D10593865914%26sitrackingid%3D237006879&amp;amp;rct=j&amp;amp;q=game%20center"&gt;Game Center&lt;/a&gt; support. You can now share your achievements and high score with other players. Woo hoo.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So far, I'm very impressed at how far players have got. I'm glad the game is providing an interesting challenge!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More interesting updates are in the pipeline...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4593116445391978845?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4593116445391978845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4593116445391978845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4593116445391978845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4593116445391978845'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/ios-enigma-squares-12.html' title='iOS: The Enigma Squares (1.2)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-nreC2qW2oWI/Tc3AYKSfgmI/AAAAAAAACrs/QrCikbm9tuo/s72-c/Title%25402x.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7906288271826448845</id><published>2011-05-12T07:01:00.000-07:00</published><updated>2011-05-13T13:46:34.233-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: Packaging apps store submissions from the command line (my zip broke)</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/-TvCq23-cdbc/TcvoREgQ0ZI/AAAAAAAACrk/rxSH-kC6LQo/s1600/Screen%2Bshot%2B2011-04-20%2Bat%2B10.57.27.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 117px;" src="http://2.bp.blogspot.com/-TvCq23-cdbc/TcvoREgQ0ZI/AAAAAAAACrk/rxSH-kC6LQo/s200/Screen%2Bshot%2B2011-04-20%2Bat%2B10.57.27.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5605829541157196178" /&gt;&lt;/a&gt;&lt;i&gt;How to package iOS apps for submission to iTunes Connect from the command line.&lt;/i&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;I'm a firm believer in the power of the command line. I like my &lt;a href="http://www.computinghistory.org.uk/cgi-bin/sitewise.pl?act=det&amp;amp;p=3472"&gt;GUI tools&lt;/a&gt; as much as the next man (as long as he's a bearded Unix guru from the 1970s). But for sheer power, repeatability and flexibility you just can't beat a good script.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which is why every project I work on has to have a simple single script that configures, builds, and packages the code, creating a well-named payload that can be installed/submitted/deployed. I feel a lot safer about the quality of a release if it's generated by a tried-and-tested script, rather than by a series of button clicks in a series of separate tools.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You know it makes sense.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;iOS projects submitted to the App Store are effectively &lt;a href="http://en.wikipedia.org/wiki/ZIP_(file_format)"&gt;zip files&lt;/a&gt; with a particular directory structure. You can drive Xcode with the &lt;a href="http://www.manpagez.com/man/1/xcodebuild/"&gt;xcodebuild&lt;/a&gt; tool to build and link your distribution version of an iOS app.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, whenever I tried to zip the project up from the command line, the&lt;i&gt; Application Loader&lt;/i&gt; utility (what you use to submit your app to iTunes Connect) just gave bizare errors.&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;i&gt;The CodeResources files must be a symbolic link to _CodeSygnature/CodeResources. Make certain that the bundle is on a locally-mounted volume...&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;i&gt;Application failed codesign verification. The signature was invalid, or it was not signed with an Apple submission certificate.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Well, that's nice gibberish. Not.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, a zip archive created using the Finder's "Compress" menu entry worked fine. Very frustrating.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Don't fear! I fixed it. Here's how to do it in your very own build script: your &lt;a href="http://www.manpagez.com/man/1/zip/"&gt;zipper&lt;/a&gt; is broken; throw it out. Use &lt;a href="http://www.manpagez.com/man/1/ditto/"&gt;ditto&lt;/a&gt; instead. Here's the line from my build script:&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;APP_FILENAME=/path/to/build/Application.app&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;PACKAGED_FILENAME=MyGoodPackagedFilename.zip&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;ditto -c -k --keepParent --rsrc "$APP_FILENAME" "$PACKAGED_FILENAME"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy your build scripts.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7906288271826448845?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7906288271826448845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7906288271826448845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7906288271826448845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7906288271826448845'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/ios-packaging-apps-store-submissions.html' title='iOS: Packaging apps store submissions from the command line (my zip broke)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-TvCq23-cdbc/TcvoREgQ0ZI/AAAAAAAACrk/rxSH-kC6LQo/s72-c/Screen%2Bshot%2B2011-04-20%2Bat%2B10.57.27.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2260027909473618143</id><published>2011-05-05T05:35:00.001-07:00</published><updated>2011-05-05T05:40:20.033-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Becoming a Better Programmer</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s200/ChoseToCare.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s200/ChoseToCare.png" border="0" alt="" /&gt;&lt;/a&gt;My &lt;b&gt;Becoming a Better Programmer&lt;/b&gt; presentation given at ACCU 2011 has been &lt;i&gt;very&lt;/i&gt; popular recently. It's one of the most-viewed presentations on &lt;a href="http://www.slideshare.net/petegoodliffe/becoming-a-better-programmer"&gt;slideshare&lt;/a&gt; this month.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At the time of writing, there have been more than 12,500 views of the entire presentation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is both exciting and flattering - and nice to know that developers truly do care about improving their skills. And nice to know that I have been able to help.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check it out &lt;a href="http://www.slideshare.net/petegoodliffe/becoming-a-better-programmer"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2260027909473618143?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2260027909473618143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2260027909473618143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2260027909473618143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2260027909473618143'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/becoming-better-programmer.html' title='Becoming a Better Programmer'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s72-c/ChoseToCare.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-890909542450461411</id><published>2011-05-05T05:25:00.001-07:00</published><updated>2011-05-05T05:32:08.858-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Relish the Challenge</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-KSxvwgoRm-s/TcKXjR0tKCI/AAAAAAAACrc/P8mqqOI4qps/s1600/cvu-cover-small.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 142px; height: 200px;" src="http://3.bp.blogspot.com/-KSxvwgoRm-s/TcKXjR0tKCI/AAAAAAAACrc/P8mqqOI4qps/s200/cvu-cover-small.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5603207518737999906" /&gt;&lt;/a&gt;&lt;div&gt;The May issue of &lt;a href="http://www.accu.org/"&gt;ACCU's&lt;/a&gt; C Vu magazine will be hitting doormats any moment now. It contains the latest instalment in my &lt;b&gt;Becoming a Better Programmer&lt;/b&gt; column. This one's called &lt;b&gt;Relish the Challenge&lt;/b&gt;, and is an encouragement to stay motivated and challenged, to seek out new things, and to avoid becoming stale and staid as a developer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope it's useful. For your stimulation, I've added the final questions from the article to the end of this blog post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The PDF version of the magazine will be available for download by ACCU members shortly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The cover I created for this month's issue is quite dense and busy. I wonder if that's any reflection on the designer?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;Questions&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Do you have projects that challenge you and stretch your skills?&lt;/li&gt;&lt;li&gt;Are there some ideas you’ve thought about for a while, but not started? Why not start a little side-project?&lt;/li&gt;&lt;li&gt;Do you balance ‘interesting’ challenges with your ‘day to day’ work?&lt;/li&gt;&lt;li&gt;Are you challenged by other motivated programmers around you?&lt;/li&gt;&lt;li&gt;Do you have a broad field of interest that informs your work?&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-890909542450461411?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/890909542450461411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=890909542450461411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/890909542450461411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/890909542450461411'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/writing-relish-challenge.html' title='Writing: Relish the Challenge'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-KSxvwgoRm-s/TcKXjR0tKCI/AAAAAAAACrc/P8mqqOI4qps/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4477590437971587540</id><published>2011-05-04T06:39:00.000-07:00</published><updated>2011-05-04T06:47:19.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='enigma'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: The Enigma Squares</title><content type='html'>&lt;a href="http://1.bp.blogspot.com/-zzdXHUkpJkc/TcFXPp__BbI/AAAAAAAACrU/X8b5vD-oT1I/s1600/Title%25402x.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 70px;" src="http://1.bp.blogspot.com/-zzdXHUkpJkc/TcFXPp__BbI/AAAAAAAACrU/X8b5vD-oT1I/s200/Title%25402x.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5602855337909487026" /&gt;&lt;/a&gt;My first &lt;i&gt;personal&lt;/i&gt; iOS project has finally seem the light of day. Please welcome into the world &lt;b&gt;&lt;a href="http://bit.ly/hDS5z6"&gt;The Enigma Squares&lt;/a&gt;&lt;/b&gt;. It's an interesting (and dare I say it) entertaining block-moving puzzle game.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check it out on &lt;a href="http://bit.ly/hDS5z6"&gt;iTunes here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've produced plenty of iOS projects for my company. But this has been an entertaining personal side-project, to keep me busy through those long spring evenings.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is actually a version of a game I first wrote (ahem) 20 years ago. Back then it was written for the Acorn Archimedes, and I sold it to a magazine for inclusion on their cover disk (remember those?) This version is a little more polished, a little more challenging, and a lot more fun.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The code's a fair bit better too, but that's another story. One that I'm sure I'll tell one day...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me know what you think of it!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4477590437971587540?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4477590437971587540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4477590437971587540' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4477590437971587540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4477590437971587540'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/05/ios-enigma-squares.html' title='iOS: The Enigma Squares'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-zzdXHUkpJkc/TcFXPp__BbI/AAAAAAAACrU/X8b5vD-oT1I/s72-c/Title%25402x.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8226187975620858846</id><published>2011-04-20T06:46:00.000-07:00</published><updated>2011-04-20T06:58:26.480-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Code: Gibberish++</title><content type='html'>I love C++.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And I hate it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whenever I pick up my C++ compiler, it feels like I'm coming home. It's a wonderfully powerful language, and one that, in the hands of the experienced, can be used to craft exquisite code. It can also be made to construct a bloody mess. Literally.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's a sharp tool. With sharp edges. Whenever you pick it up, you realise that you have a sharp tool already covered in the blood of previous unfortunate users.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://en.wikipedia.org/wiki/Uncle_Ben#.22With_great_power_comes_great_responsibility.22"&gt;With great power comes great responsibility&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The language ranges from the &lt;a href="http://www.boost.org/"&gt;sublime&lt;/a&gt; to the &lt;a href="http://en.wikipedia.org/wiki/Auto_ptr"&gt;ridiculous&lt;/a&gt;, through fields of the inexplicable, unusable, and unreadable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A great example of the gibberish end of C++'s spectrum is this example given me be a colleague.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What does the following code print?:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;using namespace std;&lt;br /&gt;int x = 50;&lt;br /&gt;cout &amp;lt;&amp;lt; setw(8) &amp;lt;&amp;lt; setfill('0') &amp;lt;&amp;lt; showbase &amp;lt;&amp;lt; hex; cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; endl;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Any guesses?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer is: &lt;span class="Apple-style-span"  style=" ;font-family:Calibri, sans-serif;"&gt;00000x32. Um, handy.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Calibri, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;What you have to say is this:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;using namespace std;&lt;br /&gt;int x = 50;&lt;br /&gt;cout &amp;lt;&amp;lt; setw(8) &amp;lt;&amp;lt; setfill('0') &amp;lt;&amp;lt; internal &amp;lt;&amp;lt; showbase &amp;lt;&amp;lt; hex; cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; endl;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;To get: &lt;span class="Apple-style-span"  style=" ;font-family:Calibri, sans-serif;"&gt;0x000032&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Iostreams. Gibberish++&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8226187975620858846?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8226187975620858846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8226187975620858846' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8226187975620858846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8226187975620858846'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/04/code-gibberish.html' title='Code: Gibberish++'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4603756140441330810</id><published>2011-04-19T07:52:00.000-07:00</published><updated>2011-04-19T07:57:06.473-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Speaking: ACCU 2011 slides available</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s1600/ChoseToCare.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s200/ChoseToCare.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5597308518043943970" /&gt;&lt;/a&gt;The slides from all of my ACCU 2011 talks are now available for your viewing pleasure on &lt;a href="http://www.slideshare.net/"&gt;SlideShare&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Find them here:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/petegoodliffe/becoming-a-better-programmer"&gt;Becoming a Better Programmer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/petegoodliffe/manyfestos"&gt;Manyfestos&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/petegoodliffe/coping-with-complexity"&gt;Coping With Complexity&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.slideshare.net/petegoodliffe/thee-objectionable-things"&gt;Three Objectionable Things&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Thanks for all the great feedback!&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're interested in me giving these talks for you, then get in touch.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4603756140441330810?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4603756140441330810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4603756140441330810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4603756140441330810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4603756140441330810'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/04/speaking-accu-2011-slides-available.html' title='Speaking: ACCU 2011 slides available'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4jta-5677lk/Ta2icPxHBCI/AAAAAAAACrM/5yEoJY7N_dE/s72-c/ChoseToCare.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8754983824980867508</id><published>2011-04-05T06:39:00.000-07:00</published><updated>2011-04-05T07:24:57.917-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: A Fading AVAudioPlayer</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/_8du__Wxp8q4/SmXg-3-RzWI/AAAAAAAAAAw/t_jlGkPfXIM/S1600-R/no_music.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 364px; height: 200px;" src="http://4.bp.blogspot.com/_8du__Wxp8q4/SmXg-3-RzWI/AAAAAAAAAAw/t_jlGkPfXIM/S1600-R/no_music.png" border="0" alt="" /&gt;&lt;/a&gt;In a recent iOS project I needed to play some background music and have it fade smoothly in and out when it starts and stops.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The "play some music" part is easy. iOS give us &lt;a href="http://developer.apple.com/library/ios/#DOCUMENTATION/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html"&gt;AVAudioPlayer&lt;/a&gt; in the AVFoundation framework. Super sweet and easy to use. However the "fade in and out" bit doesn't come for free.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The canonical solution suggested on the web is to hand-craft some nasty looping logic to get the job done. This is 2011 and we can do better than that. And, indeed, &lt;a href="https://gitorious.org/audioplayerwithfade/audioplayerwithfade"&gt;here it is&lt;/a&gt;, in all it's Objective C glory.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My solution makes interesting use of &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20-SW1"&gt;categories&lt;/a&gt;, &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20-SW1"&gt;associative references&lt;/a&gt; and &lt;a href="http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxGettingStarted.html%23//apple_ref/doc/uid/TP40007502-CH7-SW1"&gt;blocks&lt;/a&gt;. It's worth strolling through the implementation if you're interested in any of these. If not, you can just grab my code from the &lt;a href="https://gitorious.org/audioplayerwithfade/audioplayerwithfade"&gt;Gitorious project&lt;/a&gt; and use it in blissful ignorance.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1. Add a category&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, we open up our own category on the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;AVAudioPlayer&lt;/span&gt; class and define the methods we would ideally like the class to provide:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;@interface AVAudioPlayer (PGFade)&lt;br /&gt;- (void) stopWithFadeDuration:(NSTimeInterval)duration;&lt;br /&gt;- (void) playWithFadeDuration:(NSTimeInterval)duration;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's the joys of categories - you can extend existent classes in your own application easily to make it look like methods were part of the original class interface. The common convention is to save this in a file called "&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;AVAudioPlayer+PGFade.h&lt;/span&gt;".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now client code can create a bog-standard AVAudioPlayer object, and call my new methods as if they were part of the base interface:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;AVAudioPlayer *player = [AVAudioPlayer alloc] initWith...]; // however you want it set up&lt;br /&gt;[player playWithFadeDuration:2.0];&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. Associative References&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, our implementation of this is going to require some instance variables (ivars) to work with. The problem with categories is that they only allow you to add methods - you can't extend the set of instance variables defined in the class' &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@interface&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Or can you?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Associative references&lt;/i&gt; to the rescue! This is a handy Objective C runtime facility that allows you to associate another object with an existing object, with a lookup system very much like a dictionary - referenced by a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;void*&lt;/span&gt; key value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The associated object is lifetime-managed with the original object, so when you release the parent, all associated objects are also released.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using this facility we can "graft on" some of our own private ivars to the original class. Dirty, but effective.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the variables I need is a boolean variable tracking whether a fade is currently in progress. I actually expose this as a property called &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;fading&lt;/span&gt; in the category interface. The implementation looks like this:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;@implementation AVAudioPlayer (PGFade)&lt;br /&gt;&lt;br /&gt;static char fadingKey;&lt;br /&gt;&lt;br /&gt;- (BOOL) fading&lt;br /&gt;{&lt;br /&gt;NSNumber *number = (NSNumber *)objc_getAssociatedObject(self, &amp;amp;fadingKey);&lt;br /&gt;return number &amp;amp;&amp;amp; number.boolValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void) setFading:(BOOL)fading&lt;br /&gt;{&lt;br /&gt;objc_setAssociatedObject(self, &amp;amp;fadingKey, [NSNumber numberWithBool:fading], OBJC_ASSOCIATION_RETAIN_NONATOMIC);&lt;br /&gt;}&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Georgia, serif; white-space: normal; font-size: 16px; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="font-family: Georgia, serif; white-space: normal; font-size: 16px; "&gt;That's relatively simple. We just use two objective C runtime functions,  &lt;span class="Apple-style-span"  style="  white-space: pre; font-family:monospace;"&gt;objc_getAssociatedObject &lt;/span&gt;and &lt;span class="Apple-style-span"  style="  white-space: pre; font-family:monospace;"&gt;objc_setAssociatedObject&lt;/span&gt;. For the association we use the address of a static variable - this will be an unambiguous value in the whole program. The object we store is an NSNumber object initialised with the value of our boolean.&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's a simple and effective trick.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;3. Blocks&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The final bit is for bonus points. You can see the implementation of my fade routine in the example project code itself. It's pretty simple - I just initialise the fade state in a few more "associative reference" variables and schedule a method call with &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html"&gt;performSelector:withObject:afterDelay&lt;/a&gt;. Each time this is called, I adjust the AVAudioPlayer's volume, and schedule a new call if one is needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, to truly perform a stop with fade, we need to ramp the audio volume down, and when it gets to zero stop the player. This could be achieved with some more state variables and clumsy logic, but iOS now provides us with blocks which are perfect for this kind of activity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For sanity, I typedef a block (closure) type. The syntax practically identical to typedefing a pointer-to-function in C, but with ^ instead of *.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="  white-space: pre; font-family:monospace;"&gt;typedef void (^AVAudioPlayerFadeCompleteBlock)();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I make one more associated variable of this type, the block to call on completion:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;- (AVAudioPlayerFadeCompleteBlock) fadeCompletion&lt;br /&gt;{&lt;br /&gt;return (AVAudioPlayerFadeCompleteBlock)objc_getAssociatedObject(self, &amp;amp;fadeCompletionKey);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void) setFadeCompletion:(AVAudioPlayerFadeCompleteBlock)completion&lt;br /&gt;{&lt;br /&gt;objc_setAssociatedObject(self, &amp;amp;fadeCompletionKey, completion, OBJC_ASSOCIATION_COPY_NONATOMIC);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that blocks can be traded like objective C objects. You can retain, copy, and release them. In this case our code needs to take a copy (using the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;OBJC_ASSOCIATION_COPY_NONATOMIC&lt;/span&gt; flag). This ensures that any set block exists on the heap (persistent) rather than the default on-the-stack location.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, the internal "audio fade" routine need only check whether there is a completion block registered when the fade is complete, and if so call it:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;    if (fadeIsComplete)&lt;br /&gt;{&lt;br /&gt;    self.fading = NO;&lt;br /&gt;    AVAudioPlayerFadeCompleteBlock completion = self.fadeCompletion;&lt;br /&gt;    if (completion) completion();&lt;br /&gt;    self.fadeCompletion = nil;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Invoking a block looks just like calling a function. Once called, we clear out the stored block in case it is holding other resources that should be released.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This provides an elegant way to perform any arbitrary action after the fade is complete.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;That's all, folks!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The trio of Objective C facilities used here work together well to provide a simple and elegant solution to a problem that is often achieved with complex "strings-and-glue" logic. Check out the entire project on &lt;a href="https://gitorious.org/audioplayerwithfade/audioplayerwithfade"&gt;Gitorious here&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8754983824980867508?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8754983824980867508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8754983824980867508' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8754983824980867508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8754983824980867508'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/04/ios-fading-avaudioplayer.html' title='iOS: A Fading AVAudioPlayer'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_8du__Wxp8q4/SmXg-3-RzWI/AAAAAAAAAAw/t_jlGkPfXIM/s72-Rc/no_music.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6772204274000655743</id><published>2011-04-05T00:38:00.001-07:00</published><updated>2011-04-05T00:42:50.383-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Speaking: ACCU 2011</title><content type='html'>&lt;a href="http://4.bp.blogspot.com/-TPtv5Ld9-VI/TZrHH6CcfOI/AAAAAAAACqo/ZEB-ISnNPUE/s1600/2010-03-28%2BBecoming%2Ba%2BBetter%2BProgrammer.001.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://4.bp.blogspot.com/-TPtv5Ld9-VI/TZrHH6CcfOI/AAAAAAAACqo/ZEB-ISnNPUE/s200/2010-03-28%2BBecoming%2Ba%2BBetter%2BProgrammer.001.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5592000825986415842" /&gt;&lt;/a&gt;I will be speaking at the &lt;a href="http://www.accu.org/conference"&gt;ACCU 2011 conference&lt;/a&gt; in Oxford this month.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My talk is entitled &lt;b&gt;&lt;i&gt;Becoming a Better Programmer&lt;/i&gt;&lt;/b&gt;, and it's going to be great fun. And hopefully very useful, too. This year green is very much the new blue. Details (intentionally vague) on the session are &lt;a href="http://accu.org/index.php/conferences/accu_conference_2011/accu2011_sessions#Becoming%20a%20Better%20Programmer"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will also be speaking in the &lt;b&gt;&lt;i&gt;Key practices to cope with complexity&lt;/i&gt;&lt;/b&gt; session (details &lt;a href="http://accu.org/index.php/conferences/accu_conference_2011/accu2011_sessions#Key%20practices%20to%20cope%20with%20complexity"&gt;here&lt;/a&gt;). Let's hope I don't make my contribution needlessly complex.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6772204274000655743?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6772204274000655743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6772204274000655743' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6772204274000655743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6772204274000655743'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/04/speaking-accu-2011.html' title='Speaking: ACCU 2011'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-TPtv5Ld9-VI/TZrHH6CcfOI/AAAAAAAACqo/ZEB-ISnNPUE/s72-c/2010-03-28%2BBecoming%2Ba%2BBetter%2BProgrammer.001.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-946432978622672038</id><published>2011-03-18T08:53:00.000-07:00</published><updated>2011-03-18T08:57:53.415-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: Prettier auto-rotation</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-nBIx5eTBAyA/TYOA6lIO6hI/AAAAAAAACqg/6qMYHSq5MQw/s1600/sign_mini%2Broundabout.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 198px; height: 200px;" src="http://2.bp.blogspot.com/-nBIx5eTBAyA/TYOA6lIO6hI/AAAAAAAACqg/6qMYHSq5MQw/s200/sign_mini%2Broundabout.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5585449706756958738" /&gt;&lt;/a&gt;&lt;div&gt;A simple Friday iOS coding tip for you:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When your app auto-rotates do you have an unsightly white frame appearing around the edges of your beautifully hand-crafted UI?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;The default Xcode UIView-based project template creates a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;UIWindow&lt;/span&gt; with a white background. The white frame on rotation is the background of the UIWindow peeping out behind your UIView subview.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The simple fix to your UI woes: make the UIWindow background clear (either in the XIB file, or just before your call to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;[window makeKeyAndVisible]&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Simples!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-946432978622672038?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/946432978622672038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=946432978622672038' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/946432978622672038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/946432978622672038'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/03/ios-prettier-auto-rotation.html' title='iOS: Prettier auto-rotation'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-nBIx5eTBAyA/TYOA6lIO6hI/AAAAAAAACqg/6qMYHSq5MQw/s72-c/sign_mini%2Broundabout.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5182184204590262350</id><published>2011-03-16T03:33:00.000-07:00</published><updated>2011-03-16T03:37:03.818-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>[ios] iOS Development talk slides available</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-HYb8g6KeMYs/TYCSjp60ngI/AAAAAAAACqY/lkHFuyzQrrA/s1600/Screen%2Bshot%2B2011-03-16%2Bat%2B10.35.29.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://1.bp.blogspot.com/-HYb8g6KeMYs/TYCSjp60ngI/AAAAAAAACqY/lkHFuyzQrrA/s200/Screen%2Bshot%2B2011-03-16%2Bat%2B10.35.29.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5584624679185063426" /&gt;&lt;/a&gt;The slides from my popular iOS development talk, last given at &lt;a href="http://goodliffe.blogspot.com/2011/01/speaking-bcs-edinburgh-ios-development.html"&gt;BCS Edinburgh&lt;/a&gt; are available for you to view on Slideshare.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To view them, follow &lt;a href="http://www.slideshare.net/petegoodliffe/ios-development-bcs-edinburgh-20110309"&gt;this link&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5182184204590262350?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5182184204590262350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5182184204590262350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5182184204590262350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5182184204590262350'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/03/ios-ios-development-talk-slides.html' title='[ios] iOS Development talk slides available'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-HYb8g6KeMYs/TYCSjp60ngI/AAAAAAAACqY/lkHFuyzQrrA/s72-c/Screen%2Bshot%2B2011-03-16%2Bat%2B10.35.29.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5121372386899103166</id><published>2011-03-11T02:15:00.000-08:00</published><updated>2011-03-11T02:19:26.287-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Many-festos</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-97uMLrHP1Lo/TXn2zmcZPdI/AAAAAAAACqQ/r_CVu5ugkE0/s1600/cvu-cover-small.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 142px; height: 200px;" src="http://3.bp.blogspot.com/-97uMLrHP1Lo/TXn2zmcZPdI/AAAAAAAACqQ/r_CVu5ugkE0/s200/cvu-cover-small.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5582764579455843794" /&gt;&lt;/a&gt;The March issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;i&gt;C Vu&lt;/i&gt; will be hitting doormats any moment now. It contains the latest installment in my &lt;i&gt;Becoming a Better Programmer&lt;/i&gt; column. This one's called &lt;b&gt;Many-festos&lt;/b&gt;, and is a slightly irked rant on the proliferation of software development "manifestos" that have sprung up recently, and some of the arguments that have arisen around them.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The PDF version of the magazine will be available for download by ACCU members shortly.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5121372386899103166?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5121372386899103166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5121372386899103166' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5121372386899103166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5121372386899103166'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/03/writing-many-festos.html' title='Writing: Many-festos'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-97uMLrHP1Lo/TXn2zmcZPdI/AAAAAAAACqQ/r_CVu5ugkE0/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-273593958996742873</id><published>2011-02-11T08:40:00.000-08:00</published><updated>2011-02-11T08:59:53.873-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>[ios] Dynamic cast in Objective-C</title><content type='html'>In C++, you can &lt;a href="http://www.cplusplus.com/doc/tutorial/typecasting/"&gt;cast&lt;/a&gt; a pointer between two &lt;i&gt;(related)&lt;/i&gt; types, and ask the runtime to check if the conversion is valid using &lt;a href="http://cppreference.com/wiki/keywords/dynamic_cast"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;dynamic_cast&lt;/span&gt;&lt;/a&gt;. Usually in C++ the use of dynamic_cast is a sign that you're doing something wrong - good C++ design generally avoids such constructs.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, Objective-C is a far more dynamic language, and often you do need to &lt;i&gt;do&lt;/i&gt; something similar. The runtime provides all the smarts for this, but doesn't deliver it in a simple one-liner.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So let's fix that...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wondering if a view controller's &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;view&lt;/span&gt; property is a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;UISwitch&lt;/span&gt;? Try this:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;UISwitch *switch&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;    = &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;objc_dynamic_cast&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;(UISwitch,viewController.view);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;if (switch) NSLog(@"It jolly well is!);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;That's nice, isn't it? Here's how:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;#define objc_dynamic_cast(TYPE, object) \&lt;br /&gt;  ({ \&lt;br /&gt;      TYPE *dyn_cast_object = (TYPE*)(object); \&lt;br /&gt;      [dyn_cast_object isKindOfClass:[TYPE class]] ? dyn_cast_object : nil; \&lt;br /&gt;  })&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For the curious, here's what's going on...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, we define a preprocessor macro using a gcc extension: the macro &lt;i&gt;&lt;a href="http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs"&gt;compound statement&lt;/a&gt;&lt;/i&gt;. That's the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;({ ... })&lt;/span&gt; block. This is a little dirty, and I certainly wouldn't use a gcc-specific extension in my "portable" C++ code. However, Objective-C lives in a different ecosystem, where you can guarantee that compound statements will be supported. So we'll go with it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The reason I use a compound statement is to define a "local" variable - &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;dyn_cast_object&lt;/span&gt;. This is just to cover the macro's back - it needs to mention the name of the object argument twice, and if that expression has side effects you'd get twice the number of side effects otherwise. &lt;i&gt;Side-side effects. &lt;/i&gt; So I store the argument in a local variable to avoid this. (Most of the time this is unlikely to be an issue, but if you ever got bit by this problem, you'll appreciate having done it right the first time).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Then we simply ask the object is it is of the class of our cast's destination type, using &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;NSObject&lt;/span&gt;'s &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;isKindOfClass:&lt;/span&gt; selector.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not too complex. And you could do the isKindOfClass: dance wherever you need to cast. But it's nice to write the macro once and then write clear code that reveals it's intent.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-273593958996742873?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/273593958996742873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=273593958996742873' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/273593958996742873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/273593958996742873'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/02/ios-dynamic-cast-in-objective-c.html' title='[ios] Dynamic cast in Objective-C'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4864887782540122561</id><published>2011-02-11T01:14:00.000-08:00</published><updated>2011-02-11T01:36:43.077-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>[ios] Cancelling a UIGestureRecognizer</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3114/3211737908_779d283eef.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://farm4.static.flickr.com/3114/3211737908_779d283eef.jpg" border="0" alt="" /&gt;&lt;/a&gt;You have a &lt;a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html%23//apple_ref/doc/c_ref/UIView"&gt;view&lt;/a&gt; with a handful of &lt;a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html"&gt;gesture recognizers&lt;/a&gt;. Perhaps some of them are chained together with &lt;a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html#//apple_ref/occ/instm/UIGestureRecognizer/requireGestureRecognizerToFail:"&gt;requireGestureRecognizerToFail&lt;/a&gt; so that they interact well.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes, you still need to respond to other user interaction, and cause any pending gesture to &lt;i&gt;immediately fail&lt;/i&gt;. There isn't an API for that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I had this issue when my application's "timeline" view, which was using pinch, tap, and pan gestures in concert, needed to grow temporary &lt;a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html"&gt;UIButton&lt;/a&gt; subviews. The buttons worked fine, but pressing them also triggered the gesture recognizers - very confusing for the user.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the solution.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;How to forcibly cancel a UIGestureRecnogizer&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Add a new category (I call it "&lt;i&gt;Cancel&lt;/i&gt;") to the UIGestureRecognizer class extending it with a new &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;cancel&lt;/span&gt; method:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@interface UIGestureRecognizer (&lt;b&gt;Cancel&lt;/b&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;- (void)cancel;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;And implement the new method like this:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@implementation UIGestureRecognizer (Cancel)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;- (void)cancel&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    self.enabled = NO;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    self.enabled = YES;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;The simple trick of switching off and back on  a gesture will force it to cancel.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then for bonus points, I add a category on UIView to make it easy to cancel all the gestures attached to it. I tend not to hold the gestures as member variables in my view controller because there isn't any need to do so - they are retained by the view you attach them to.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;//-----------------------------------------&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;// In .h file:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@interface UIView (&lt;b&gt;CancelAllGestures&lt;/b&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;- (void) cancelAllGestureRecognizers;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;//-----------------------------------------&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;// In .m file:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@implementation UIView (CancelAllGestures)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;- (void) cancelAllGestureRecognizers&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    for (UIGestureRecognizer *gesture in self.gestureRecognizers)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        [gesture cancel];&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;@end&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;This new method could then be easily used in my main view controller, by attaching it to the my UIButton objects as a new action:&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;[button addTarget:myViewWithGestures&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;           action:@selector(&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;cancelAllGestureRecognizers&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; forControlEvents:UIControlEventTouchDown];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Categories are a useful Objective C feature that really do help to make your code more clear and readable. Here they provide the means for another simple solution. I hope you find it useful.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4864887782540122561?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4864887782540122561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4864887782540122561' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4864887782540122561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4864887782540122561'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/02/ios-cancelling-uigesturerecognizer.html' title='[ios] Cancelling a UIGestureRecognizer'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3114/3211737908_779d283eef_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3178406799695909767</id><published>2011-02-04T06:33:00.000-08:00</published><updated>2011-02-04T06:36:06.691-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>So you need some software?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TUwOr6DA8_I/AAAAAAAACpw/zp17A96X1U8/s1600/Flowchart.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 311px; height: 400px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TUwOr6DA8_I/AAAAAAAACpw/zp17A96X1U8/s400/Flowchart.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5569842986629526514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;This is your handy cut-out-and-keep guide to software development.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Click on the image for high-res version.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3178406799695909767?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3178406799695909767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3178406799695909767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3178406799695909767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3178406799695909767'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/02/so-you-need-some-software.html' title='So you need some software?'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0KMnzNqRq8Y/TUwOr6DA8_I/AAAAAAAACpw/zp17A96X1U8/s72-c/Flowchart.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6305963842015025829</id><published>2011-02-04T04:44:00.001-08:00</published><updated>2011-11-24T02:05:09.545-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>PGMidi updated</title><content type='html'>&lt;a href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s1600/general-midi-logo.jpg"&gt;&lt;img alt="" border="0" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s1600/general-midi-logo.jpg" style="cursor: hand; cursor: pointer; float: right; height: 165px; margin: 0 0 10px 10px; width: 300px;" /&gt;&lt;/a&gt;Attention &lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;PGMidi&lt;/a&gt; users! I've updated my &lt;i&gt;MIDI Monitor&lt;/i&gt; example project again, this time making PGMidi less of an example, and a lot more useful for general use.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check it out on the&lt;a href="https://github.com/petegoodliffe/PGMidi"&gt; GitHub project page&lt;/a&gt;&amp;nbsp;(historical note: it was hosted on this&amp;nbsp;&lt;a href="http://gitorious.org/midimonitor/midimonitor"&gt;gitorious project&lt;/a&gt; page, but that is now deprecated in favour of GitHub).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What's changed:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The PGMidi class now allows you to determine what MIDI sources and MIDI connections are currently available.&lt;/li&gt;&lt;li&gt;It allows you to determine whether the source/destination is a networked session, or a physically attached device.&lt;/li&gt;&lt;li&gt;The "events" PGMidi sends through the delegate interface are far more explicit.&lt;/li&gt;&lt;li&gt;I've added some useful tools to find a matching source/destination pair if you want to speak to one specific MIDI device.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;The MIDIMonitor example application continues to show how to use the PGMidi API.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thanks for all the comments and feedback I've received about this code. I hope you find these updates useful.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6305963842015025829?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6305963842015025829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6305963842015025829' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6305963842015025829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6305963842015025829'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/02/pgmidi-updated.html' title='PGMidi updated'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s72-c/general-midi-logo.jpg' height='72' width='72'/><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2978454632588518082</id><published>2011-01-28T02:27:00.000-08:00</published><updated>2011-01-28T02:34:33.958-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Speaking: BCS Edinburgh (iOS development)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.bcs.org/custom/bcs/img/bcsLogoTop.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 375px; height: 88px;" src="http://www.bcs.org/custom/bcs/img/bcsLogoTop.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;I will be speaking at the &lt;a href="http://www.edinburgh.bcs.org/"&gt;Edinburgh branch&lt;/a&gt; of the BCS on the subject of iPhone development on March the 9th.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The details of the session, times, and location &lt;a href="http://www.edinburgh.bcs.org/events/2010-11/110309.htm"&gt;are available here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the synopsis:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  border-collapse: collapse; font-family:arial, sans-serif;font-size:13px;"&gt;&lt;div&gt;&lt;div&gt;&lt;span style="color:#797979;"&gt;&lt;b&gt;&lt;span style="font-size:130%;"&gt;&lt;span style=" ;font-size:14px;"&gt;Developing applications for iPhone, iPad (and other iOS devices)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: rgb(121, 121, 121); "&gt;&lt;i&gt;"An introduction to iPhone development for beginners or those who are casually interested and want a leg up the learning curve"&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#797979;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#797979;"&gt;The iPhone, iPad and their iOS relatives are becoming an increasingly popular and important platform. More and more developers are looking into what the platform can offer and how to harness its power for their products.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#797979;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#797979;"&gt;In this presentation, an experienced iOS developer provides a boot-strap in iPhone development. The talk is an overview of how to get started as an iPhone developer. You will gain an understanding of the platform, the tools, and the core technologies, including:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    The main languages: Objective C/C++&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    Using the Xcode IDE, and various deployment/testing tools &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    Common iPhone/Mac OS design patterns, idioms, and practices&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    Becoming a native: how to "think in iPhone"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    An overview of the libraries and facilities that exist&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;    Limitations of the development environment.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(121, 121, 121); "&gt;We'll see the pros and cons of iPhone development. You will leave with an understanding of how to deploy your applications on the device, and whether it is the right platform for you to target.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2978454632588518082?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2978454632588518082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2978454632588518082' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2978454632588518082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2978454632588518082'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/speaking-bcs-edinburgh-ios-development.html' title='Speaking: BCS Edinburgh (iOS development)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-9060997426582711508</id><published>2011-01-27T03:02:00.000-08:00</published><updated>2011-01-27T03:29:23.604-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iOS: performSelectorOnMainThread: with two arguments</title><content type='html'>iOS's &lt;a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html"&gt;NSObject&lt;/a&gt; class provides a mechanism to run any selector on a different thread. The most often used variant runs the selector on the "main" (i.e. UI) thread, the snappily titled: &lt;a href="http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html%23//apple_ref/occ/instm/NSObject/performSelectorOnMainThread:withObject:waitUntilDone:"&gt;performSelectorOnMainThread:withObject:waitUntilDone:&lt;/a&gt;. However, the limitation with this call is that you can only supply one argument.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes, one is not enough. There is a two argument non-thread version, &lt;a href="http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html%23//apple_ref/occ/intfm/NSObject/performSelector:withObject:withObject:"&gt;here&lt;/a&gt;. So why not invent our own two-argument threaded version?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can add this easily enough to the base &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;NSObject&lt;/span&gt; class by opening a new category on it just for the purpose.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's how...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1. Define our API&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We open a category on NSObject (note the category name in brackets)&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;@interface NSObject (PGPerformSelectorOnMainThreadWithTwoObjects)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;- (void) performSelectorOnMainThread:(SEL)selector withObject:(id)arg1 withObject:(id)arg2 waitUntilDone:(BOOL)wait;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;@end&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Naturally, it follows the existing performSelector API signatures, but just adds our extra &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;withObject:&lt;/span&gt; argument.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2. Implement it&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the secret sauce. Careful application of &lt;a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSMethodSignature_Class/Reference/Reference.html"&gt;NSMethodSignature&lt;/a&gt;, and &lt;a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html"&gt;NSInvocation&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&lt;pre&gt;@implementation NSObject (PGPerformSelectorOnMainThreadWithTwoObjects)&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;- (void) performSelectorOnMainThread:(SEL)selector withObject:(id)arg1 withObject:(id)arg2 waitUntilDone:(BOOL)wait&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span"  style=" ;font-family:'courier new';"&gt; &lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt; NSMethodSignature *sig = [self methodSignatureForSelector:selector];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    if (!sig) return;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo setTarget:self];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo setSelector:selector];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo setArgument:&amp;amp;arg1 atIndex:2];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo setArgument:&amp;amp;arg2 atIndex:3];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo retainArguments];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;    [invo performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-size:x-small;"&gt;@end&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now you have your own simple way to invoke a call to selector on the main thread from wherever you are in your code. Handy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-9060997426582711508?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/9060997426582711508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=9060997426582711508' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/9060997426582711508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/9060997426582711508'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/ios-performselectoronmainthread-with.html' title='iOS: performSelectorOnMainThread: with two arguments'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6114582894912973088</id><published>2011-01-26T06:56:00.000-08:00</published><updated>2011-01-26T07:00:18.231-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><title type='text'>Speaking: ACCU 2011</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://accu.org/content/images/conferences/2011/accu2011web.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 300px; height: 90px;" src="http://accu.org/content/images/conferences/2011/accu2011web.png" border="0" alt="" /&gt;&lt;/a&gt;I will be speaking at the &lt;a href="http://accu.org/index.php/conferences"&gt;ACCU 2011 developer conference&lt;/a&gt; in Oxford, UK in April.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This year, my ACCU presentation is called &lt;a href="http://accu.org/index.php/conferences/accu_conference_2011/accu2011_sessions#Becoming%20a%20Better%20Programmer"&gt;Becoming a Better Programmer&lt;/a&gt; (yes, following the title of my magazine column - but it's not the same content, honest!).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the talk synopsis:&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;i&gt;You're a programmer. You spend your life programming. (You dull person, you!)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Don't you want to do it as well as you possibly can?&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;This entertaining talk will provide a number of practical, simple methods to become a better programmer. There will be plenty of hand-waving and jumping, a little philosophy, and much wisdom from our excellent programmer forebears.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Be the best programmer you can!&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6114582894912973088?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6114582894912973088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6114582894912973088' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6114582894912973088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6114582894912973088'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/speaking-accu-2011.html' title='Speaking: ACCU 2011'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8691518083397757578</id><published>2011-01-26T06:04:00.000-08:00</published><updated>2011-01-27T15:16:55.878-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>Reflections: The year that was</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TUAtZNlFGbI/AAAAAAAACpc/sfYALJncJ_Y/s1600/clipboard_list_with_pencil.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 200px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TUAtZNlFGbI/AAAAAAAACpc/sfYALJncJ_Y/s200/clipboard_list_with_pencil.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5566499050595097010" /&gt;&lt;/a&gt;&lt;div&gt;I'm a bit late to the table with this one given that we're almost a full month into 2011, but it's always good to take stock of what you've achieved in a year. And: &lt;i&gt;better late than never&lt;/i&gt;, eh?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was prompted to perform this exercise by a few other people's similar posts; perhaps you'd like to do the same thing?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll admit that I actually began writing this list at the end of last year, but have only just got around to finishing off my notes. Enough with the procrastination. I seem to suffer from a bad case of &lt;i&gt;everything-is-more-important-than-everything-else-itis&lt;/i&gt; recently.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Amongst other things, in 2010:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;I continued writing my &lt;b&gt;regular software development column&lt;/b&gt; for &lt;a href="http://www.accu.org/"&gt;ACCU's&lt;/a&gt; CVu magazine. This year I renamed the column, from the slightly stuffy and ambiguous "&lt;i&gt;Professionalism in Programming&lt;/i&gt;" to the more lucid "&lt;i&gt;Becoming a Better Programmer&lt;/i&gt;".&lt;/li&gt;&lt;li&gt;&lt;b&gt;Speaking&lt;/b&gt; at developer of conferences. I gave &lt;a href="http://accu.org/index.php/conferences/accu_conference_2010/accu2010_speakers#Pete%20Goodliffe"&gt;two talks&lt;/a&gt; at ACCU 2010 in Oxford, and one in the &lt;a href="http://qconlondon.com/london-2010/presentation/The+Craftsman+Learns+%28or+Learning+the+Craft%29"&gt;Software Craftsmanship&lt;/a&gt; track of QCon London 2010. I also gave a presentation on iPhone development for &lt;a href="http://softwareast.ning.com/"&gt;Software Eas&lt;/a&gt;t in Cambridge. It was refreshing to attend other techie conferences as a "mere" attendee.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Book contributions&lt;/b&gt;. I contributed three entries to O'Reily's &lt;a href="http://oreilly.com/catalog/9780596809492"&gt;97 Things Every Programmer Should Know&lt;/a&gt; book, edited by Kevlin Henney.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Kept on developing...&lt;/b&gt; Produced a number of iOS apps for my company (DJ apps, Synths, and a hardware MIDI SDK). And worked on Mac apps, getting them available in the Mac App Store when it launched.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Kept on developing more... &lt;/b&gt;It's been gratifying that a lot of my publicly available code components have been very popular in 2010. Especially the iOS &lt;a href="http://goodliffe.blogspot.com/2011/01/more-ios-midi-using-networked-midi.html"&gt;MIDI I/O library&lt;/a&gt; I wrote which has found its way into &lt;i&gt;many&lt;/i&gt; iOS apps, and my work getting the &lt;a href="http://goodliffe.blogspot.com/2010/09/building-boost-framework-for-ios-iphone.html"&gt;Boost libraries easily available on iOS&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Continued &lt;b&gt;graphic design and layout&lt;/b&gt; work, overseeing the layout and design of CVu and Overload &lt;a href="http://accu.org/index.php/aboutus/aboutjournals"&gt;magazines&lt;/a&gt;, as well as producing the covers for both publications.&lt;/li&gt;&lt;li&gt;Performed a number of techie &lt;b&gt;book reviews&lt;/b&gt;. Mostly this year, I have been reviewing iPhone/iOS development &lt;a href="http://goodliffe.blogspot.com/search/label/books"&gt;books&lt;/a&gt; for &lt;a href="http://accu.org/index.php"&gt;ACCU&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Learnt &lt;b&gt;new technologies&lt;/b&gt;: this year was definitely the year of &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;, which I now use for everything, including accessing &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; repositories.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Preached&lt;/b&gt; on a Sunday morning at &lt;a href="http://www.oldwindsorchurch.org.uk/"&gt;Old Windsor Parish Church&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Spoke at the wedding&lt;/b&gt; of two great friends, Steve and Frances.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Playing keyboards&lt;/b&gt; at three conferences in Cambridge (as well as regular stints in the Sunday morning band at &lt;a href="http://cthree.org/"&gt;C3&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Leading a &lt;b&gt;&lt;a href="http://cthree.org/Groups/92329/Cambridge_Community_Church/New_To_C3/Small_Groups/Small_Groups.aspx"&gt;smallgroup&lt;/a&gt;&lt;/b&gt; at C3.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Moved house&lt;/b&gt; (I now have a studio, wooo!)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Phew! That list's not exhaustive (I wonder what I've forgotten about), but its enough for now. It's been a busy year. And not a dull one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;2010 albums of the year:&lt;/b&gt; Bonobo's &lt;a href="http://www.we7.com/#/album/Bonobo/Black-Sands"&gt;Black Sands&lt;/a&gt;, Brandon Flower's &lt;a href="http://www.we7.com/#/album/Brandon-Flowers/Flamingo"&gt;Flamingo&lt;/a&gt;, Foal's&lt;a href="http://www.we7.com/#/album/Foals/Total-Life-Forever"&gt; Total Life Forever&lt;/a&gt;, Seasick Steve's &lt;a href="http://www.we7.com/#/album/Seasick-Steve/Songs-For-Elisabeth"&gt;Songs for Elisabeth&lt;/a&gt;, Vampire Weekend's &lt;a href="http://www.we7.com/#/album/Vampire-Weekend/Contra"&gt;Contra&lt;/a&gt;, 65daysofstatic's &lt;a href="http://www.we7.com/#/album/65daysofstatic/We-Were-Exploding-Anyway"&gt;We Were Exploding Anyway&lt;/a&gt;, St. Lola In The Fields' &lt;a href="http://www.we7.com/#/album/St-Lola-In-The-Fields/High-Atop-The-Houses-And-The-Towns"&gt;High Atop The Houses And The Towns&lt;/a&gt;, Lou Rhode's &lt;a href="http://www.we7.com/#/album/Lou-Rhodes/One-Good-Thing"&gt;One Good Thing&lt;/a&gt;, Jonsi's &lt;a href="http://www.we7.com/#/album/Jonsi/Go"&gt;Go&lt;/a&gt;, Goldfrapp's &lt;a href="http://www.we7.com/#/album/Goldfrapp/Head-First"&gt;Head First&lt;/a&gt;, and &lt;a href="http://www.we7.com/#/album/Klaxons/Surfing-The-Void"&gt;Klaxon's Surfing the Void&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8691518083397757578?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8691518083397757578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8691518083397757578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8691518083397757578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8691518083397757578'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/reflections-year-that-was.html' title='Reflections: The year that was'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/TUAtZNlFGbI/AAAAAAAACpc/sfYALJncJ_Y/s72-c/clipboard_list_with_pencil.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6132929505266813398</id><published>2011-01-14T01:24:00.000-08:00</published><updated>2011-01-14T01:34:18.393-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: When It's Done, It's Done</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TTAYQRWkTqI/AAAAAAAACpU/inS4QSUK9es/s1600/cvu-cover-small.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 142px; height: 200px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TTAYQRWkTqI/AAAAAAAACpU/inS4QSUK9es/s200/cvu-cover-small.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5561972207617592994" /&gt;&lt;/a&gt;The January issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;i&gt;C Vu&lt;/i&gt; magazine is out now. It contains the latest installment in my &lt;i&gt;Becoming a Better Programmer&lt;/i&gt; column. This one's called &lt;b&gt;When It's Done, It's Done,&lt;/b&gt; and is a description of how to do the "right" amount of work; to work out when your current task will be complete, and when you should stop working on it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The magazine should have landed on ACCU members' doormats already. The PDF version is available for download on the &lt;a href="http://www.accu.org/"&gt;website&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the first issue of &lt;i&gt;C Vu&lt;/i&gt; for which I have produced the cover using &lt;a href="http://www.photoshop.com/"&gt;Photoshop&lt;/a&gt; (previous issues were drawn in &lt;a href="http://www.gimp.org/"&gt;The Gimp&lt;/a&gt;). Most people probably won't notice, although I took the opportunity to make a few small visual tweaks. Ironically, Paul (the guest editor) asked me for a cover that was a bit "Java-y", and then there were no actual articles about Java. Ah well...&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6132929505266813398?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6132929505266813398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6132929505266813398' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6132929505266813398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6132929505266813398'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/writing-when-its-done-its-done.html' title='Writing: When It&apos;s Done, It&apos;s Done'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/TTAYQRWkTqI/AAAAAAAACpU/inS4QSUK9es/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6412401996503805807</id><published>2011-01-05T01:38:00.000-08:00</published><updated>2011-11-24T02:06:13.296-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>More iOS MIDI (using networked MIDI connections)</title><content type='html'>&lt;a href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s1600/general-midi-logo.jpg"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5558344901679307506" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s200/general-midi-logo.jpg" style="cursor: pointer; float: right; height: 110px; margin-bottom: 10px; margin-left: 10px; margin-right: 0px; margin-top: 0px; width: 200px;" /&gt;&lt;/a&gt;My &lt;a href="http://goodliffe.blogspot.com/2010/11/sending-midi-through-coremidi.html"&gt;iOS MIDI I/O example code&lt;/a&gt; has been incredibly popular. It's great to know that many music apps out there have incorporated my code to get their MIDI interfacing working.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thanks for all the kind feedback.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have been updating the MIDI code with a few structural tidy-ups, and an often requested feature - the ability to use networked MIDI sessions (connections).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Doing it manually: Using networked MIDI connections&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;iOS provides some a neat networked MIDI connection facility. However, despite being easy to set up, network MIDI sessions aren't initially obvious.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, you must include:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;#import &amp;lt;CoreMIDI/MIDINetworkSession.h&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Because network sessions are not included in the umbrella CoreMIDI.h include file. Sigh.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next you must establish a network session by winking the (evil) singleton instance into existence:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;MIDINetworkSession* session = [MIDINetworkSession defaultSession];&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Then, merely turn it on:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;session.enabled          = YES;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;session.connectionPolicy = MIDINetworkConnectionPolicy_Anyone;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;Yes, that is all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Documentation for &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;MIDINetworkSession&lt;/span&gt; is available &lt;a href="http://developer.apple.com/library/ios/#documentation/CoreMidi/Reference/MIDINetworkSession_ClassReference/Reference/Reference.html"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The easy way: using PGMidi&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're using my MIDI classes, then you can just call the &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;PGMidi&lt;/span&gt; class' &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;enableNetwork: &lt;/span&gt;method with &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;YES&lt;/span&gt; or &lt;span class="Apple-style-span" style="font-family: 'courier new';"&gt;NO&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Get the code&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The latest version of my MIDI interface code, and a sample project that shows it in action is available from the &lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;GitHub project page&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Feedback, as ever, is welcomed.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6412401996503805807?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6412401996503805807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6412401996503805807' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6412401996503805807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6412401996503805807'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2011/01/more-ios-midi-using-networked-midi.html' title='More iOS MIDI (using networked MIDI connections)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TSM1PRuy2vI/AAAAAAAACpM/Y3fCbUM_UcI/s72-c/general-midi-logo.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7036814474524972164</id><published>2010-12-08T06:34:00.001-08:00</published><updated>2010-12-08T06:52:28.854-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Uploading Mac App Store apps whose names contain a space</title><content type='html'>As the launch of the Mac App Store grows ever nearer (mere days if interweb rumours are to be believed) developers are hastily uploading theirMac  apps to be there at launch time.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For the most part, Apple have streamlined the upload procedure and integrated it into the Xcode IDE well (although, you MUST remember to download and install an Xcode plugin from the developer site, or the facility is mysteriously absent).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TP-YCw16LoI/AAAAAAAACpA/kZjkeOcHIgc/s1600/Screen%2Bshot%2B2010-12-08%2Bat%2B11.38.07.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 197px; height: 200px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TP-YCw16LoI/AAAAAAAACpA/kZjkeOcHIgc/s200/Screen%2Bshot%2B2010-12-08%2Bat%2B11.38.07.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5548320439181913730" /&gt;&lt;/a&gt;&lt;div&gt;However the upload-to-iTunes-Connect procedure doesn't always work. In particular, it fails spectacularly (see the image) &lt;b&gt;if your application name includes spaces&lt;/b&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Clearly, application names including spaces are Not The Right Way To Do Things. No one would want to do something like that. (No, we don't use applications like "Address Book" "DVD Player" "Front Row" or "Photo Booth". They'll never catch on.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The worst part of the problem is that Xcode's upload error is completely cryptic. Rather than:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;i&gt;You tried to upload a binary whose bundle name contains a space.&lt;/i&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;you get something like:&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;i&gt;Apple's web service operation was not successful.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Unable to authenticate the package: 4084782348.itmsp&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;ERROR ITMS-4000: "Line 6 column 62: bad character content for element at XPath /package/software_assets/assets/data_file/file_name"&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Catchy, eh? User friendly, eh?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's particularly galling as the "Validate..." step in the Xcode organiser window will not check for this problem, and tells you that your application is valid for upload. Sigh.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After discovering that there are problems with bundle names containing spaces, there are obvious things you could try:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Rename the application without spaces. &lt;b&gt;FAIL&lt;/b&gt;: No one wants to use an application called AddressBook.&lt;/li&gt;&lt;li&gt;Fiddle the &lt;i&gt;NSBundleName&lt;/i&gt; Info.plist entry so that it doesn't have a space in it, but leave the the "Application Name.app" filename as it was. &lt;b&gt;FAIL 1&lt;/b&gt;: I don't &lt;i&gt;think&lt;/i&gt; that this is a valid bundle any more. &lt;b&gt;FAIL 2&lt;/b&gt;: It doesn't work. You still get the upload error.&lt;/li&gt;&lt;li&gt;Scream, cry, whinge. &lt;b&gt;FAIL&lt;/b&gt;: Whilst it doesn't actually make any technical difference, this will make you feel better for a short while.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;There is a solution, though. And it turns out to be quite simple.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Rather than following the &lt;a href="http://developer.apple.com/devcenter/mac/documents/submitting.html"&gt;Apple instructions for uploading your app&lt;/a&gt; to iTunes Connect, perform the "Build and Archive" step. "Validate..." your application for luck. Then click on "Share..." and chose to save an image to your hard disk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now use Application Loader to upload the &lt;i&gt;pkg&lt;/i&gt; image created to iTunes Connect.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It just works.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7036814474524972164?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7036814474524972164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7036814474524972164' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7036814474524972164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7036814474524972164'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/12/uploading-mac-app-store-apps-whose.html' title='Uploading Mac App Store apps whose names contain a space'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/TP-YCw16LoI/AAAAAAAACpA/kZjkeOcHIgc/s72-c/Screen%2Bshot%2B2010-12-08%2Bat%2B11.38.07.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4167625835411982382</id><published>2010-11-18T02:28:00.000-08:00</published><updated>2010-11-18T03:01:01.607-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Make some noise! (Audio on iOS)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TOUAEC_DrtI/AAAAAAAACo4/tcH31RgzsLE/s1600/au.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px; height: 150px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TOUAEC_DrtI/AAAAAAAACo4/tcH31RgzsLE/s200/au.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5540834986070093522" /&gt;&lt;/a&gt;There are two main APIs on iOS for playing programatically-generated audio:&lt;div&gt;&lt;ul&gt;&lt;li&gt;Audio Units [&lt;a href="http://developer.apple.com/library/ios/#documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/Introduction/Introduction.html"&gt;see here&lt;/a&gt;]&lt;/li&gt;&lt;li&gt;Audio Queues [&lt;a href="http://developer.apple.com/library/ios/#documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Introduction/Introduction.html"&gt;see here&lt;/a&gt;]&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;i&gt;Audio units&lt;/i&gt; are a lower-level, lower-latency technology. And also, a relatively complex API. A&lt;i&gt;udio queues&lt;/i&gt; are higher-level and simpler to use, but have far greater latency.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have produced a sample project showing the simplest creation of an audio unit and audio queue output so you can compare and contrast the two APIs. Get it on &lt;a href="http://gitorious.org/iosaudioexample"&gt;Gitorious here&lt;/a&gt;. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The following series of blog entries will describe each technology.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;About the project&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The project builds a sample iOS application that plays a steady sine wave as long as it is running. If you look at &lt;a href="http://gitorious.org/iosaudioexample/iosaudioexample/blobs/master/Source/main.mm"&gt;main.mm&lt;/a&gt; you'll see a single &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;#define&lt;/span&gt; for &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;USE_AUDIO_QUEUE_OUTPUT&lt;/span&gt; that can be used to switch between the audio unit and audio queue back ends.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are extra things a well-behaved iOS audio app should do that are not (yet) illustrated by this example project. Notably, your app should use the &lt;a href="http://developer.apple.com/library/ios/#documentation/Audio/Conceptual/AudioSessionProgrammingGuide/"&gt;Audio Sessions API&lt;/a&gt; to define what kind of audio session it requires and to handle interruptions to the audio output (e.g. when a phone call it received whilst your app is running).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Make some noise!&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before we work out how to make noise with our iOS devices, we need some audio to start with. For this reason, the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;AudioProducer&lt;/span&gt; protocol defines a simple interface that the audio backends can grab an audio stream from.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It looks like this:&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;/// Type of audio sample produced by an AudioProducer&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;typedef SInt16 Sample;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;/// Protocol for objects that produce audio&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;@protocol AudioProducer&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;@property (nonatomic) float sampleRate;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;/// Fills a buffer with "size" samples.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;/// The buffer should be filled in with interleaved stereo samples.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;- (void) produceSamples:(Sample *)audioBuffer size:(size_t)size;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;@end&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; color: #f5e800"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;That is, we'll be peddling signed 16-bit integer samples, and have a single method that can be called to grab the next block of interleaved stereo audio samples.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Given that, I have written a simple &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SineWave&lt;/span&gt; audio generator. It's not the most elegant generator, I'll admit. It uses a resonant filter to approximate a sine wave rather than the maths library trig functions for performance reasons.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;SineWave&lt;/span&gt; interface adopts the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;AudioProducer&lt;/span&gt; protocol, and adds two extra properties - the &lt;i&gt;frequency&lt;/i&gt; of the sine wave and the &lt;i&gt;peak&lt;/i&gt; (amplitude) of the wave. You can see the interface &lt;a href="http://gitorious.org/iosaudioexample/iosaudioexample/blobs/master/Source/Audio/AudioProducer.h"&gt;here&lt;/a&gt; and the implementation &lt;a href="http://gitorious.org/iosaudioexample/iosaudioexample/blobs/master/Source/Audio/AudioProducer.mm"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Atomicity&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Note that since this is a simplistic example I have made all of these properties nonatomic. However, both audio units and audio queues will pull audio from your application in a background thread (not the main user interface thread).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The audio unit uses a very high priority background thread, as it is a very low latency audio pipeline with little buffering. The audio queue thread is not set as high-priority, as it employs a large amount of buffering.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You must bear these threads in mind when writing an audio generator. Ensure that any parameter that can be changed is thread-safe. Make sure that if the UI is in the process of adjusting values and gets interrupted by the audio thread that no disasters (e.g. nasty audio glitches) can result.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What this looks like in practice is different for each application. But this is an important warning to heed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Next time&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now we have some audio to play, next time we'll look at how to use the audio queue APIs to play it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4167625835411982382?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4167625835411982382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4167625835411982382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4167625835411982382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4167625835411982382'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/11/make-some-noise-audio-on-ios.html' title='Make some noise! (Audio on iOS)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/TOUAEC_DrtI/AAAAAAAACo4/tcH31RgzsLE/s72-c/au.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5048013553455928432</id><published>2010-11-12T01:55:00.001-08:00</published><updated>2010-11-12T02:01:43.319-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: This Time I've Got It...</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://accu.org/content/images/journals/CVu225Cover.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 354px;" src="http://accu.org/content/images/journals/CVu225Cover.png" border="0" alt="" /&gt;&lt;/a&gt;The November issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s C Vu magazine is out now. It contains the latest installment in my &lt;i&gt;Becoming a Better Programmer&lt;/i&gt; column. This one's called &lt;b&gt;This Time I've Got It...&lt;/b&gt; and is a software development parable. As the article strap-line puts it: &lt;i&gt;Pete Goodliffe tells us a story of stress, short-sightedness, and solutions&lt;/i&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The magazine should have landed on ACCU members' doormats already. The PDF version is available for download on the &lt;a href="http://accu.org/"&gt;website&lt;/a&gt;. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5048013553455928432?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5048013553455928432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5048013553455928432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5048013553455928432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5048013553455928432'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/11/writing-this-time-ive-got-it.html' title='Writing: This Time I&apos;ve Got It...'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8208384197427190275</id><published>2010-11-02T05:04:00.000-07:00</published><updated>2011-11-24T02:06:42.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Sending MIDI through CoreMIDI</title><content type='html'>&lt;a href="http://www.synthtopia.com/content/wp-content/uploads/2007/07/usb-midi-cable.jpg"&gt;&lt;img alt="" border="0" src="http://www.synthtopia.com/content/wp-content/uploads/2007/07/usb-midi-cable.jpg" style="cursor: hand; cursor: pointer; float: right; height: 201px; margin: 0 0 10px 10px; width: 275px;" /&gt;&lt;/a&gt;The 4.2 iOS GM seed is out. CoreMIDI is coming to the masses. So I've updated my CoreMIDI example to show how to send MIDI out through the USB port. (I've had a lot of people ask me for this.)&lt;br /&gt;&lt;br /&gt;Go to the &lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;GitHub project page&lt;/a&gt; and check out the update. It's a simple addition, but shows the simplest way of getting MIDI data out of your application and through CoreMIDI.&lt;br /&gt;&lt;br /&gt;Interestingly, the later - &lt;i&gt;and the GM&lt;/i&gt; - versions of iOS 4.2 are far less forgiving of attached USB control devices. Most of the devices I test with are rejected by the iPad because they draw too much power. These are devices with LEDs, but that are certainly within USB power specifications. That's quite a shame.&lt;br /&gt;&lt;br /&gt;As ever, I welcome feedback about this example project. Let me know if you find it useful.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8208384197427190275?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8208384197427190275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8208384197427190275' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8208384197427190275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8208384197427190275'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/11/sending-midi-through-coremidi.html' title='Sending MIDI through CoreMIDI'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4191865445055535008</id><published>2010-10-21T05:34:00.000-07:00</published><updated>2011-11-24T02:08:34.608-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='ios'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Using CoreMIDI in iOS (an example)</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TMA1h8FVjsI/AAAAAAAACow/o23MHOga1mU/s1600/your_app_here.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5530479199591435970" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TMA1h8FVjsI/AAAAAAAACow/o23MHOga1mU/s200/your_app_here.png" style="cursor: hand; cursor: pointer; float: right; height: 147px; margin: 0 0 10px 10px; width: 200px;" /&gt;&lt;/a&gt;In &lt;a href="https://developer.apple.com/ios/"&gt;iOS&lt;/a&gt; 4.2 the &lt;a href="http://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/CACoreMIDIRef/"&gt;CoreMIDI&lt;/a&gt; framework is dropping into the standard operating system. &lt;a href="http://www.midi.org/"&gt;MIDI&lt;/a&gt; connectivity using generic class-compliant USB MIDI hardware will be available to all.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's not a big framework, with a handful of pure-C APIs. But its affect will be profound. What was previously only possible using Akai's &lt;a href="http://www.synthstationapp.com/sdk.php"&gt;AkaiConnect SDK&lt;/a&gt; (which &lt;i&gt;is&lt;/i&gt; a very nice Objective-C API) or Line 6's MIDI Mobilizer SDK will be available to all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From what I can see, the iOS CoreMIDI version is going to be the exact same API as the Mac OS desktop variant. I expect developer take-up of this API to be far faster than for the existing two (non-standard) iOS MIDI interface APIs. Pretty soon every iPhone synth app will support Apple's generic MIDI API.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is, if they can work out how to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;CoreMIDI isn't the best documented API (&lt;a href="http://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/CACoreMIDIRef/MIDISetup/index.html"&gt;this&lt;/a&gt; is all you get: a list of typedefs and functions). Fortunately, the headers are well-commented and the API is mercifully simple and sensible. However, with no compelling examples (that I could find) it takes a little digging to work out how to use CoreMIDI.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So here I present a very simple example project, with a reusable Objective-C MIDI interface class. With this code, you can get up to speed with CoreMIDI quickly. Indeed, if you just paste my &lt;a href="http://gitorious.org/midimonitor/midimonitor/blobs/master/Sources/MIDI/MidiInput.h"&gt;MidiInput&lt;/a&gt; class into your synth app you'd be good to go.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Grab it from the &lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;GitHub project&lt;/a&gt; here.&lt;i&gt; (Update note: the repo master used to be hosted on&amp;nbsp;&lt;a href="http://gitorious.org/midimonitor/midimonitor"&gt;Gitorious here&lt;/a&gt;&amp;nbsp;but we've moved to GitHub in these enlightened times)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Please let me know if you find it useful, or if you use it in your own projects.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Integrating CoreMIDI in your application&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, you need to decide if you want your app to support devices running iOS versions before 4.2. Since CoreMIDI is only introduced in 4.2, you have to jump through a few hoops to keep your app running on earlier versions:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Weakly link to the CoreMIDI framework&lt;/b&gt;, so on OS versions without it your application will still launch. &lt;i&gt;(You do this by going to your application's target in the Xcode tree view, selecting "Get info", and in the "General" tab's "Linked libraries" section ensuring that CoreMIDI is set to "Weak" not "Required".)&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Including CoreMIDI functionality conditionally&lt;/b&gt;. The best way to do this is inspect the &lt;i&gt;kCFCoreFoundationVersionNumber&lt;/i&gt; variable and only initialise your MIDI handling if the value represents iOS 4.2 or later.&lt;i&gt; (See the iOS version detection header file in my example project for an elegant way to do this).&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A demonstration of all of this is available in my example project.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Using CoreMIDI&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;CoreMIDI itself isn't too complex if you're happy to read the headers and work out what's going on. You need a basic grasp of how Mac OS's Core Foundation works, to understand lifetime management issues and to access string properties, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;CoreMIDI has a few basic concepts: most importantly clients, devices (with endpoints) and ports. The C APIs let you enumerate these, and register a notification to keep abreast of changes in MIDI connection state.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;MIDI inputs are "sources" in CoreMIDI. MIDI outputs are "destinations".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Given those basic facts, you should be able to read through my MidiInput class and figure out what's going on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Parsing MIDI&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My example program just spits out a stream of binary MIDI data. I'm not showing any parsing of the MIDI data stream here. This parsing isn't rocket science, but is another step you have to perform.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Contact me if you want to know more about parsing MIDI.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="https://github.com/petegoodliffe/PGMidi"&gt;Get the code here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4191865445055535008?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4191865445055535008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4191865445055535008' title='41 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4191865445055535008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4191865445055535008'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/10/using-coremidi-in-ios-example.html' title='Using CoreMIDI in iOS (an example)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/TMA1h8FVjsI/AAAAAAAACow/o23MHOga1mU/s72-c/your_app_here.png' height='72' width='72'/><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7339412556428509008</id><published>2010-10-21T00:25:00.000-07:00</published><updated>2010-10-21T00:34:15.062-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Some Practical Ideas To Help You Learn</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s1600/bagpuss_professor_yaffle.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 180px; height: 155px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s1600/bagpuss_professor_yaffle.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;p&gt;A I wind down my &lt;a href="http://goodliffe.blogspot.com/search/label/learning"&gt;blog series&lt;/a&gt; on software developers learning, I present some practical ideas to help you improve your learning:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;Cultivate a healthy set of &lt;i&gt;attitudes&lt;/i&gt;: take responsibility for  your learning.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Learn one programming language per year. (This is excellent  advice in The Pragmatic Programmer that is still very valid today.)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;i&gt;Scratch an itch!&lt;/i&gt; (What are you curious about? Consider  something “leftfield”, not programming-related. Ensure that at all times you have  something you're learning about that isn't directly related to your  day job).&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Read at least one book every two months (Read more if you  want, but set some kind of benchmark to aim for).&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Look after your&lt;i&gt; learning machine&lt;/i&gt; – get good nutrition, and  plenty of rest. Avoid stress. Have fun!&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Build mental maps as you learn.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Try to use &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-understanding-brain.html"&gt;both sides&lt;/a&gt; of your brain.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Perform &lt;a href="http://goodliffe.blogspot.com/search/label/learning"&gt;deliberate practice&lt;/a&gt; &amp;amp; exercise as you learn.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Network: actively learn from others, and seek to teach/mentor  others.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Enjoy learning. This stuff is fun.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;Apply any new knowledge cautiously.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h1 lang="pl-PL" class="western"&gt;Conclusion&lt;/h1&gt; &lt;p&gt;You have to take responsibility for your own learning. It's not up to your employer, your state education system, an assigned mentor, or any other person.&lt;/p&gt; &lt;p&gt;&lt;i&gt;You&lt;/i&gt;&lt;span style="font-style: normal"&gt; are in charge of your own learning. It's important to continually improve your skills to improve as a developer. And to do that you have to &lt;/span&gt;&lt;i&gt;learn&lt;/i&gt;&lt;span style="font-style: normal"&gt; to learn. To make it rewarding you have to learn to &lt;/span&gt;&lt;i&gt;love&lt;/i&gt;&lt;span style="font-style: normal"&gt; doing it.&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;Learn to live to love to learn.&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;/p&gt; &lt;h2 class="western" style="font-style: normal"&gt;Questions to ponder&lt;/h2&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="font-style: normal"&gt;When were you last in a situation  that required learning?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How did you approach it?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How successful were you?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How quickly did you learn?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;How could you have performed  better?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Did you learn, then work, or learn  as you worked?&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal"&gt;Which do you think is most  effective?&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7339412556428509008?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7339412556428509008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7339412556428509008' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7339412556428509008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7339412556428509008'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/10/learning.html' title='Learning: Some Practical Ideas To Help You Learn'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s72-c/bagpuss_professor_yaffle.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5356840227129314597</id><published>2010-10-20T14:36:00.000-07:00</published><updated>2010-10-20T14:45:53.992-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simplicity'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Write Less Code!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TL9ht9GEWLI/AAAAAAAACoo/u1cz41p4nSg/s1600/no-entry.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 194px; height: 200px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TL9ht9GEWLI/AAAAAAAACoo/u1cz41p4nSg/s200/no-entry.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5530246309556279474" /&gt;&lt;/a&gt;&lt;div style="text-align: left;"&gt;It's a sad fact that in our modern world that there's simply too much code. I can cope with the fact that my car engine is controlled by a computer, there's obviously software cooking the food in my microwave, and it wouldn't surprise me if my genetically modified cucumbers had an embedded micro controller in them. That's all fine; its not what I'm obsessing about. I'm worried about all the &lt;i&gt;unnecessary&lt;/i&gt; code out there.&lt;/div&gt;&lt;div&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;There's simply too much unnecessary code kicking around. Like weeds, these evil lines of code clog up our precious byes of storage, obfuscate our revision control histories, stubbornly get in the way of our development, and use up precious code space, choking the good code around them.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Why is there so much unnecessary code? Perhaps it's due to genetic flaws. Some people like the sound of their own voice. You've met them; you just can't shut them up. They're the kind of people you don't want to get stuck with at parties. Yada yada yada. Other people like their own code too much. They like it so much they write reams of it. &lt;span style="font-family:Courier, monospace;"&gt;{ yada-&gt;yada.yada(); }&lt;/span&gt; Or perhaps they're the programmers with misguided managers who judge progress by how many thousands of lines of code have been written a day.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Writing lots of code does &lt;i&gt;not&lt;/i&gt; mean that you've written lots of software. Indeed, some code can actually negatively affect the amount of software you have – it gets in the way, causes faults, and reduces the quality of the user experience. The programming equivalent of anti-matter.&lt;/p&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Some of my best software improvement work has been by removing code. I fondly remember one time when I lopped literally thousands of lines of code out of a sprawling system, and replaced it with a mere ten lines of code. What a wonderfully smug feeling of satisfaction. I suggest you try it some time.&lt;/p&gt; &lt;h2 class="western"&gt;Why should we care?&lt;/h2&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;So why is this phenomenon &lt;i&gt;bad&lt;/i&gt;, rather than merely &lt;i&gt;annoying&lt;/i&gt;? There are many reasons why unnecessary code is the root of all evil. Here are a few headlines:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Writing a  fresh line of code is the birth of a little lifeform. It will need  to be lovingly nurtured into a useful and profitable member of  software society. Then you release the product.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-left: 1.25cm; margin-bottom: 0cm; font-style: normal"&gt; Over the life of the software system, that line of code needs maintenance. Each line of code costs a little. The more you write, the higher the cost. The longer they live, the higher the cost. Clearly, unnecessary code needs to meet a timely demise before it bankrupts us.&lt;/p&gt; &lt;ul&gt;  &lt;li value="1"&gt;&lt;p style="margin-bottom: 0cm; font-style: normal"&gt;More  code means there is more to read – it makes our programs harder to  comprehend. Unnecessary code can mask the purpose of a function, or  hide small but important differences in otherwise similar code.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal"&gt;The more code  there is, the more work required to make modifications – the  program is harder to modify.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Code harbours  bugs. There more code you have, the more places there are for bugs  to hide.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Duplicated  code is particularly pernicious; you can fix a bug in one copy of  the code and, unbeknown to you, still have another thirty two  identical little bugs kicking around elsewhere.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-bottom: 0cm; font-style: normal"&gt;Unnecessary code comes in many guises: unused components, dead code, pointless comments, unnecessary verbosity, and so on. In a future post, I'll look at some of these pernicious beasties in a little more detail.&lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5356840227129314597?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5356840227129314597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5356840227129314597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5356840227129314597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5356840227129314597'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/10/write-less-code.html' title='Write Less Code!'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TL9ht9GEWLI/AAAAAAAACoo/u1cz41p4nSg/s72-c/no-entry.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8861051589214628858</id><published>2010-10-19T03:26:00.000-07:00</published><updated>2010-10-19T03:50:57.820-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Mapping your learning journey</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TL11Y671KsI/AAAAAAAACog/2BSWKScICA8/s1600/mindmap.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 162px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TL11Y671KsI/AAAAAAAACog/2BSWKScICA8/s200/mindmap.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5529704988478352066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;In the last&lt;a href="http://goodliffe.blogspot.com/2010/09/learning-some-how-tos.html"&gt;&lt;/a&gt; &lt;a href="http://goodliffe.blogspot.com/2010/09/learning-some-how-tos_27.html"&gt;few&lt;/a&gt; posts on &lt;a href="http://goodliffe.blogspot.com/search/label/learning"&gt;learning&lt;/a&gt; I've been reviewing a number of tools that help us, as software developers, learn.The final tool we'll look at in our arsenal is a powerful old favourite: the &lt;i&gt;mind map&lt;/i&gt;. &lt;a href="http://en.wikipedia.org/wiki/Mind_map"&gt;Mind maps&lt;/a&gt; are a powerful outlining technique that appeases the left brain's linear organisational fetish whilst satisfying the right brain's spatial, relational desires.&lt;/p&gt; &lt;p&gt;Mind maps are structured outlines in which you start with a key concept in the middle and add information around it forming a web. You can add extra relations between items, and freely use colour, illustration, size and position to highlight extra information.  &lt;/p&gt; &lt;p&gt;I often produce mind maps for talks and articles I'm writing. Being an unashamed sad geek, I tend to produce these electronically (I used &lt;a href="http://freemind.sourceforge.net/"&gt;FreeMind&lt;/a&gt; which works on Windows, Mac, and Linux). Then I can keep them under source control and version them alongside my articles.&lt;/p&gt; &lt;p&gt;However, many people claim that you will miss the full benefit of the mind mapping technique by doing this. The more visceral, physical act of creating a hand-written version helps you explore and retain information. By laying out the relations yourself rather than relying on a machine to typeset the “document” for you, you consider inter-relations and build a tangible picture in your mind that will aid later recall.&lt;/p&gt; &lt;p&gt;Next time you're learning, why not try to record knowledge in a mind maps you go? When investigating a learning route and working out what you need to know, record your findings in a mind map.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Use mind maps to catalogue information. They are a proven, powerful tool.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8861051589214628858?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8861051589214628858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8861051589214628858' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8861051589214628858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8861051589214628858'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/10/learning-mapping-your-learning-journey.html' title='Learning: Mapping your learning journey'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/TL11Y671KsI/AAAAAAAACog/2BSWKScICA8/s72-c/mindmap.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5775113265056356983</id><published>2010-09-30T00:48:00.001-07:00</published><updated>2010-09-30T01:10:16.951-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>A UITableView with an "empty" view</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TKRBNFi1sJI/AAAAAAAACoI/ax_Z4tAmG0A/s1600/image.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 148px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TKRBNFi1sJI/AAAAAAAACoI/ax_Z4tAmG0A/s200/image.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5522610736145477778" /&gt;&lt;/a&gt;Most every &lt;a href="http://developer.apple.com/devcenter/ios/index.action"&gt;iOS&lt;/a&gt; application that presents a list of information is built around the &lt;a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html"&gt;UITableView&lt;/a&gt; class. It's a central part of the iPhone UI arsenal.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The &lt;i&gt;really&lt;/i&gt; polished apps use this class particularly well. Look at the iPod application, for example. When there is nothing to display in a table view, the iPod app shows a placeholder view with a pretty icon and some text explaining why the list is empty:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TKREQZcnbzI/AAAAAAAACoQ/n9LoTq1Ku8o/s1600/photo.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 126px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/TKREQZcnbzI/AAAAAAAACoQ/n9LoTq1Ku8o/s200/photo.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5522614091562577714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's these neat little UI touches that set a truly great application apart from a merely adequate one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;I want one of those&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's not rocket science to code such UI behaviour, but why do that when someone's already done it for you?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Mosey on over to the &lt;a href="http://gitorious.org/tableviewwithemptyview"&gt;TableViewWithEmptyView Gitorious project&lt;/a&gt; and grab my code from there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Most of that project's files comprise the requisite scaffolding to provide an example demonstrating the class. To use the class in your own project you need only copy over the &lt;a href="http://gitorious.org/tableviewwithemptyview/tableviewwithemptyview/blobs/master/Classes/PGTableWithEmptyView/PGTableViewWithEmptyView.h"&gt;PGTableViewWithEmptyView.h&lt;/a&gt; and &lt;a href="http://gitorious.org/tableviewwithemptyview/tableviewwithemptyview/blobs/master/Classes/PGTableWithEmptyView/PGTableViewWithEmptyView.m"&gt;PGTableViewWithEmptyView.m&lt;/a&gt; files.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using the class is simple. It works exactly like a standard UITableView, but has one extra property &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;emptyView&lt;/span&gt;. Assign this property the UIView you want displayed when there are no items in the table. The rest happens automatically for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The empty view fades in and out smoothly for added UI chintz.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make things even easier, you can wire all this up in your XIB file, so your code need never mention the PGTableViewWithEmptyView class itself. Now &lt;i&gt;that's&lt;/i&gt; &lt;a href="http://www.pauldaniels.co.uk/"&gt;magic&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd be grateful to hear from you if you use this class. Please also feel free to send me any suggestions, improvements, or bug reports.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5775113265056356983?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5775113265056356983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5775113265056356983' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5775113265056356983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5775113265056356983'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/09/uitableview-with-empty-view.html' title='A UITableView with an &quot;empty&quot; view'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/TKRBNFi1sJI/AAAAAAAACoI/ax_Z4tAmG0A/s72-c/image.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-2195755621087591424</id><published>2010-09-29T08:23:00.000-07:00</published><updated>2011-03-14T03:35:57.359-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Building a Boost framework for iOS (iPhone, iPad, etc)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.joachim-faulhaber.de/boost_powered_by.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 277px; height: 86px;" src="http://www.joachim-faulhaber.de/boost_powered_by.png" border="0" alt="" /&gt;&lt;/a&gt;Several &lt;a href="http://www.boost.org/"&gt;Boost&lt;/a&gt; versions have ticked past since I last posted about &lt;a href="http://goodliffe.blogspot.com/2009/12/boost-on-iphone.html"&gt;building a Boost framework for use with the iPhone&lt;/a&gt;. Each version of Boost requires subtly different build steps, and each version better supports building iPhone versions out of the box.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;The good news:&lt;/i&gt; Boost 1.44.0 builds for iPhone a lot more easily than previous versions.&lt;div&gt;&lt;i&gt;The bad news:&lt;/i&gt; making a framework is still not easy.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;But first, why?&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;First, let's answer the obvious question: Why would you want to bother building a framework at all?&lt;br /&gt;&lt;br /&gt;Quite simply: &lt;i&gt;to make your life easier. &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Using the native Boost build, you (may) need to link against a number of different Boost libraries in your application. And then you need to do a clever dance to ensure you link against either the i386 (simulator) or armv6/armv7 (iPhone devices) versions, depending on your build configuration.&lt;br /&gt;&lt;br /&gt;That is tedious and annoying, and not the way it should be. Other Apple "libraries" are provided as a "framework" which you just need to mention once in Xcode, and then the build system works out how to link to the correct version and how to find the right headers.&lt;br /&gt;&lt;br /&gt;So, if we can turn Boost into a framework life would be so much easier.&lt;br /&gt;&lt;br /&gt;And that's what I have done.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pete: &lt;i&gt;Doing all the hard work to save literally... some... people all the hassle.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;Executive summary&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Now, you can do it too.&lt;br /&gt;&lt;br /&gt;Just run the script you'll find in Gitorious here: &lt;a href="http://gitorious.org/boostoniphone/boostoniphone"&gt;http://gitorious.org/boostoniphone/boostoniphone&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Download yourself boost_1_44_0.tbz into the same directory, run the script. Make a cuppa. Make another cuppa. And then admire your new shiney Boost framework.&lt;br /&gt;&lt;br /&gt;Use it like any other framework. Draggy droppy. Happy happy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What changed?&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;For the hardcore faithful who care about htese things, here's what's changed since my last script version:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Boost now builds for iOS far more easily (I think this changed for the better in 1.43.0). Now, you just need to write some gibberish in a user-config.jam and run a boostrap script. &lt;i&gt;That&lt;/i&gt; is a darned site easier than it used to be.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;To make it build for the simulator, you still need to invent some missing header files.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;But the biggest hassle in this version was creating the final universal library file. Since the ARM builds themselves are now fat archives (including an armv6 and armv7 version of each .o file) I needed to work out how to make a functional uber-lib file. Because Apple's binutils are not useful GNU ones, their &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ar&lt;/span&gt; is braindead. The only way to make a correctly functioning library (that I could find) was to un-&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;lipo&lt;/span&gt; the fat ARM binaries, un-&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ar&lt;/span&gt; each archive, link all the original .os into an uber library, than &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;lipo&lt;/span&gt; up each of those. Does that sound painful? Yes. It hurt.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-2195755621087591424?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/2195755621087591424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=2195755621087591424' title='50 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2195755621087591424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/2195755621087591424'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/09/building-boost-framework-for-ios-iphone.html' title='Building a Boost framework for iOS (iPhone, iPad, etc)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>50</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6780955189206294599</id><published>2010-09-27T05:41:00.000-07:00</published><updated>2010-09-27T05:45:46.101-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: A cunning plan...</title><content type='html'>&lt;p&gt;In the common work scenario you start from ground zero and need to get up to speed with something in super-fast time. You need to pick up a new codebase, a new set of technologies, and a new problem domain. And be effective and productive almost immediately.&lt;/p&gt; &lt;p&gt;This is rarely possible. But you can be effective fairly rapidly as long as you recognise that you are starting out at the &lt;i&gt;novice&lt;/i&gt; Dreyfus level (remember our look at the &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-learning-models.html"&gt;Dreyfus Model of Skills Acquisition&lt;/a&gt;?). In order to be effective at this point you must find a good set of rules to follow, since novices rely on rules to get work done.&lt;/p&gt; &lt;p&gt;But you want to progress beyond novice level, don't you?&lt;/p&gt; &lt;p&gt;In order to learn effectively you need to put in place a considered learning plan. Now, if I wanted to get from my home in Cambridge to visit a friend in Inverness, I wouldn’t just jump in the car and set off. I’d need to plan a route first. I wouldn’t even set up my satnav and follow its instructions. Should I really trust a device to know best?Does it know how I prefer to travel, any particularly busy roads at this time of year, which roads the authorities have decided to perform military assaults on today, etc? Similarly, does a teacher know better about how to get me from here to knowledge?&lt;/p&gt; &lt;p&gt;So I'd have to carefully plan a route first. Maybe getting in the car isn’t actually the best way to get to Inverness – perhaps I should instead fly there, and hire a car at the other end.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Put in place a deliberate learning plan.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p&gt;So how might we apply this practically to our learning? Start by recognising exactly what you do know right now. Determine what you &lt;i&gt;need&lt;/i&gt; to know. Weigh up the possible routes to get there: books, courses, web research, podcasts, etc.&lt;/p&gt; &lt;p&gt;Then determine two or three waypoints along the way you can purposefully aim for. Don't aim too far into the future, as once you have learnt more you may need to re-plan your learning route. Work out how to learn enough to get to those first waypoints. Work out exactly how you'll know when  you've got there. (Consider this &lt;i&gt;Test Driven Learning&lt;/i&gt; – work out some tests (katas, specific tasks, etc) that will prove you know something. You can use these same tests in the future to check for regressions in your learning). Then once you have a specific plan in place, begin learning.&lt;/p&gt; &lt;p&gt;Planning and executing a learning journey will make your work more focussed and directed. It may prevent you from wasting time by browsing for far too general information on the web, or reading all of a book when only two chapters in the middle are relevant.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6780955189206294599?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6780955189206294599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6780955189206294599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6780955189206294599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6780955189206294599'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/09/learning-some-how-tos_27.html' title='Learning: A cunning plan...'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3820610287239302929</id><published>2010-09-17T05:06:00.000-07:00</published><updated>2010-09-17T05:17:08.109-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Some How-Tos</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TJNbm_QM6AI/AAAAAAAACoA/qLl0uglx570/s1600/learning-town-450a.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 190px; height: 200px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TJNbm_QM6AI/AAAAAAAACoA/qLl0uglx570/s200/learning-town-450a.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5517854693831534594" /&gt;&lt;/a&gt;&lt;p style="font-style: normal"&gt;Continuing my blog series on software developers &lt;a href="http://goodliffe.blogspot.com/search/label/learning"&gt;learning&lt;/a&gt;, I'm going to look at some of the tools available to help us learn most effectively.&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Using tools&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;So what tools are available? When I ask at conferences what the best learning tool is, without fail someone immediately says "The Brain". However, that is not the right answer.&lt;/p&gt;&lt;p style="font-style: normal"&gt;As strange as it sounds, the most potent and powerful tool we can employ is the &lt;i&gt;entire human body&lt;/i&gt;. A human being is a large interconnected system, the brain is important, it's our CPU, but it's connected and influenced heavily by the rest of our fleshy substance.&lt;/p&gt;&lt;p style="font-style: normal"&gt;We'll see how the whole body is important and can be exploited to help us learn more effectively.&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;The little grey cells&lt;/b&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;But let's start by focussing on the brain. Sadly, we’re not really ever given a user’s manual for the brain. (And even if we were, most men wouldn’t read it anyway...)&lt;/p&gt; &lt;p style="font-style: normal"&gt;Firstly, we must keep this thing well prepared mechanically. Use the correct fuel: enjoy a healthy diet and make sure you keep well hydrated. It is said that the best brain foods are protein-rich foods such as meat, fish and cheese; these are good sources of amino acids. Also ensure you give yourself a good supply of the appropriate vitamins and minerals (vitamin B, sodium, potassium, and omega-3 are all said to be important for brain function). To keep your brain working at it's top condition (and let's be clear – to be an effective developer you really should consider how to keep your brain working as well as you can) you should pay attention to this kind of thing.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Other very obvious basic brain mechanics are to get plenty of sleep and avoid as much stress as possible to enable you to be less distracted and better able to think. It sounds glib advice, but how often do you consider how continual stress or burning the candle at both ends affects your effectiveness?&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Using all of the brain&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-understanding-brain.html"&gt;a previous blog entry&lt;/a&gt; we investigated the left/right brain modes. Most developers lean towards left-brain modes of thinking, so to maximise use of our potential brain power we need to learn to dial down the left side of our brain to give the right side a fighting chance. Otherwise we'll only exploit half of our potential learning power.&lt;/p&gt; &lt;p&gt;Do remember, though, that both modes of thought are essential. We really need to work out how to get both brain modes to work in concert. In order to think and learn effectively we must be able to bring both “sides” of our brain into use.&lt;/p&gt; &lt;p&gt;There are some very basic documented ways to stimulate the right side of your brain. &lt;i&gt;Cross-sensory feedback&lt;/i&gt; will stimulate parts of the brain that we don't normally exercise. Consider trying some of these actions whilst learning:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;listening to music whilst you work,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;doodling whilst you think (&lt;i&gt;yes I am paying attention in  your meeting, look at how many doodles I've made...&lt;/i&gt;),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;fiddling with something (a pen or a paperclip, perhaps),   &lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;talking whilst you work (vocalising what you're doing or  learning, it really does help you retain more knowledge),&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;making thought processes concrete rather than purely  intellectual – like modelling things with building blocks or CRC  cards,&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;meditative practices (many help you attain greater focus and  cut out distractions)&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;These actions can help to invoke the right brain whilst performing activities that you might naturally focus more on left-brain operation. Each of these expand sensory input and serve to activate more neural pathways than normal.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Multiple input, maximal output&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Different personality types learn in different ways. I can’t prescribe the best method of learning for everyone. However, try to learn a topic by absorbing information from many different information sources. In this modern connected world we're presented with many media forms:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;The written: e.g. books, magazines, blogs.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;The spoken: e.g. audio books, presentations, user groups,  podcasts, courses&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;The visual: e.g. video podcasts, tv shows, performances&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Some people will respond better to particular media. What works best for you? For the best results mix several of these sources. Use podcasts on a topic to reinforce what you're reading in a book. Attend a training course and read a book on the topic, too.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Use as many input types as possible to maximise your learning potential.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Take note&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Whilst learning grab a notepad and capture information as you uncover it, rather than let it wash over you.&lt;/p&gt; &lt;p&gt;This serves two purposes. Firstly, it keeps you focussed and helps you to maintain concentration on the topic. It's a basic idea, but remarkably helpful. Secondly, even if you throw those notes away immediately afterwards, the cross-sensory stimulation will aid your recall of facts.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Takes notes as you learn. Even if you throw them away.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;The practice of learning&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Our key to learning is to pay attention to &lt;i&gt;the practice of learning&lt;/i&gt;. Here I'm not using the noun &lt;i&gt;practice&lt;/i&gt;. No, learning is an activity; unless you remain consciously and actively involved you will not learn effectively. Learning without practice, without applying the new knowledge, will not lead to deep understanding or long-term recall. We need to perform what is known as &lt;i&gt;deliberate practice&lt;/i&gt; (&lt;i&gt;&lt;a href="http://www.amazon.co.uk/Self-theories-Motivation-Personality-Development-Psychology/dp/1841690244"&gt;Self-theories: Their role in motivation, personality and development&lt;/a&gt;&lt;/i&gt; (1999) Carol S Dweck. ISBN-10: 1841690244)&lt;/p&gt;  &lt;p&gt;It is perfectly possible to perform pointless practice; to not pay full attention and waste your own time and effort. I'm reminded of some high-school recorder lessons that I was subjected to (ooh, many years ago now). This class was dumped into a room, each given a “learn the recorder” book, and expected to get on with it. It's true that that teaching method does leave a lot to be desired. And it's obvious that a group of kids that don't care at all about playing recorder will never learn to play the recorder. There was no motivation, a failing attitude.&lt;/p&gt; &lt;p&gt;But more importantly, a thirty minute lesson where no one is paying attention or trying to deliberately learn will never lead to learning. At the next lesson all the kids started back at page one again; they'd forgotten everything they'd read previously. There was no actual learning taking place in those lessons. A whole term saw very few people progress beyond the first half-hour of the teaching plan. The lessons were literally a load of hot air. And raucous screeching sounds.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Learning without &lt;/b&gt;&lt;/i&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;doing&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;i&gt; is a fruitless task.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Ensure that your learning regimen involves mindful practice. Powerful techniques to consider here are &lt;a href="http://codekata.pragprog.com/"&gt;Coding Katas&lt;/a&gt; and Coding Dojos. Katas were introduced into the development worlds by Dave Thomas of pragmatic programmer fame. A kata, like its martial arts synonym, is a small task or process that a student can repeat deliberately in order to learn a skill. Perhaps a simple coding exercise or refactoring task. Coding Dojos are meetings where programmers gather to perform katas together. Specific, deliberate learning meetings.&lt;/p&gt; &lt;p&gt;Dojos are becoming increasingly popular. Jon Jagger and Olve Maudal ran &lt;a href="http://www.cyber-dojo.com/"&gt;an excellent Dojo&lt;/a&gt; at this year's ACCU conference, for example. Follow the link for the software system they developed to run it.&lt;/p&gt; &lt;h2 class="western"&gt;&lt;/h2&gt;&lt;p&gt;If the brain is the CPU of our learning machine, then we should consider other uses of the machine that will aid learning. In the modern world, few computers are an island. Networking is an essential learning aid. The social context enhances our learning, and adds accountability (aiding attitude) and greater interactivity (aiding deliberate practice and cross-sensory feedback).&lt;/p&gt; &lt;p&gt;These are all invaluable social learning practices:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;pair programming&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;study groups&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;mentoring and teaching (by teaching others you solidify your  knowledge, you are forced to learn more yourself, and as you see a  newbie begin to gain a wider picture you will realise flaws in your  own knowledge, or see foundational knowledge in a fresh light that  will be really beneficial)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;writing articles (for magazines, for the web, for blogs)&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;discussion (perhaps in the pub)&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3820610287239302929?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3820610287239302929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3820610287239302929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3820610287239302929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3820610287239302929'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/09/learning-some-how-tos.html' title='Learning: Some How-Tos'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TJNbm_QM6AI/AAAAAAAACoA/qLl0uglx570/s72-c/learning-town-450a.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-1310924537131503218</id><published>2010-09-17T04:50:00.000-07:00</published><updated>2010-09-17T05:00:37.825-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Becoming a Better Programmer</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TJNWmDGcDEI/AAAAAAAACn4/qMQZmwKihqg/s1600/cvu-cover-small.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 142px; height: 200px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TJNWmDGcDEI/AAAAAAAACn4/qMQZmwKihqg/s200/cvu-cover-small.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5517849180126317634" /&gt;&lt;/a&gt;Issue 22.4 of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s CVu magazine is out, containing my latest column. This month it's called &lt;i&gt;People Power&lt;/i&gt;. It describes the importance of working with high quality, passionate programmers.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This issue, though, has seen a very significant change in my column.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For over ten years now I've been regularly writing a column entitled &lt;i&gt;Professionalism in Programming&lt;/i&gt;. (I originally named it after the ACCU's "motto".) Times change, and although there's nothing &lt;i&gt;wrong&lt;/i&gt; with the title per-se, it doesn't reflect clearly and unambiguously what I've been writing about.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I've changed the column's name. I now call it &lt;b&gt;Becoming a Better Programmer&lt;/b&gt;. I think this is clearer, snappier, and more useful. I hope you agree!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also modified the way I tackle topics somewhat. I hope you'll appreciate it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd love to hear your comments and feedback.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The magazine should have landed on ACCU members' doormats already. The PDF version is available for download on the &lt;a href="http://www.accu.org"&gt;website&lt;/a&gt;. (And yes, for the cover I have been working through my "pink phase").&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-1310924537131503218?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/1310924537131503218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=1310924537131503218' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1310924537131503218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1310924537131503218'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/09/writing-becoming-better-programmer.html' title='Writing: Becoming a Better Programmer'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0KMnzNqRq8Y/TJNWmDGcDEI/AAAAAAAACn4/qMQZmwKihqg/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6977752792229634533</id><published>2010-08-11T02:44:00.000-07:00</published><updated>2010-08-11T02:59:01.490-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Some How-Tos</title><content type='html'>&lt;blockquote&gt;&lt;div style="text-align: right;"&gt;Tell me, and I will forget. Show me, and I may remember. Involve me, and I will understand.&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;– Confucius&lt;/b&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TGJ0F0LFkmI/AAAAAAAACno/Kq7hwtHbUh0/s1600/DL+Picture.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 138px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TGJ0F0LFkmI/AAAAAAAACno/Kq7hwtHbUh0/s200/DL+Picture.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5504089337853481570" /&gt;&lt;/a&gt;&lt;div&gt;So far we've investigated &lt;i&gt;why&lt;/i&gt; learning is important to software developers, and &lt;i&gt;what&lt;/i&gt; we should be learning. We've looked at some learning models and uncovered many valuable facts about the way the brain stores, processes and retains information. But that's all been background. We've not yet actually put any wheels on our boat, and looked at the practical tools and processes that will help us to learn better.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Now it's time to rectify this omission.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Manage your knowledge portfolio&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The &lt;a href="http://www.pragprog.com/the-pragmatic-programmer"&gt;pragmatic programmers describe&lt;/a&gt; a vivid and potent metaphor for learning – they talk about your &lt;i&gt;knowledge portfolio&lt;/i&gt;. Consider your current working set of knowledge like a portfolio of investments.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This metaphor beautifully highlights how we should &lt;i&gt;manage&lt;/i&gt; the information we have gathered, carefully investing to keep our portfolio current, and bringing in new investments to strengthen it. Consider which items you should retire from your portfolio, to make room for other things. Be aware of the risk/reward balance of the items in your portfolio.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some things are common knowledge, but a safe investment to hold – they are low risk, easy to learn about, and guaranteed to be useful in the future. Other investments are riskier – they may not be mainstream technologies and practices, so studying them may not pay off in the future. But if they do become mainstream then you will be one of a smaller set of people experienced in that niche, and so able to exploit that knowledge more. These higher risk knowledge investments may pay much greater dividends in the future.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You need a good spread of risk and a healthy range of knowledge investments.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;Purposefully manage your knowledge portfolio.&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;The angle of approach&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Whenever I look at a topic in programming (and by now, I've written about quite a few in&lt;a href="http://www.goodliffe.net/publications"&gt; my columns&lt;/a&gt; and &lt;a href="http://www.goodliffe.net/codecraft"&gt;my book&lt;/a&gt;), the essence of success always seems to be determined by a single issue. And in the field of learning it seems as clear as ever: to be successful at learning you have to adopt the correct &lt;i&gt;attitude&lt;/i&gt;. Your attitude towards learning will directly determine the quality of your learning. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We saw &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-understanding-brain.html"&gt;previously&lt;/a&gt; how mental state can affect performance, and the social psychologist Carol Dweck's &lt;a href="http://mindsetonline.com/"&gt;research into the affect of mental attitude on ability to learn&lt;/a&gt;: that those who believed they could learn did so far more effectively than those who thought they couldn't. &lt;i&gt;Self-belief &lt;/i&gt;is an incredibly important attitude.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We must take &lt;i&gt;responsibility&lt;/i&gt; for learning – it is something we must do for ourselves, we cannot expect others to make us learn. We must adopt an attitude of &lt;i&gt;continuous learning&lt;/i&gt;, never believing that we know it all or that we know enough – there must always be a &lt;i&gt;hunger&lt;/i&gt; for new knowledge, a driving &lt;i&gt;curiosity&lt;/i&gt;. This couples with &lt;i&gt;humility&lt;/i&gt;; again recognising that we don't know everything and that we can learn from anyone and anything.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The most effective tool in learning is to &lt;i&gt;care&lt;/i&gt; about what you're learning, and to be prepared to invest effort in order to learn. Dweck wrote about this in &lt;a href="http://www.amazon.co.uk/Self-theories-Motivation-Personality-Development-Psychology/dp/1841690244"&gt;her book Self-Theories&lt;/a&gt;: &lt;i&gt;Effort is one of the things that gives meaning to life. Effort means you care about something, that something is important to you and you are willing to work for it&lt;/i&gt;. If you are prepared to invest effort into learning about something, it not only shows that you value the topic, it means that you intend to and desire to learn.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Coming next: some practical mechanisms to improve your learning.&lt;/i&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6977752792229634533?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6977752792229634533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6977752792229634533' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6977752792229634533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6977752792229634533'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/08/learning-some-how-tos.html' title='Learning: Some How-Tos'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TGJ0F0LFkmI/AAAAAAAACno/Kq7hwtHbUh0/s72-c/DL+Picture.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5350704624004823727</id><published>2010-08-09T07:29:00.000-07:00</published><updated>2010-08-09T07:33:48.218-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>This is how we build software</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TGARCUoagzI/AAAAAAAACng/yslQGKrfuPQ/s1600/SoftwareDevelopment.png"&gt;&lt;img style="margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 282px; height: 400px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TGARCUoagzI/AAAAAAAACng/yslQGKrfuPQ/s400/SoftwareDevelopment.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5503417476242375474" /&gt;&lt;/a&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TGARCUoagzI/AAAAAAAACng/yslQGKrfuPQ/s1600/SoftwareDevelopment.png"&gt;&lt;/a&gt;My tongue was planted firmly in my cheek when I drew this little masterpiece. (Click on the image for a larger version.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It originally appeared in the June 2010 issue of &lt;a href="http://www.accu.org"&gt;ACCU&lt;/a&gt;'s C Vu magazine as part of my regular software development column.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5350704624004823727?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5350704624004823727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5350704624004823727' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5350704624004823727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5350704624004823727'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/08/this-is-how-we-build-software.html' title='This is how we build software'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0KMnzNqRq8Y/TGARCUoagzI/AAAAAAAACng/yslQGKrfuPQ/s72-c/SoftwareDevelopment.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6913661236316385460</id><published>2010-08-09T05:08:00.000-07:00</published><updated>2010-08-09T05:15:09.712-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: A review</title><content type='html'>&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 450px; height: 300px;" src="http://www.links999.net/utopia/images/sleep-learning.jpg" border="0" alt="" /&gt;It's been a while since I wrote a blog about software developers learning. &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-learning-models.html"&gt;Previous&lt;/a&gt; &lt;a href="http://goodliffe.blogspot.com/2010/04/learning-understanding-brain.html"&gt;postings&lt;/a&gt;&lt;a href="http://goodliffe.blogspot.com/2010/02/live-to-love-to-learn.html"&gt; have&lt;/a&gt; investigated learning models, the mechanics of the brain, how, why and what to learn, and more.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's more to come, but let's just take a little refresher of some of the points I've raised so far:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Learning is a basic human skill.&lt;/b&gt; We can all do it. We do it all the time.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Our learning is too narrowly focused&lt;/b&gt;. Consider a wider sphere of reference. Draw inspiration from other fields.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Learning is hard work.&lt;/b&gt; It doesn't come for free. But you don't get a reward without an investment.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Learn to learn. &lt;/b&gt;That's why I'm writing this series! The most effective learning is done on purpose and planned to maximise effectiveness.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The left brain/right brain split&lt;/b&gt; We need to employ all of our available brainpower to make our learning maximally effective.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Personality type affects learning style&lt;/b&gt; Understand how you best learn and exploit that to your advantage.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Memory fades&lt;/b&gt; Unless you refresh your knowledge by using it, your memory of it will become unreliable.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Memory grows&lt;/b&gt; Constant stimulation is required to maintain growing mental capacity.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Mental state effects learning&lt;/b&gt; Cultivate a positive attitude towards learning. Otherwise you may as well not bother.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Learning models &lt;/b&gt;Certain models can help us classify levels of expertise and plan how to gain it.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Shortly I will describe at some very practical techniques to help improve our learning capabilities.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6913661236316385460?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6913661236316385460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6913661236316385460' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6913661236316385460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6913661236316385460'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/08/learning-review.html' title='Learning: A review'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7637947784798992927</id><published>2010-08-03T04:05:00.000-07:00</published><updated>2010-08-05T01:30:08.759-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Eulagise: Adding a EULA to a DMG</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TFf4OBGQebI/AAAAAAAACnQ/UenKeV4bsTg/s1600/EULA.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 76px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TFf4OBGQebI/AAAAAAAACnQ/UenKeV4bsTg/s200/EULA.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5501138389552888242" /&gt;&lt;/a&gt;My code projects usually include a &lt;i&gt;release script&lt;/i&gt;, a shell script that does something like this:&lt;div&gt;&lt;ul&gt;&lt;li&gt;cleans the build tree,&lt;/li&gt;&lt;li&gt;rebuilds the project,&lt;/li&gt;&lt;li&gt;runs the unit tests (stopping if they fail), and&lt;/li&gt;&lt;li&gt;packages the project.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;It's that last step I'm concerned with here. On Mac OS packaging usually involves building a &lt;a href="http://en.wikipedia.org/wiki/Apple_Disk_Image"&gt;DMG&lt;/a&gt; disk image. Automatically creating a DMG isn't &lt;i&gt;entirely&lt;/i&gt; straightforward in a shell script. In fact, it's not straightforward at all. It took me a while to master the process; I bastardised and tweaked part of the &lt;a href="http://adium.im/"&gt;Audium&lt;/a&gt; build process to perform this feat of engineering.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A recent requirement was to add a &lt;a href="http://en.wikipedia.org/wiki/Software_license_agreement"&gt;EULA&lt;/a&gt; to the DMG. If you're a Mac user then you've probably seen them once or twice. They look something like this (this isn't my one, for client confidentiality purposes).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TFf8NjAS4wI/AAAAAAAACnY/fJ_A35lXw8Q/s1600/eula.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 142px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/TFf8NjAS4wI/AAAAAAAACnY/fJ_A35lXw8Q/s200/eula.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5501142779521327874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The EULA appears when you double-click the DMG file, if you agree to the EULA then the disk image opens. If you don't agree, then, well you can work out the rest.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Something so simple, and so standard, must be easy to add. Right?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hate to spoil a good story, but it's a &lt;i&gt;bit&lt;/i&gt; tricky. Don't worry, the story has a happy ending.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's not an easy task because:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The EULA has to be in a very particular format.&lt;/li&gt;&lt;li&gt;The EULA has to be added to the &lt;a href="http://en.wikipedia.org/wiki/Resource_fork"&gt;resource fork&lt;/a&gt; of the DMG.&lt;/li&gt;&lt;li&gt;You can only add resources (i.e. the EULA) to an &lt;i&gt;unflattened&lt;/i&gt; DMG object, use the &lt;i&gt;Rez&lt;/i&gt; utility to add resources, and re-flatten the DMG.&lt;/li&gt;&lt;li&gt;There are no clear and easy docs on the subject. (That I could find.)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Of course, being a script we want this to be automated, rather than a clicky-draggy process. There are programs that'll do clicky-draggy. We have to rule those out.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ideally we want a script that takes a text file as input and the DMG to attach it to. Magic invisible elves inside the script do the rest.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I spent some time writing my own script, hitting a number of obstacles each time around, and then research pointed me towards the &lt;a href="http://www.seamonkey-project.org/"&gt;Seamonkey&lt;/a&gt; build system. Seamonkey has a script &lt;a href="http://mxr.mozilla.org/seamonkey/source/build/package/mac_osx/pkg-dmg?raw=1"&gt;here&lt;/a&gt; that can do it. Hurrah! The script also creates the DMG in the first place, setting icons, volume name, etc. Sounds great, except that it does all the other stuff rather badly. Or at least, less well than the script I already created.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I removed all the other cruft, and paired Seamonkey's script down into &lt;b&gt;eulagise&lt;/b&gt;. Eulagise is a simple (ish) script to add a EULA to a pre-existing DMG. You use it like this:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;./eulagise.pl --license MyEula.txt --target MyDiskImage.dmg&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;a href="http://en.wikipedia.org/wiki/Aleksandr_Orlov_(meerkat)"&gt;Simples&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can get the script on &lt;a href="http://gitorious.org/eulagise/eulagise"&gt;gitorious here&lt;/a&gt;. I hope to neaten it up, and remove all the extraneous cruft shortly.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7637947784798992927?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7637947784798992927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7637947784798992927' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7637947784798992927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7637947784798992927'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/08/eulogise-adding-eula-to-dmg.html' title='Eulagise: Adding a EULA to a DMG'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0KMnzNqRq8Y/TFf4OBGQebI/AAAAAAAACnQ/UenKeV4bsTg/s72-c/EULA.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7888790240495856549</id><published>2010-07-22T00:59:00.000-07:00</published><updated>2010-07-22T01:09:24.867-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Software Development in 2010</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://accu.org/content/images/journals/CVu223Cover.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 351px;" src="http://accu.org/content/images/journals/CVu223Cover.png" border="0" alt="" /&gt;&lt;/a&gt;Issue 22.3 of &lt;a href="http://accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;span style="font-weight:bold;"&gt;CVu&lt;/span&gt; magazine is out now. It contains the my latest &lt;i&gt;Professionalism in Programming&lt;/i&gt; column, entitled &lt;b&gt;Software Development in 2010&lt;/b&gt;.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In case you were wondering, my tongue was firmly planted in my cheek when I wrote it. Well, drew it, really. It was time for a little light relief after the previous installments on &lt;a href="http://goodliffe.blogspot.com/2010/05/writing-live-to-love-to-learn-part-3.html"&gt;software developers learning&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's also another of my book reviews printed in the issue. This time, I look at &lt;a href="http://apress.com/"&gt;APress&lt;/a&gt;' &lt;i&gt;iPhone User Interface Design Projects&lt;/i&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As ever, it's another interesting issue of CVu. Recommended reading.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7888790240495856549?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7888790240495856549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7888790240495856549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7888790240495856549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7888790240495856549'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/07/writing-software-development-in-2010.html' title='Writing: Software Development in 2010'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7109651932392312197</id><published>2010-06-17T05:34:00.001-07:00</published><updated>2010-06-17T23:17:35.222-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Speaking: iPhone Development Software East June</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s200/iPhone+Development.pngt.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s200/iPhone+Development.pngt.png" border="0" alt="" /&gt;&lt;/a&gt;I will be speaking at &lt;a href="http://www.software-east.co.uk/"&gt;Software East&lt;/a&gt; on the 24th June 2010 in Cambridge UK, on the subject of &lt;i&gt;iPhone Development&lt;/i&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a talk I will be giving with &lt;a href="http://twitter.com/phil_nash"&gt;Phil Nash&lt;/a&gt; and Lee Mallabone. It promises to be a fun, practical, and very interesting introduction to developing apps on the iPhone. It already appears to be a quite popular event judging by signup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The event is &lt;b&gt;free to attend&lt;/b&gt; (if you book in advance), and kicks off sometime after 6.30pm (I think the talk starts about 7pm IIRC, there's a buffet served beforehand).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Places are limited, so &lt;b&gt;sign up now&lt;/b&gt; to guarantee yourself a place.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The event page is &lt;a href="http://software-east.net/events/iphone-development"&gt;here&lt;/a&gt;. Go sign up now. What are you waiting for?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7109651932392312197?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7109651932392312197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7109651932392312197' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7109651932392312197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7109651932392312197'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/06/speaking-iphone-development-software.html' title='Speaking: iPhone Development Software East June'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s72-c/iPhone+Development.pngt.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-1457876286836389165</id><published>2010-06-14T07:43:00.000-07:00</published><updated>2010-06-14T07:47:58.482-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Book review: iPhone User Interface Design Projects</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TBZAaERjopI/AAAAAAAACm0/qu2P9oeEDoo/s1600/9781430223597.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 125px; height: 165px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/TBZAaERjopI/AAAAAAAACm0/qu2P9oeEDoo/s200/9781430223597.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5482640412938314386" /&gt;&lt;/a&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;b&gt;Name:&lt;/b&gt; iPhone User Interface Design Projects&lt;/div&gt;&lt;div&gt;&lt;b&gt;Author:&lt;/b&gt; Various&lt;/div&gt;&lt;div&gt;&lt;b&gt;Publisher:&lt;/b&gt; APress&lt;/div&gt;&lt;div&gt;&lt;b&gt;Price:&lt;/b&gt; $39.99&lt;/div&gt;&lt;div&gt;&lt;b&gt;Pages:&lt;/b&gt; 252&lt;/div&gt;&lt;div&gt;&lt;b&gt;Reviewed by:&lt;/b&gt; Pete Goodliffe&lt;/div&gt;&lt;div&gt;&lt;b&gt;Book homepage:&lt;/b&gt; &lt;a href="http://apress.com/book/view/1430223596"&gt;here&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Verdict:&lt;/b&gt; OK&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;This is another book in APress' iPhone development series. Like all the later books in the series, it's produced in black and white, which is a shame given that the book focuses on user interfaces.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is a collection of essays from ten different authors. Each chapter stands alone. Some of the authors are clearly programmers, and their descriptions of interface design come from a techie viewpoint. Others authors are domain experts or people who hired in programmers to get their job done. These discussions are far less technical in nature.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've read quite a few of the APress iPhone books now, and although they are good, I'm starting to get tired of each chapter starting with a gushing "the iPhone is great" section before getting into the meat of the topic. I'd like to see a little heavier editorial control if this series continues. The chapters are personal in nature, and that is part of the charm of these books. However some of the lengthy intros add nothing of value to their chapters.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The material in this book is not as strong as others in this series. This opinion does reflect my bias as a coder rather than an UI designer, but experienced UI designers won't find much essential or new information in this book. In general, good iPhone UI design requires an understanding the native iPhone idioms and of how to create compelling touch-based interfaces for small screen sizes. Some chapters go a way towards describing this; but sadly the book is by no means a compelling or thorough discourse on the subject.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will admit my favourite chapter was a very interesting one on the Font catalogue application FontShuffle. The UI material here was somewhat thin, but it was a really interesting insight into the world of typography.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're starting off on some iPhone UI design work, know nothing about the topic, and fancy a chatty, but brief, introduction to subject this book is OK. If you are a UI designer then you'll probably not find much of value here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-1457876286836389165?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/1457876286836389165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=1457876286836389165' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1457876286836389165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/1457876286836389165'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/06/book-review-iphone-user-interface.html' title='Book review: iPhone User Interface Design Projects'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/TBZAaERjopI/AAAAAAAACm0/qu2P9oeEDoo/s72-c/9781430223597.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4846767137729172613</id><published>2010-06-03T04:12:00.000-07:00</published><updated>2010-06-03T04:30:44.906-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Desert Island Books</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TAeSVRmO6TI/AAAAAAAACms/gvp1KO1JTdc/s1600/desert-island.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 134px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/TAeSVRmO6TI/AAAAAAAACms/gvp1KO1JTdc/s200/desert-island.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5478508365918169394" /&gt;&lt;/a&gt;I was asked to contribute to the &lt;b&gt;Desert Island Books&lt;/b&gt; feature in the current issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;i&gt;C Vu&lt;/i&gt; Magazine by &lt;a href="http://paulgrenyer.blogspot.com/"&gt;Paul Grenyer&lt;/a&gt;. This is a techie take on Radio 4's Desert Island Disks format. Programmers are asked to chose about five books, one of which must be a novel, and one or two albums.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's an interesting choice to have to make, and shows a lot about you.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's what I wrote. The &lt;i&gt;C Vu&lt;/i&gt; article begins with Paul's intro, which was pleasantly non-disparaging! Thanks, Paul!&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;While I was speaking aloud about ways to describe Pete Goodliffe, Jez Higgins suggested I use a recent comment from accu-general, ‘blond, balding, barefoot’. While accurate these aren’t a particularly nice way to describe Pete, although barefoot is at least accurate and not disparaging, like the other two.&lt;br /&gt;&lt;br /&gt;When I think of Pete four things instantly spring to mind, his friendly personality, his bare feet, Cambridge, and curry. I have had many a curry and more than a few beers with Pete Goodliffe, both in Oxford and on occasion in Cambridge. When I think about Pete technically, his sound and solid technical knowledge and advice stand out. He has a lot of experience in software development and not only does he make it work for him to generate great software, he is always happy to help others and pass on the knowledge where he can (sorry Pete, I won’t mention the book).&lt;br /&gt;&lt;br /&gt;I very narrowly missed out on working with Pete a few years ago, which was a shame because I would have learnt a lot.&lt;/span&gt;&lt;/blockquote&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; 'Times New Roman'"&gt;So here I am, stuck on a desert island with nothing but the birds for company. Still, it could be worse; at least the conversation won’t get too geeky. I can’t help but wonder what kind of calamitous event catapulted me from my secure (if dull) office chair to this remote tropical location. Probably one of those stories that no one will ever believe back home, but it almost certainly involved a few whiskies, an ill-placed wager, and a temperamental particle physicist. Curse you CERN and Speyside!&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; 'Times New Roman'"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;At least I’ve got the decent weather. Let’s just hope global warming doesn’t shrink my new island home even further. Perhaps this stack of improbably placed books would provide me a small tower to sit on if the tide does indeed rise.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;For my company on this forsaken isle, the gods of Fate and Calamit&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;y &lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[PJG: I’ve never been described like that before!]&lt;/span&gt;&lt;/span&gt;&lt;span style="font: Helvetica"&gt; &lt;/span&gt;have seen fit to bestow upon me four programming books, one novel, and two albums.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;The computer books seem sadistic, cruel and somewhat ironic, as they haven't left me a computer &lt;span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[PJG: You didn’t ask!]&lt;/span&gt;&lt;/span&gt;. If they had, I’d ram it full if e-books, anyway. At least I’m good for toilet paper for a while. The CDs are just plain torture, as the swines didn’t leave me a CD player &lt;span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[PJG: See previous comment]&lt;/span&gt;&lt;/span&gt;. I’ll have to fashion one from a coconut tree and an albatross. Or just whistle.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;So that means it’s only the novel that’s useful, then. Better pick a big one..&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;So what computer books should I chose? I could select four books I have always wanted to read, but never got round to buying. I could select four random books on a whim that might be interesting. But given that I won’t be able to fiddle with a computer any more (unless I find myself a convenient passing rescue party), I may as well select four classic books that have enthused me in days gone by. Books that will help me reminisce about the good old days when I had hair, when keys were rubbery, and when computers had rainbows on them.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;And that is indeed my first choice. I’ll re-read &lt;i&gt;&lt;a href="http://www.amazon.co.uk/First-Steps-Spectrum-Carolyn-Hughes/dp/0006922406"&gt;First Steps with Your ZX Spectrum&lt;/a&gt; &lt;/i&gt;by Carolyn Hughes. I haven’t picked this book up in about 30 years, but it was my first ever programming book, and the thing that first gave me a passion for programming. I digested the entire book before I ever got near a computer. It has immense personal significance to me. And it also had pretty cartoon pictures of computers telling you what to do. I’ve not read a book like it since.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;In a fit of nostalgia, I recently bought that same book on Amazon. For three pence. Seriously. Three pence. The postage was two orders of magnitude more than the book itself. That really does show how the value of knowledge decreases over time.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;The next book providing this stranded programmer with a stroll down memory lane is Booch’s classic &lt;i&gt;&lt;a href="http://www.blogger.com/Object%20Oriented%20Analysis%20and%20Design%20With%20Applications"&gt;Object Oriented Analysis and Design With Applications&lt;/a&gt;&lt;/i&gt;. I may be developing a theme here, as I recall this book also had a number of interesting cartoons in it. But that’s not why I’m choosing it. I first encountered OOAD at university and it provided an incredibly clear, well reasoned and enjoyable overview of quality design techniques and the application of OO principles to software design. It was a genuinely great introduction to the philosophy of software design. It is also unusual, being one of the minority of hard-cover programming books&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;I’ve ever owned. So it might be useful for hitting wild animals with.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;This book pre-dates the quadrilateral joys of UML, and I always loved Booch’s OO diagramming style. He represented classes by clouds; simply because they were easier to draw on the back of a napkin. The man’s a genius.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;i&gt;&lt;a href="http://www.amazon.co.uk/Pragmatic-Programmer-Andrew-Hunt/dp/020161622X/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1275564371&amp;amp;sr=1-1"&gt;The Pragmatic Programmer&lt;/a&gt; &lt;/i&gt;by Andy Hunt and Dave Thomas will be my third book. It’s a wonderful clear, entertaining, and motivating discourse of the practice of programming from a personal and social standpoint. It’s the kind of book that I love to read, and one of the few books that you can read over and over again, because you actually want to.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;It’s full of sage, refreshing advice.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;However, it could have been vastly improved with a few carefully placed cartoons.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;My last techie book is a hard call. Of the numerous books that have challenged and/or aided me in my career I’d struggle to chose just one. I could spend some serious&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;time digesting a hardcore C++ tome, like Bjarne’s &lt;i&gt;TCPPPL&lt;/i&gt;, or any of Meyer’s or Sutter’s excellent C++ references. I could pick up a development process book, like Beck’s &lt;i&gt;eXtreme Programming Explained &lt;/i&gt;(I remember that one being a very fresh read when I first opened it). Or I could drill into any of a number of design books, like the classic (and painfully obvious) Gang of Four tome or a number of later pattern languages. Perhaps something more recent would be a good companion like Michael Feathers’ legacy code book.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;I’m stuck.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;So I think I’ll select Sam’s &lt;i&gt;&lt;a href="http://www.amazon.co.uk/Sams-Teach-Yourself-24-Hours/dp/0672326817/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1275564388&amp;amp;sr=1-1"&gt;Teach Yourself C++ in 24 Hours&lt;/a&gt; &lt;/i&gt;and be done with it. It’s bound to be wonderful nonsense, and is certain to produce an emotional response. Can’t be any worse than a Schildt book, can it? I think I’ll need the laughs.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;Now to ship those books securely to my remote prison I’ll need to pack them carefully. I wonder if anyone will notice if I wrap them in a stack of ACCU magazines?&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;Presuming that I’m supplied with standard desert island accoutrements such as a copy of the Bible and the complete works of Shakespeare (perhaps with an accompanying infinite number of monkeys on an infinite number of typewriters – hopefully on their own island) then my choice of novel will be a collection of C.S. Lewis’ &lt;i&gt;&lt;a href="http://www.amazon.co.uk/Chronicles-Narnia-seven-bound-together/dp/0007117302/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1275564412&amp;amp;sr=1-1"&gt;Chronicles of Narnia&lt;/a&gt;&lt;/i&gt;. I’ve always had a soft spot for these books (as with much of Lewis’ other writing). I love the Christian symbolism in them, and have started getting into them with my children, so these books would bring back a selection of old and new memories as I’m stranded here.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;It just remains for me to make the choice of two albums. I’m an avid music lover with a wide and somewhat eclectic taste. However, should my soundtrack for a tropical adventure be something relaxing like a Sigur Ross album, something by Lamb, or Air’s chilled &lt;i&gt;Moon Safari&lt;/i&gt;, or perhaps something more upbeat like a Kings of Leon or Killers album? My choice will instead be the awesome Flaming Lip’s masterwork &lt;i&gt;&lt;a href="http://www.amazon.co.uk/Yoshimi-Battles-Pink-Robots-Flaming/dp/B000068PQ0"&gt;Yoshimi Battles the Pink Robots&lt;/a&gt;&lt;/i&gt;, and Delirious’ &lt;i&gt;&lt;a href="http://www.amazon.co.uk/Mezzamorphis-Delirious/dp/B00000J5ZY/ref=sr_1_2?ie=UTF8&amp;amp;qid=1275564458&amp;amp;sr=1-2-spell"&gt;Mezamorphis&lt;/a&gt;&lt;/i&gt;. Both of these are epic, dense, layered, meaningful and rewarding listens.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; "&gt;So that’s it. Spare a thought for me marooned here, and pray I don’t suffer from a coconut allergy or sun stroke.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4846767137729172613?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4846767137729172613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4846767137729172613' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4846767137729172613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4846767137729172613'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/06/desert-island-books.html' title='Desert Island Books'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/TAeSVRmO6TI/AAAAAAAACms/gvp1KO1JTdc/s72-c/desert-island.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3035716003797596706</id><published>2010-05-07T06:30:00.000-07:00</published><updated>2010-05-07T06:42:53.825-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Live to Love to Learn (Part 3)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S-QWkCi5x0I/AAAAAAAACmk/h-6D_Q4i4-U/s1600/cvu-cover-small.png" style="text-decoration: none;"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 142px; height: 200px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S-QWkCi5x0I/AAAAAAAACmk/h-6D_Q4i4-U/s200/cvu-cover-small.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5468520655948990274" /&gt;&lt;/a&gt;Issue 22.2 of ACCU's &lt;b&gt;CVu&lt;/b&gt; magazine is rolling off the printers now. It contains the third (and final) part of my mini-series on software developers learning: &lt;b&gt;Live to Love to Learn&lt;/b&gt;. This installment is the 61st &lt;i&gt;Professionalism in Programming&lt;/i&gt; column I have written. Phew!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also contributed to Paul Grenyer's &lt;b&gt;Desert Island Books&lt;/b&gt; column, describing five techie books and two CDs that I'd take with me to my very personal desert island prison. It was an interesting and challenging choice to make. Paul wrote some very kind words about me, too. Paul, I'm blushing!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This issue also contains a book review I wrote (of &lt;i&gt;iPhone Advanced Projects&lt;/i&gt; by aPress), as well as a photo of me speaking at ACCU 2010. I'm going for maximum exposure, clearly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When I sent this month's cover image to Steve Love, the editor, he said it looked like I'd spilt coffee all over it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's another great issue (despite all my contributions). If you're not an ACCU member but you're passionate about programming do consider &lt;a href="http://accu.org/index.php/joining"&gt;joining ACCU&lt;/a&gt; now.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3035716003797596706?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3035716003797596706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3035716003797596706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3035716003797596706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3035716003797596706'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/05/writing-live-to-love-to-learn-part-3.html' title='Writing: Live to Love to Learn (Part 3)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S-QWkCi5x0I/AAAAAAAACmk/h-6D_Q4i4-U/s72-c/cvu-cover-small.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7404277851202315101</id><published>2010-04-30T03:54:00.000-07:00</published><updated>2010-04-30T04:08:53.391-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Learning Models</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S9q4nRJ9hwI/AAAAAAAACmc/4xxT2HaYjKA/s1600/monkeys.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 148px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S9q4nRJ9hwI/AAAAAAAACmc/4xxT2HaYjKA/s200/monkeys.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5465884082527110914" /&gt;&lt;/a&gt;&lt;p style="font-style: normal"&gt;Continuing my series on software developers learning, here is a brief look at a couple of very interesting and useful &lt;i&gt;learning model&lt;/i&gt;&lt;i&gt;s&lt;/i&gt;. (See also &lt;a href="http://en.wikipedia.org/wiki/Learning_styles"&gt;learning styles&lt;/a&gt; on Wikipedia for other interesting material).&lt;/p&gt;&lt;p style="font-style: normal"&gt;There are a wide variety of interesting and applicable models, and so this investigation is naturally not an exhaustive survey of what might be applicable to us, as software developers.&lt;/p&gt;&lt;p style="text-align: center; "&gt;&lt;i&gt;This material has been adapted and expanded from my March 2010 &lt;/i&gt;&lt;a href="http://accu.org/"&gt;&lt;i&gt;CVu&lt;/i&gt;&lt;/a&gt;&lt;i&gt; &lt;b&gt;Professionalism in programming&lt;/b&gt; magazine column.&lt;/i&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Learning models&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;&lt;/b&gt;There are a number of very illuminating models of learning that have been constructed by educational psychologists. The &lt;i&gt;&lt;b&gt;Dreyfus Model of Skill Acquisition&lt;/b&gt;&lt;/i&gt; is a particularly interesting example, postulated by brothers Stuart and Hubert Dreyfus in 1980 whilst they were working on artificial computer intelligence [&lt;i&gt;A Five-Stage Model of the Mental Activities Involved in  Directed Skill Acquisition.&lt;/i&gt;&lt;span style="font-style: normal"&gt;  Stuart E. Dreyfus; Hubert L. Dreyfus. Storming Media. (Available  from: &lt;a href="http://handle.dtic.mil/100.2/ADA084551"&gt;http://handle.dtic.mil/100.2/ADA084551&lt;/a&gt;)]. After examining highly skilled practitioners in fields such as airline pilots and chess grand-masters, they identified five specific levels of understanding:&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Novice&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  A complete newbie. Novices want to get results fast, but have no  experience to guide them in doing do. They look for rules they can  follow by rote, and have no judgement to tell whether those rules  are good or bad. Given good rules (or luck finding suitable  resources on Google), novices can get quite far. Novices have &lt;/span&gt;&lt;i&gt;no&lt;/i&gt;&lt;span style="font-style: normal"&gt;  knowledge of a topic (yet).&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Advanced beginner&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  At this level, some experience that has lead to learning; you can  break free from rules a little and try tasks on your own. But  perception is still limited, and you'll get stuck when things go  wrong. At this level there is a better understanding of where to get  answers (you know the best API references, for example) but you are  still not at a level where you can comprehend the bigger picture.  The beginner can't focus out irrelevant details, as far as they're  concerned everything and anything could be important to the problem  at hand. Beginners rapidly gain &lt;/span&gt;&lt;i&gt;explicit&lt;/i&gt;&lt;span style="font-style: normal"&gt;  &lt;/span&gt;&lt;i&gt;knowledge&lt;/i&gt;&lt;span style="font-style: normal"&gt; – the  kind of factual knowledge than can be easily written down and  articulated.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Competent&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  This stage sees you with a mental model of the problem domain;  you've mapped the knowledge base, and have begun to associate parts  and understand the relative importance of different aspects. This  big picture view allows you to approach unknown problems, and plan  methodical routes into those problems rather than diving in and  hoping rules will get you to a solution. This is a good place to be.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Proficient&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  people move beyond competency. They have a much better understanding  of the big picture, and are frustrated with the simplifications that  the novice needed. They can correct previous errors and reflect on  their experiences to work better in the future. At this point you  can also learn from other's experiences and assimilate them into  your body of understanding. Proficient people can interpret &lt;/span&gt;&lt;i&gt;maxims&lt;/i&gt;&lt;span style="font-style: normal"&gt;  (as opposed to simplistic rules) and apply them to a problem (e.g.  they know how and when to apply design patterns). Now it is easy to  identify and focus only on the issues that really matter,  confidently ignoring irrelevant details. Here we see the person has  gained significant &lt;/span&gt;&lt;i&gt;tacit knowledge&lt;/i&gt;&lt;span style="font-style: normal"&gt;  – knowledge that's hard to transfer by exposition, that is only  gained by experience and deep understanding.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Expert&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  This is the pinnacle of the learning tree. There are very few  experts. They are authorities on a subject; they know it completely,  and can use this skill interlinked with other skills. They can teach  others (although they probably teach competents better than novices  as there is less of a disconnect). Experts have &lt;/span&gt;&lt;i&gt;intuition&lt;/i&gt;&lt;span style="font-style: normal"&gt;,  so rather than needing rules they naturally see an answer, even if  they can't articulate why it's the best solution.&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;span style="font-style: normal"&gt;Why is the Dreyfus Model interesting? It's a revealing framework to understand where you currently stand in the mastery of a topic, and help determine where you need to get to. Do you need to be an &lt;/span&gt;&lt;i&gt;expert&lt;/i&gt;&lt;span style="font-style: normal"&gt;? Most people are &lt;/span&gt;&lt;i&gt;competent&lt;/i&gt;&lt;span style="font-style: normal"&gt; and this is satisfactory (indeed, a team of experts would be far too top-heavy, and probably dysfunctional).&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;It also illustrates how you should expect to be solving problems at each stage of your learning. Are you looking for simple rules to apply, hungrily gathering maxims to draw experience from, or intuitively sensing answers? How much of a “big picture” view do you have of the topic?&lt;/p&gt; &lt;p style="font-style: normal"&gt;The Dreyfus model is also a very useful aid for teamwork. If you know where a colleague sits on the notice-expert spectrum you can better tailor your interaction with them. It will help you learn how to work with other people – should you give them some simple rules, explain some maxims, or leave them to weave new information into their broader understanding.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Note than the Dreyfus model applies &lt;i&gt;per skill&lt;/i&gt;. You may be an expert in a particular topic, and a complete notice in another. This is natural. And should also be a source of humility – even if you know all there is to know about Behaviour Driven Design, you may no nothing about the Joe Bloggs Test Framework. It should excite you that there is something more to learn that may enhance your expertise in BDD, whilst keeping you humble that you aren't an infallible expert in every subject! No one likes a know-it-all.&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;i&gt;&lt;b&gt;Shu-Ha-Ri&lt;/b&gt;&lt;/i&gt; is another interesting model of learning that originates in Japanese Martial Arts. It is a set of three terms describing the stages a student goes through to to achieve mastery in their discipline, roughly translating to Learn, Detach, Transcend. In the &lt;i&gt;Shu&lt;/i&gt; phase, the student studies under one teacher; he does not understand enough to mix concepts from different streams, but aims to imitate the teacher precisely. He must build up experience in the field, absorbing the teacher's explicit and tacit knowledge. Once he has a full understanding of the techniques, the student reflects on them in the &lt;i&gt;Ha&lt;/i&gt; phase. The knowledge he has learned will not change, but he can interpret, reflect and explore the deeper meaning. Finally, the student progresses to &lt;i&gt;Ri&lt;/i&gt;, where he moves beyond studentship; he has original thoughts, and becomes a master himself. He now has the skills and experience to innovate.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Heed this model. Don't try to transcend and innovate until you have completed the Shu phase of your learning (remember to be aware of &lt;i&gt;unconscious incompetence&lt;/i&gt;) and have completed the Ha phase of understanding the knowledge.&lt;/p&gt;&lt;p style="font-style: normal"&gt;In my recent conference presentations on this subject, I've also looked at the fashionable "craftsman" model, and seen how the historic &lt;i&gt;&lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Guild"&gt;guilds&lt;/a&gt;&lt;/b&gt;&lt;/i&gt; system of the pre-industrial revolution applies (and doesn't apply) to our learning. It's an interesting model that bears comparison to shu-ha-ri.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7404277851202315101?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7404277851202315101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7404277851202315101' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7404277851202315101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7404277851202315101'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/04/learning-learning-models.html' title='Learning: Learning Models'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/S9q4nRJ9hwI/AAAAAAAACmc/4xxT2HaYjKA/s72-c/monkeys.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3591516698070816021</id><published>2010-04-26T04:02:00.001-07:00</published><updated>2010-04-26T04:07:03.201-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Software Developers Learning: Slides available</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/S9Vy9Xpo6uI/AAAAAAAACl0/rsytJmq0I8U/s1600/2010-03-28+Learning+ACCU.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/S9Vy9Xpo6uI/AAAAAAAACl0/rsytJmq0I8U/s200/2010-03-28+Learning+ACCU.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5464400121530215138" /&gt;&lt;/a&gt;&lt;div&gt;The slides from my &lt;a href="http://accu.org/index.php/conferences"&gt;ACCU 2010&lt;/a&gt; presentation on software developers learning, poetically entitled &lt;b&gt;&lt;i&gt;Stood at the bottom of a mountain looking up&lt;/i&gt;&lt;/b&gt; are now available.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This was a very popular presentation, and the room was packed, so thanks to all those who came along and squeezed in. I've had a lot of great feedback, so I'm glad that the talk was useful. As promised, there are a lot of references at the end of the slides that you can follow for more information.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The slides are available on SlideShare &lt;a href="http://www.slideshare.net/petegoodliffe/stood-at-the-bottom-of-a-mountain-looking-up"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you'd like me to give this talk at your site, user group or conference, then please get in touch.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3591516698070816021?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3591516698070816021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3591516698070816021' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3591516698070816021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3591516698070816021'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/04/software-developers-learning-slides.html' title='Software Developers Learning: Slides available'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/S9Vy9Xpo6uI/AAAAAAAACl0/rsytJmq0I8U/s72-c/2010-03-28+Learning+ACCU.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6782598359217048528</id><published>2010-04-26T02:57:00.000-07:00</published><updated>2010-04-26T03:03:23.276-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>iPhone Development slides available</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s1600/iPhone+Development.pngt.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s200/iPhone+Development.pngt.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5464383583290324546" /&gt;&lt;/a&gt;The slides from my ACCU 2010 presentation on iPhone development are now available, for those who wanted a copy.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can view them on SlideShare &lt;a href="http://www.slideshare.net/petegoodliffe/iphone-development-a-brief-introduction"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you'd like me to give this talk at your site, user group or conference, then please get in touch.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6782598359217048528?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6782598359217048528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6782598359217048528' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6782598359217048528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6782598359217048528'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/04/iphone-development-slides-available.html' title='iPhone Development slides available'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S9Vj6t5-9kI/AAAAAAAACls/RN1-7lY1aOo/s72-c/iPhone+Development.pngt.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7404899252197517798</id><published>2010-04-11T14:45:00.000-07:00</published><updated>2010-04-11T14:55:46.723-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Learning: Understanding the brain</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_0KMnzNqRq8Y/S8JFJP75x_I/AAAAAAAAClk/4hKWDQvCfOs/s1600/brain.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 128px;" src="http://2.bp.blogspot.com/_0KMnzNqRq8Y/S8JFJP75x_I/AAAAAAAAClk/4hKWDQvCfOs/s200/brain.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5459001723525384178" /&gt;&lt;/a&gt;Psychologists, biologists, and other similar evil geniuses have studied the human brain for years, and have formulated many models of brain behaviour and models of learning. There is an overwhelming quantify of research on the subject (some quite contradictory). &lt;p style="font-style: normal"&gt;Understanding (at least at a basic level) how the brain works, and some of its characteristics will help us, as software developers, work out how to learn most effectively. Even a rough understanding of some basic principles will help us unlock the potential learning and processing capabilities of our grey matter.&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;The left brain/right brain split. &lt;/b&gt;We hear a lot about the “left-brain” and the “right-brain”. These terms have entered pop culture, and you are as likely to hear them discussed by artists and CEOs as by psychologists. It comes from research (pioneered in the 1970s by Roger W Sperry who coined the left/right brain terminology) discovering that our mental activity is split between the two hemispheres of the brain; either side controlling a different &lt;i&gt;mode&lt;/i&gt; of thinking (&lt;i&gt;Lateral specialization in the surgically separated  hemispheres.&lt;/i&gt;&lt;span style="font-style: normal"&gt; R.W. Sperry. In  Neurosciences Third Study Program. F. Schmitt and F. Worden (Eds.),  Cambridge: MIT Press 3:5-19 (1974).).&lt;/span&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;span style="font-style: normal"&gt;The left hemisphere tends to govern analytic and logical activities (language, symbolic representation, rational deduction, the linear thought process) whilst the right hemisphere performs non-linear processes (characterised as non-rational, spatial, holistic, and identifying spatial relationships).&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;The common view is that people rely more, or tend towards using, one side of their brain rather than other. Artistic, creative types favour their right brain; academics and office-workers favour the left. Apart from reinforcing a social stereotype, this is not strictly accurate since the split of  brain activity is not pure laterally biased. Several psychologists have since tried to come up with other terms, but popular culture has latched on to left- and right- and we're stuck with them.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Both parts of our brain and both modes of thought are essential. In order to think and learn effectively we must be able to bring both “sides” of our brain into use. Since programmers tend to lean towards the left-brain mode of operation, we must learn to introduce more right-brain thinking into our regimen; this requires us to find ways to “dial down” our left brain activity to give the other side a fighting chance.&lt;/p&gt; &lt;p style="font-style: normal"&gt;I'll describe some ways to do this in later postings. There's a lot more that could be said on this subject; it is a huge topic, and well worth investigating more if you are interested.&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Personality type affects learning style&lt;/b&gt; If you favour the right-brain mode of thinking you will learn best when presented with patterns and a holistic view of a subject, rather than a serial stream of information. You'll prefer to make associations and understand overarching themes. If you favour the left-brain you want a linear rational presentation of the topic. You'll prefer to assimilate facts than to have a grand story told you.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Clearly your brain wiring has a radical effect on the most effective style of learning for you.&lt;/p&gt; &lt;p style="font-style: normal"&gt;There are many models of personality type, perhaps the most famous being the &lt;a href="http://en.wikipedia.org/wiki/Myers-Briggs_Type_Indicator"&gt;Myers-Briggs Type Indicator&lt;/a&gt; (MBTI). MBTI classifies your personality along four axes. Your personality type will effect how you associate knowledge, and how you best learn. One MBTI axis is &lt;i&gt;Introvert-Extrovert&lt;/i&gt;. Introverts would rather learn on their own – they need private mental space to work things through. Extroverts learn well in groups where they can discuss and feed off the ideas of others. Another interesting axis is &lt;i&gt;Sensing-Intuition&lt;/i&gt;. The Sensing personality is the classic left-brainer who emphasises facts and details. They must complete one task before moving on. Intuitive people are right-brainers who use their imagination more. They can move on without completing a task or before they understand everything about a subject.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Understanding your particular personality type (there are many MBTI tests available on the web, for example) will reveal specific ways to make your learning routine maximally effective.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Understand how you learn best.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Memory fades.&lt;/b&gt; There was a time when psychologists believed that a memory, once made, was permanent. However this is not the case: a certain enzyme (PKMzeta) is required to keep synaptic connections valid. Lose the enzyme, you lose the memory! (&lt;a href="http://www.nytimes.com/2009/04/06/health/research/06brain.html?_r=1"&gt;See this for more info&lt;/a&gt;).&lt;/p&gt; &lt;p style="font-style: normal"&gt;Our memory is also fallible in other, less chemical, ways. The brain isn't perfect. You'll notice that old memories can change and distort in your mind. (So it's probably not true that &lt;i&gt;things aren't as good as they used to be.&lt;/i&gt;) Memories and opinions can easily warp as we recollect them, to fit our current preferences or preconceived notions. We can very easily implant our own false memories (unconsciously) or become subject to false suggestion from others.&lt;/p&gt; &lt;p style="font-style: normal"&gt;In order to keep your memory active, it must be refreshed – constantly read and exercised. If you don't need and employ a skill then you will use it.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Use your knowledge. Or you'll lose it.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Memory grows.&lt;/b&gt; It was originally thought that mental capacity decreased over time; that humans  start off with a fixed number of brain cells and over the course of a lifetime this number decreases (due to the ageing process, damage caused by trauma, or other abuse – like excessive alcohol intake).&lt;/p&gt; &lt;p style="font-style: normal"&gt;This was determined by scientists studying animals in laboratory cages; they saw no sign of &lt;i&gt;neurogenesis&lt;/i&gt; – the growth of brain cells. But this was simply because a brain devoid of stimulus need make no new connections. The test subjects' brains didn't expand because there was no need to; life in a cage stunts brain growth. That's a pretty damning inditement of modern cubicle working!&lt;/p&gt; &lt;p style="font-style: normal"&gt;In the early 1990s psychologist Elizabeth Gould discovered that in suitable conditions (an environment with stimulation and opportunities to interact and learn) the brain is perfectly capable of growing neurons and making new connections (&lt;i&gt;Neurogenesis in the Neocortex  of Adult Primates.&lt;/i&gt; Elizabeth Gould, Alison J. Reeves, Michael S.  A. Graziano, Charles G. Gross. In: Science 15 October 1999:Vol. 286.  no. 5439, pp. 548 – 52.). Other subsequent studies have drawn links between exercise and increased brain growth.&lt;/p&gt; &lt;p style="font-style: normal"&gt;So that's good news – you have a practically limitless ability to expand your mind. And the scientists have proved that you need stimulation do to so! Break out of your cubicle, and feel free to drink a beer!&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Mental state effects learning.&lt;/b&gt; Factors such as stress and a lack of sleep will clearly contribute to an inability to concentrate, and so will degrade your ability to learn. Your mental &lt;i&gt;attitude&lt;/i&gt; also dictates how well you will learn. Psychologist Carol Dweck's research (&lt;i&gt;Mindset: The New Psychology of  Success.&lt;/i&gt; Carol S Dweck. Ballantine Books. ISBN: 0345472322) shows that students who believed that they couldn't increase their knowledge were not able to do so. Those who believed they could increase their mental capability were easily able to.&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Believe in your ability to learn.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;People who enjoy learning naturally learn more. People who want to learn, learn more. Is this the power of mind over matter? Perhaps it is; and it's something we need to exploit. I've long argued that our attitude effects the quality of our work. This is the central theme of my book Code Craft (&lt;i&gt;Code Craft: The Practice of  Writing Excellent Code. &lt;/i&gt;Pete Goodliffe. No Starch Press. ISBN:  1593271190).&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;I will be speaking more on this topic at the &lt;a href="http://www.accu.org/conference"&gt;ACCU conference&lt;/a&gt; next week.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7404899252197517798?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7404899252197517798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7404899252197517798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7404899252197517798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7404899252197517798'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/04/learning-understanding-brain.html' title='Learning: Understanding the brain'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S8JFJP75x_I/AAAAAAAAClk/4hKWDQvCfOs/s72-c/brain.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-7174170243762285979</id><published>2010-03-30T01:15:00.001-07:00</published><updated>2010-03-30T01:25:47.049-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><title type='text'>Speaking: QCon 2010 learning slides now available</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S7G1WUs_F-I/AAAAAAAAClU/QMU1ibZ7MIA/s1600/2010-03-09+The+Craftsman+Learns+(Slides)+-+Pete+Goodliffe.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S7G1WUs_F-I/AAAAAAAAClU/QMU1ibZ7MIA/s200/2010-03-09+The+Craftsman+Learns+(Slides)+-+Pete+Goodliffe.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5454340018841524194" /&gt;&lt;/a&gt;A belated thanks to everyone who came to my&lt;a href="http://qconlondon.com/london-2010/presentation/The+Craftsman+Learns+%28or+Learning+the+Craft%29"&gt; QCon London 2010 talk&lt;/a&gt; on software developers' learning. I've had some great feedback, which just goes to show that a hangover doesn't do much to dent my presentation skills! I'm glad people found the talk useful; I know it's an interesting topic, and one that programmers don't think hard about too often.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;For those who wanted the slides, they are now available online &lt;/b&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/PeteGoodliffe_TheCraftsmanLearnsorLearningTheCraft.pdf"&gt;&lt;b&gt;here&lt;/b&gt;&lt;/a&gt;&lt;b&gt;.&lt;/b&gt; They've got a lot of extra reference information that I didn't have time to pack into the talk. Don't eat them all at once.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The conference itself was full of very interesting stuff and, as ever, a lot of the most interesting learning happens outside of the talks themselves. The organisers did a great job.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will be presenting an extended version of this talk (and speaking on other topics too) at the ACCU Conference in Oxford this April.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-7174170243762285979?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/7174170243762285979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=7174170243762285979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7174170243762285979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/7174170243762285979'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/03/speaking-qcon-2010-learning-slides-now.html' title='Speaking: QCon 2010 learning slides now available'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S7G1WUs_F-I/AAAAAAAAClU/QMU1ibZ7MIA/s72-c/2010-03-09+The+Craftsman+Learns+(Slides)+-+Pete+Goodliffe.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8665260704378027709</id><published>2010-03-09T02:30:00.000-08:00</published><updated>2010-03-09T02:39:14.840-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: Live To Love To Learn</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://accu.org/content/images/journals/CVu221Cover.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 354px;" src="http://accu.org/content/images/journals/CVu221Cover.png" border="0" alt="" /&gt;&lt;/a&gt;The latest issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s CVu Magazine is out now. It contains the second part of my series on software developers learning: &lt;b&gt;Live To Love To Learn&lt;/b&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is something I've been looking into a lot recently; I've spent many hours researching, writing and speaking on the subject. Learning is a large topic (seriously vast), and the more I learn about it, the more I realise I don't know!&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's quite a lengthy article this month; looking at some basic learning facts, some interesting models of learning, and investigations into how the brain works in order to gain and retain knowledge. I hope you find it interesting and useful.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is the 60th column in my &lt;i&gt;Professionalism in Programming&lt;/i&gt; series. That means I've been writing these articles for &lt;b&gt;10 years&lt;/b&gt; now. &lt;b&gt;That&lt;/b&gt; is a frightening thought!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I should have learnt how to quit by now...&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8665260704378027709?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8665260704378027709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8665260704378027709' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8665260704378027709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8665260704378027709'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/03/writing-live-to-love-to-learn.html' title='Writing: Live To Love To Learn'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-5144233373167719496</id><published>2010-03-08T16:16:00.000-08:00</published><updated>2010-03-09T00:08:17.598-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><title type='text'>Speaking: QCon London 2010 (this week)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5WTyAeMw0I/AAAAAAAAClM/NkRR_kKh2Cs/s1600-h/2010-01-11+Learning.001.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5WTyAeMw0I/AAAAAAAAClM/NkRR_kKh2Cs/s200/2010-01-11+Learning.001.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5446421811703890754" /&gt;&lt;/a&gt;I am speaking at &lt;a href="http://qconlondon.com/"&gt;QCon in London&lt;/a&gt; this week. The official details for my session &lt;a href="http://qconlondon.com/london-2010/speaker/Pete+Goodliffe"&gt;are here&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My talk is entitled: &lt;b&gt;The Craftsman Learns (or Learning the Craft)&lt;/b&gt; and it's going to be both practical and a great deal of fun. We'll investigate why software developers learn, what software developers (should) learn, and some keys that will help us to learn more effectively.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Useful stuff for any programmer who cares about their craft.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-5144233373167719496?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/5144233373167719496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=5144233373167719496' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5144233373167719496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/5144233373167719496'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/03/speaking-qcon-london-2010-this-week.html' title='Speaking: QCon London 2010 (this week)'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5WTyAeMw0I/AAAAAAAAClM/NkRR_kKh2Cs/s72-c/2010-01-11+Learning.001.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-33166650703715131</id><published>2010-03-05T02:20:00.000-08:00</published><updated>2010-03-05T02:44:11.228-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Book: 97 Things Every Programmer Should Know</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5DdqZ6cmmI/AAAAAAAAClE/V2E5UgvmjfQ/s1600-h/IMG_1018.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px; height: 200px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5DdqZ6cmmI/AAAAAAAAClE/V2E5UgvmjfQ/s200/IMG_1018.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5445095670071204450" /&gt;&lt;/a&gt;The latest book in &lt;a href="http://oreilly.com/"&gt;O'Reilly's&lt;/a&gt; 97 Things series is out now: &lt;b&gt;97 Things Every Programmer&lt;/b&gt; should know. I have three items in this book, and have just received my paper copy (photographic proof attached for the non-believers!).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Despite the somewhat underwhelming cover (it's now the series ident, apparently), it's actually a very well produced book. Thanks to everyone involved.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Details from the publisher's website &lt;a href="http://oreilly.com/catalog/9780596809492/"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My contributions are:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: 11px; color: rgb(34, 34, 34); "&gt;&lt;h3 style="font-size: 11px; display: block; border-top-color: rgb(255, 255, 255); border-right-color: rgb(222, 222, 222); border-bottom-color: rgb(222, 222, 222); border-left-color: rgb(255, 255, 255); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 3px; padding-right: 7px; padding-bottom: 3px; padding-left: 7px; position: relative; font-weight: bold; width: 732px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;span class="chapter-label"&gt;&lt;/span&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;h3 style="font-size: 11px; display: block; border-top-color: rgb(255, 255, 255); border-right-color: rgb(222, 222, 222); border-bottom-color: rgb(222, 222, 222); border-left-color: rgb(255, 255, 255); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 3px; padding-right: 7px; padding-bottom: 3px; padding-left: 7px; position: relative; font-weight: bold; width: 732px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;span class="chapter-label"&gt;Chapter 26 &lt;/span&gt;Don't Ignore That Error!&lt;/h3&gt;&lt;div&gt;&lt;h3 style="font-size: 11px; display: block; border-top-color: rgb(255, 255, 255); border-right-color: rgb(222, 222, 222); border-bottom-color: rgb(222, 222, 222); border-left-color: rgb(255, 255, 255); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 3px; padding-right: 7px; padding-bottom: 3px; padding-left: 7px; position: relative; font-weight: bold; width: 732px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;span class="chapter-label"&gt;Chapter 39 &lt;/span&gt;Improve Code by Removing It&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style="font-size: 11px; display: block; border-top-color: rgb(255, 255, 255); border-right-color: rgb(222, 222, 222); border-bottom-color: rgb(222, 222, 222); border-left-color: rgb(255, 255, 255); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 3px; padding-right: 7px; padding-bottom: 3px; padding-left: 7px; position: relative; font-weight: bold; width: 732px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;span class="chapter-label"&gt;Chapter 96 &lt;/span&gt;You Gotta Care About the Code&lt;/h3&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;h3 style="font-size: 11px; display: block; border-top-color: rgb(255, 255, 255); border-right-color: rgb(222, 222, 222); border-bottom-color: rgb(222, 222, 222); border-left-color: rgb(255, 255, 255); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 3px; padding-right: 7px; padding-bottom: 3px; padding-left: 7px; position: relative; font-weight: bold; width: 732px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;/h3&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-33166650703715131?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/33166650703715131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=33166650703715131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/33166650703715131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/33166650703715131'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/03/book-97-things-every-programmer-should.html' title='Book: 97 Things Every Programmer Should Know'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S5DdqZ6cmmI/AAAAAAAAClE/V2E5UgvmjfQ/s72-c/IMG_1018.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-4425256390352606020</id><published>2010-02-22T02:16:00.000-08:00</published><updated>2010-02-22T02:40:51.631-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>Book review: iPhone Advanced Projects</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S4Ja0NGn8RI/AAAAAAAACk0/IGgVQqgO-h0/s1600-h/9781430224037.gif"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 125px; height: 165px;" src="http://4.bp.blogspot.com/_0KMnzNqRq8Y/S4Ja0NGn8RI/AAAAAAAACk0/IGgVQqgO-h0/s200/9781430224037.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5441011152734122258" /&gt;&lt;/a&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;b&gt;Name:&lt;/b&gt; iPhone Advanced Projects&lt;/div&gt;&lt;div&gt;&lt;b&gt;Author:&lt;/b&gt; Various&lt;/div&gt;&lt;div&gt;&lt;b&gt;Publisher:&lt;/b&gt; APress&lt;/div&gt;&lt;div&gt;&lt;b&gt;Price:&lt;/b&gt; $39.99&lt;/div&gt;&lt;div&gt;&lt;b&gt;Pages:&lt;/b&gt; 374&lt;/div&gt;&lt;div&gt;&lt;b&gt;Reviewed by:&lt;/b&gt; Pete Goodliffe&lt;/div&gt;&lt;div&gt;&lt;b&gt;Verdict&lt;/b&gt;: OK&lt;/div&gt;&lt;div&gt;&lt;b&gt;Book homepage:&lt;/b&gt; &lt;a href="http://www.apress.com/book/view/9781430224037"&gt;here&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is another book in the APress iPhone "projects" series. It follows the form of its predecessors; it is a series of 11 essays by different authors on a particular topic which that they have some familiarity (I'm not sure I can always say "expertise") in.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Production&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, the book production bears discussion. Unlike previous books, this one is printed in plain black and white rather than the accustomed luxurious full-colour. The book still costs the same amount, so this appears to be a ploy by publisher to increase profit rather than a way to position book at lower price point to gain more readers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Unfortunately, the book suffers because of this. Not only is it less visually appealing, it is less practical and easy to follow. Some visual modification should have been applied to the format to make it work in B&amp;amp;W. Without colour, the sans-serif body text is harder to read and is less distinct from headings, subtitles, and illustrations.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In particular, many screen shots suffer. Often an author refers to details that are completely lost in a sea of black ink. These images should have been edited to improve contrast, or the text reworked to explain the point without an illustration.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Editing&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the whole this book has been well edited and proofed, probably better than some of the other books in the series. There are only a few typos. It hangs together as well as the other books, which is fine - it's a series of unconnected essays on different topics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As another "grab bag" book, you'll either want to make a purchase if you care about a specific topic included (see below), or you just want a general overview of a number of topics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Topics&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The book covers the expected iPhone topics: Graphics/UI (creating particle systems, OpenGL ES reflections, and making responsive UIs), networking (writing an app backend server to integrate with iphone app, using push notifications, yet another socket-based UDP example, and sending an email from your app), audio, debugging, and data handling (both in SQLite, and Core Data).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Most chapters are sufficiently detailed. The audio chapter, I felt, was a chatty overview, but didn't provide as good a grounding as just reading the iPhone audio docs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As ever, the detail in each chapter cannot replace the iPhone SDK docs which are complete and detailed. However, there are often little information gems that will help your development and save you a little time working with that technology.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're new to iPhone programming, this might be an interesting book. Also consider the other Apress titles in the series, and chose the book with the topics you are most interested in.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-4425256390352606020?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/4425256390352606020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=4425256390352606020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4425256390352606020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/4425256390352606020'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/02/book-review-iphone-advanced-projects.html' title='Book review: iPhone Advanced Projects'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_0KMnzNqRq8Y/S4Ja0NGn8RI/AAAAAAAACk0/IGgVQqgO-h0/s72-c/9781430224037.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8619542486391917141</id><published>2010-02-11T02:00:00.000-08:00</published><updated>2010-02-11T02:16:06.440-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><title type='text'>Speaking: Sunday Morning Service, Old Windsor</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S3PYmEXJwSI/AAAAAAAACks/Ad9OjjxDM0Y/s1600-h/Transfigurationraffaelo.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 181px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S3PYmEXJwSI/AAAAAAAACks/Ad9OjjxDM0Y/s200/Transfigurationraffaelo.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5436927323683799330" /&gt;&lt;/a&gt;One of my more baroque speaking engagements of late: this Sunday I will be preaching in the morning 9.30 service at &lt;a href="http://www.oldwindsorchurch.org.uk/"&gt;Old Windsor&lt;/a&gt; in Berkshire.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The service theme is the &lt;a href="http://en.wikipedia.org/wiki/Transfiguration_of_Jesus"&gt;transfiguration&lt;/a&gt;. My talk will therefore probably involve feet in mouths.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8619542486391917141?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8619542486391917141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8619542486391917141' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8619542486391917141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8619542486391917141'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/02/speaking-sunday-morning-service-old.html' title='Speaking: Sunday Morning Service, Old Windsor'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/S3PYmEXJwSI/AAAAAAAACks/Ad9OjjxDM0Y/s72-c/Transfigurationraffaelo.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3144796172642225934</id><published>2010-02-11T01:53:00.000-08:00</published><updated>2010-02-11T01:58:06.257-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Developers Learning: The Facts of Life</title><content type='html'>&lt;div&gt;&lt;p align="RIGHT" style="font-style: normal"&gt;&lt;span style="font-family:Helvetica, sans-serif;"&gt;Learning is like rowing upstream: not to advance is to drop back.&lt;/span&gt;&lt;/p&gt; &lt;p align="RIGHT" style="font-style: normal"&gt;– &lt;span style="font-family:Helvetica, sans-serif;"&gt;&lt;b&gt;Chinese proverb&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;Continuing my exploration of the ways we (software developers) can improve our learning, here are a few facts that provide some useful context. None of them are at all specific to the software development but, as ever, I'm writing from the perspective of the software developer, and addressing the development world.&lt;/div&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Learning is a basic human skill.&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;&lt;/b&gt;We all do it. We just do it in different amounts. Small children are constantly learning and amassing new skills. Language, cause-and-effect, and social skills are picked up rapidly from birth. As are basic physiological capabilities like eating, walking, and continence. (Although continence might also be considered a social skill of sorts.)&lt;/p&gt; &lt;p style="font-style: normal"&gt;When it arrives freshly formatted, the human brain rapidly absorbs information and develops skills across a wide range of experiences. It's a remarkable device, both intricate and powerful, and we need to learn how to best use it. Unfortunately, it doesn't come with a User's Manual. (Even if it did, most men wouldn't read it, anyway).&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Our learning is often too narrowly focused.&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;&lt;/b&gt;&lt;span style="font-weight: normal"&gt;Infants absorb information in many disciplines rapidly. And simultaneously. They don't know that they're simply &lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;not supposed to&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: normal"&gt;. But all too soon, our training starts; we're introduced to the thought police.&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;Or, rather, a&lt;/span&gt;t school we hop on board the academic train and our incredible generalised learning capability is slowly frittered away. At primary school we are taught a range of topics. At secondary school these topics are formalised and compartmentalised somewhat. As we progress through the academic system we cut out certain topics and concentrate on those that suit us best (because of interest or aptitude). At (UK) GCSE level, we narrow the focus to about 8 subjects. We progress to A-Level and narrow that focus to 3 or 4 subjects. Then we progress to university level where we focus on a single subject.&lt;/p&gt; &lt;p style="font-style: normal"&gt;This increasing focus in learning is useful in that it allows us time to become highly proficient in one area, and to devote time to practice the specific skills required to master that subject. It also allows us to chose a single topic that excites and interests us: surely a prerequisite for effective learning.&lt;/p&gt; &lt;p style="font-style: normal"&gt;But often such high specialisation is detrimental to your ability to learn in general. It ingrains a lack of curiosity for other disciplines or any appreciation of the wider human experience. However, it is when disciplines collide that we often see the the most exquisite insights (consider, for example, how Alexander's architectural work illuminated the field of software design [1]).&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;Learning is hard.&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;&lt;/b&gt;When an infant learns, the world is new and exciting; as they coast through it they just absorb stuff. After a certain point, the things you &lt;i&gt;have&lt;/i&gt; to learn become less interesting. Adults force you to learn stuff. It involves effort. Effort which you could expend on other tasks, like playing with your friends, or your toys. Then you're given homework and learning starts to take over your precious “free time”. It feels like hard work. It &lt;i&gt;is&lt;/i&gt; hard work.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Learning is hard.&lt;/p&gt; &lt;p style="font-style: normal"&gt;That hard work will, though, be rewarded. But it's easy to resent learning as a tedious chore that stands between us and “fun” or “ability”. Many people's early school experience of learning still colours their adult life approach to learning, even if they don't realise it. How often have you balanced the reward of learning something against the effort involved? How often has the initial learning effort put you off learning something new? Are you now automatically programmed to avoid areas you know nothing about because it is uncomfortable to appear ignorant?&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Have your past experiences coloured the way you approach learning?&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;&lt;b&gt;We must learn how to learn.&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;&lt;/b&gt;&lt;span style="font-weight: normal"&gt;Many people were spoon-fed information in school, and told not to criticise. This instils a bad attitude to learning; where it is something someone &lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;gives&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: normal"&gt; you, or that a teacher &lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;does to&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: normal"&gt; you. Learning is actually a personal process that you have to take individual responsibility for.&lt;/span&gt;&lt;/p&gt; &lt;p align="CENTER"&gt;&lt;i&gt;&lt;b&gt;Do you take personal responsibility for your own learning?&lt;/b&gt;&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal; font-weight: normal"&gt;Don't blithely accept what you're told. Keep your brain engaged. It's dangerously easy to fall into the trap of believing what you're reading or being told is the gospel truth, rather than something that should be evaluated.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p style="font-style: normal; font-weight: normal"&gt;How many  people read things on the internet and presume that they are true?  Wikipedia has a genuine air of authority, yet contains many  remarkable mis-truths. Some of the tubes of the internet are rather  grimy.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal; font-weight: normal"&gt;How many  people read things in their newspaper and unquestioningly presume  that they are correct? True, there are lunatics out there on the  web, but paid journalists wouldn't make things up, would they?  &lt;i&gt;Wrong&lt;/i&gt;: there are plenty of lunatics in the media, too. If you  believed everything you read in the newspaper then you wouldn't eat  or drink anything for fear that it would given you an incurable  disease.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p style="font-style: normal; font-weight: normal"&gt;If it's in a  textbook, written by an academic, peer reviewed, and recommended by  a prestigious university then it must be correct. But consider who  paid to write the book, or who funded the research. What are their  motives driven by? Many things presented as fact in the most  prestigious journals are, in fact, opinion and conjecture backed up  by slim arguments. For example, 70% of everything I've written up to  this point was made up. Including that statistic.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;Be aware that you can learn the wrong thing and believe it's the right thing. This can be at best embarrassing, and at worst dangerous. This is illustrated by the&lt;/span&gt; &lt;i&gt;Four Stages of Competence&lt;/i&gt; (a classification posited in the by 1940s by psychologist Abraham Maslow). You may have:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Conscious incompetence.&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  You don't know something. But you know that you're ignorant. This is  a relatively safe position to be in. You probably don't care –  it's not something you need to know. Or you know that you're  ignorant and it is a source of frustration.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Conscious competence.&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  This is also a good state to be in. You know something. And you know  that you know it. To use this skill you have to make a conscious  effort, and concentrate.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Unconscious competence.&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  This is when your knowledge of a topic is so great that it has  become second nature. You are no longer aware that you are using  your expertise. Most adults, for example, can consider walking and  balance as an unconscious competence – we just do it without a  second thought.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Unconscious incompetence.&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;  This is the dangerous place to be. You don't know that you don't  know something. You are ignorant of your ignorance. Indeed, it is  very possible that you think you understand the subject but don't  appreciate how very wrong you are. It is a &lt;/span&gt;&lt;i&gt;blind spot &lt;/i&gt;&lt;span style="font-style: normal"&gt;in  your knowledge.&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="font-style: normal"&gt;So be very careful when claiming competence in any subject, let alone any level of expertise.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3144796172642225934?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3144796172642225934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3144796172642225934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3144796172642225934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3144796172642225934'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/02/developers-learning-facts-of-life.html' title='Developers Learning: The Facts of Life'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-3636560240934281880</id><published>2010-02-03T03:58:00.000-08:00</published><updated>2010-02-03T04:16:59.399-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='speaking'/><title type='text'>Speaking: QCon London 2010</title><content type='html'>&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 494px; height: 88px;" src="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/top-banner.jpg" border="0" alt="" /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I will be speaking at &lt;a href="http://www.qconlondon.com/"&gt;QCon 2010&lt;/a&gt; in London this March. Details of my session are listed &lt;a href="http://qconlondon.com/london-2010/speaker/Pete+Goodliffe"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm excited to be talking in the "Software Craftsmanship" track (something I care about - my book is called &lt;a href="http://www.amazon.com/Code-Craft-Practice-Writing-Excellent/dp/1593271190"&gt;Code Craft&lt;/a&gt;, after all...) My talk title is &lt;b&gt;The Craftsman Learns (or Learning the Craft)&lt;/b&gt;. It's an investigation of how, why, and when a software craftsman should learn.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's a little more info:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="  border-collapse: collapse; font-family:Verdana, sans-serif;font-size:11px;"&gt;&lt;div align="left" style="text-align: left; "&gt;&lt;i style="text-align: left; "&gt;&lt;/i&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div align="left" style="text-align: left; "&gt;&lt;i style="text-align: left; "&gt;Software developers should be perennial students.&lt;/i&gt;&lt;/div&gt;&lt;div align="left" style="text-align: left; "&gt;&lt;br /&gt;Exceptional programmers aren't the ones who know it all. No one possibly can, no matter what the self-professed gurus would have you believe. Truly great software developers know their limits, and constantly strive to push them, to learn new skills and amass a catalogue of new techniques that can be applied to their craft.&lt;br /&gt;&lt;br /&gt;As a programmer you constantly face fresh challenges; you will frequently be forced to learn a new language, a new technology, or a new project. And you will have to know it all by... yesterday. It's both our responsibility and, hopefully, our pleasure.&lt;br /&gt;&lt;br /&gt;I this talk we'll investigate:&lt;br /&gt;&lt;ul style="text-align: left; "&gt;&lt;li style="text-align: left; "&gt;how the software craftsman approaches learningwhat information to learn, and what to ignore&lt;/li&gt;&lt;li style="text-align: left; "&gt;how to learn new things effectively&lt;/li&gt;&lt;li style="text-align: left; "&gt;techniques for quickly picking up new technology&lt;/li&gt;&lt;li style="text-align: left; "&gt;healthy attitudes to towards learning&lt;/li&gt;&lt;li style="text-align: left; "&gt;the craftsman's curiosity, and how to assuage it&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div align="left" style="text-align: left; "&gt;&lt;b style="text-align: left; "&gt;&lt;br /&gt;Keywords&lt;/b&gt;: Craftsman, Learning, Soft-skills, Software practice&lt;br /&gt;&lt;b style="text-align: left; "&gt;&lt;br /&gt;Target audience&lt;/b&gt;:&lt;/div&gt;&lt;ul style="text-align: left; "&gt;&lt;li style="text-align: left; "&gt;Software developers who care about their craft and want to improve their coding skills.&lt;/li&gt;&lt;li style="text-align: left; "&gt;No assumption will be made about specific technical knowledge.&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-3636560240934281880?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/3636560240934281880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=3636560240934281880' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3636560240934281880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/3636560240934281880'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/02/speaking-qcon-london-2010.html' title='Speaking: QCon London 2010'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-8520985683960963757</id><published>2010-02-03T03:54:00.000-08:00</published><updated>2010-02-03T05:42:38.786-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='learning'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Live to Love to Learn</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s1600-h/bagpuss_professor_yaffle.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 180px; height: 155px;" src="http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s400/bagpuss_professor_yaffle.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5434012169066063474" /&gt;&lt;/a&gt;&lt;p align="RIGHT" style="font-style: normal"&gt;&lt;span style="font-family:Helvetica, sans-serif;"&gt;Learning without thought is labor lost; thought without learning is perilous.&lt;/span&gt;&lt;/p&gt;&lt;p align="RIGHT" style="font-style: normal"&gt;&lt;span style="font-family:Helvetica, sans-serif;"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;– &lt;span style="font-family:Helvetica, sans-serif;"&gt;&lt;b&gt;Confucius&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;These are a few thoughts on the importance of learning. It's a theme I've been dwelling on lately, as I've been rapidly learning a lot of new technologies, skills, and languages. I am writing on the topic in my Professionalism in Programming magazine column, and will be talking on the subject at a &lt;a href="http://goodliffe.blogspot.com/2010/02/speaking-qcon-london-2010.html"&gt;couple of&lt;/a&gt; &lt;a href="http://goodliffe.blogspot.com/2009/12/speaking-accu-2010.html"&gt;conferences&lt;/a&gt; this year.&lt;/p&gt;&lt;p style="font-style: normal"&gt;This blog entry is addressed to software developers, as I am a software developer. However I believe it's applicability extends beyond software development...&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Learning to learn&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;Programming is a creative, intuitive process. I, like many other programmers, like to think of it as an artistic pursuit; one of working a medium to produce something of utility and beauty. But all too often the commercial reality of coding is something more akin to being placed in a meat grinder, until every last ounce of coding prowess and motivation has been sucked from your soul.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Nonetheless, programming is an exciting and dynamic field to work in. One of the main reasons is that there is &lt;i&gt;always&lt;/i&gt; something new to learn. Rarely are programmers forced to run around in circles performing the same repeated task for years and years, only discovering new ways to develop RSI and failing eyesight. We continually face the unknown: new problems, new situations, new teams, new technologies, or some combination of these. True, some programming jobs face more excitement than others, more of the unknown than others, and garner more techie thrills. But if you're going to be stuck in an office sat behind a desk, you may as well keep your mind occupied.&lt;/p&gt; &lt;p style="font-style: normal"&gt;We are continually challenged to learn, to increase our skills and our capabilities. If you feel like you're stagnating in your career, one of the most practical steps you can take to get out of the rut is to take the effort to &lt;i&gt;learn something new&lt;/i&gt;. On purpose.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Now, some people are naturally better at absorbing new information and “getting up to speed” more rapidly than others. They are better at taking on new concepts and relating new concepts to gather a greater understanding. That's natural. But it's something we can all improve at. You need to take charge of your learning.&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Check point&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-style: normal"&gt;Ask yourself now whether &lt;/span&gt;&lt;i&gt;learning&lt;/i&gt;&lt;span style="font-style: normal"&gt; is something that you think about consciously as a programmer? Is it something you consider as one of your programming skills? Do you actively try to learn things? Do you willingly put yourself into areas of the unknown? Or do you try to stick to what you know best, looking for an easy life?&lt;/span&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;Are you motivated as a programmer to find out new information and improve yourself? Do you relish learning? Or is it something of an inconvenience?&lt;/p&gt; &lt;p style="font-style: normal"&gt;Do you want to improve as a programmer? I suspect that in this regard I'm preaching to the converted in this article. An ACCU member reading CVu clearly wants to widen their knowledge. Well done, give yourself a pat on the back! The simple fact is this: if you want to improve as a programmer, you &lt;i&gt;need&lt;/i&gt; to be a skilled and seasoned learner. And you need to learn to enjoy it.&lt;/p&gt; &lt;p style="font-style: normal"&gt;So lets think about the what, why and how...&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;Why learn?&lt;/b&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;Sometimes you have no choice but to learn; you are faced with a new task and you know nothing about the technology or the problem domain. You've got to get up to speed, and fast. Often the killer problem is that you have &lt;i&gt;no&lt;/i&gt; time to do this in, and have to make a work estimate or deliver the first bit of functionality before you'd even have time to gather the vaguest overview of the topic.&lt;/p&gt; &lt;p style="font-style: normal"&gt;The programmer's lot is not a happy one.&lt;/p&gt; &lt;p style="font-style: normal"&gt;But even when you're coasting – working on reserve knowledge, with no need for new information – it's important to keep the grey cells ticking over and absorb new knowledge. One important reason is to simply cultivate a good learning habit; to maintain your ability to absorb information. Continually learning also helps to shape your programming attitude; to prevent you from believing that you're an expert! No one likes a know-it-all, after all.&lt;/p&gt; &lt;p style="font-style: normal"&gt;There are plenty of other good reasons to develop yourself by learning. Your motivation might be to keep yourself fresh, to sharpen your existing skills, or simply to satisfy your natural curiosity. Or the reason might be more mercenary: the strengthen your employability, or allow you to manoeuvre into a programming field you're more interested in.&lt;/p&gt; &lt;p style="font-style: normal"&gt;If you don't keep up a habit of continual learning you will go stale. You'll stagnate. The technological world will pass you by.&lt;/p&gt; &lt;p style="font-style: normal"&gt;This demonstrates a simple learning maxim: &lt;b&gt;Learning. You've either &lt;/b&gt;&lt;i&gt;&lt;b&gt;got&lt;/b&gt;&lt;/i&gt;&lt;b&gt; to, or you &lt;/b&gt;&lt;i&gt;&lt;b&gt;ought&lt;/b&gt;&lt;/i&gt;&lt;b&gt; to.&lt;/b&gt;&lt;/p&gt;&lt;p style="font-style: normal"&gt;&lt;b&gt;What to learn?&lt;/b&gt;&lt;/p&gt; &lt;p&gt;There's a whole world of things you could attempt to pick up. So what should you look at? Donald Rumsfeld summed up this conundrum in a particularly apt way when he made an infamous White House press conference: &lt;i&gt;As we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say, we know there are some things we do not know. But there are also unknown unknowns – the ones we don't know we don't know.&lt;/i&gt;&lt;/p&gt; &lt;p style="font-style: normal"&gt;So what do you pick? Clearly not something you know you know (although learning a topic more deeply, or attempting to consolidate your knowledge on a topic is a valuable task). Instead should you chose something that you &lt;i&gt;know&lt;/i&gt; you don't know, or first learn about &lt;i&gt;what&lt;/i&gt; you don't know in order to chose what to learn? That might make your brain bleed. Thanks a bunch, Rumsfeld.&lt;/p&gt; &lt;p style="font-style: normal"&gt;Perhaps the list below will help. If you are learning for “fun and personal profit” rather than your job leading you to a specific topic, you might consider:&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn a new technology&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;.  For programmers this is the obvious choice. We're fascinated by the  different ways we can make electrons dance, and there's a wide field  here to mine.&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="margin-left: 1.25cm"&gt;&lt;span style="font-style: normal"&gt;You might choose to find out about a new programming language; there is no shortage of new and interesting languages being developed, there are many widely-used languages that you could learn to gain employability-enhancing skills, and there are many interesting existing languages. Consider looking at a language that promotes a different paradigm to your current languages to learn new ways to approach and solve problems – perhaps a functional programming language like Haskell would be a good choice. In their classic 1999 book, the Programmatic Programmers recommended learning one new language every year [1]. It's good advice. You don't have to become an expert, but do get beyond &lt;/span&gt;&lt;i&gt;“Hello, World!”&lt;/i&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; font-style: normal"&gt;You could instead choose to learn a new library or application framework; perhaps an interesting low-level utility or a snazzy new high-level UI toolkit. After all, you can never have enough UI toolkits.&lt;/p&gt; &lt;p style="margin-left: 1.25cm"&gt;&lt;span style="font-style: normal"&gt;Or learn a new software tool. You should never underestimate the usefulness of learning new tools that will make your work more productive and/or more enjoyable. Learn how to use a new text editor, or IDE. Learn a new documentation tool or a test framework. Learn a new build system, an issue tracking system, a source control system (indulge yourself in the new &lt;/span&gt;&lt;i&gt;distributed version control&lt;/i&gt;&lt;span style="font-style: normal"&gt; craze that all the cool kids are going on about), a new operating system, and so on.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-left: 1.25cm; font-style: normal"&gt;Even if you are not going to use the new technology immediately in your “day job”, learning about it will almost certainly help you to use your existing technology in better ways, and will help you to evaluate new technologies when the need arises.&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn new technical  skills&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;.  You might want to learn how to more effectively read code, or write  technical documentation. You could learn how to manage a software  team and climb the greasy career ladder.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn how to work with  people&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;. Yes, this is  tediously “touchy-feely” for most code monkeys. But it can be an  incredibly interesting field, and very useful. You could look at  sociology, or study some management texts. This kind of information  will help you to become a much more capable team worker, and will  enable you to lead teams into directions that you think they should  go in, rather than suffer in silence. It will help you to understand  how people are communicating to you, and how to communicate  effectively with them. You'll discover how to understand your  customer better, and filter their requirements.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn a new problem  domain&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;. Maybe you always  wanted to write mathematical modelling software, or do audio DSP  work. Without any experience or knowledge you'd be unlikely to fall  into a job in a new sphere, so give yourself a head start and begin  to learn about it. Then work out how to get practical, demonstrable  experience.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn how to learn&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;.  Seriously! Perhaps you could invest your time into finding out some  new learning techniques that will help you absorb knowledge more  effectively. Do you find there's a constant barrage of information  you need to tap in to, and it just seems to flow past you?  Investigate ways to seek out, consume, and absorb knowledge. There's  a whole lot more to this than I can cover in these C Vu articles,  after all! Consider learning and practicing new skills such as mind  mapping and speed reading.&lt;/span&gt;&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt;Learn something  completely different&lt;/b&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;.  Or, more interestingly, you may prefer to choose something  completely left-field with no relevance to your day job, and no  obvious software applicability. Learn a new foreign language, a  musical instrument, a new branch of science, art or philosophy. Hey,  even spirituality. Far from being a pointless waste of time, or a  distracting personal hobby, doing this will open your world view  wider. If you're willing to look for the interesting themes and  techniques you will certainly find that it helps to inform the way  you program.&lt;/span&gt;&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;p style="font-style: normal"&gt;Above all, pick something that interests you. Pick something that will benefit you (the act of learning in itself &lt;i&gt;is&lt;/i&gt; a benefit, but choosing something because it will give you fresh usable skills, broadens your insight, or brings you pleasure is a good thing). You will be investing a significant amount of time, so invest wisely!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-8520985683960963757?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/8520985683960963757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=8520985683960963757' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8520985683960963757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/8520985683960963757'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/02/live-to-love-to-learn.html' title='Live to Love to Learn'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_0KMnzNqRq8Y/S2l9RvJVJnI/AAAAAAAACkk/y3A-lHxTezU/s72-c/bagpuss_professor_yaffle.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6216087485946249154</id><published>2010-01-18T12:33:00.000-08:00</published><updated>2010-01-18T12:37:07.634-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><category scheme='http://www.blogger.com/atom/ns#' term='accu'/><title type='text'>Writing: New article in CVu</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://accu.org/content/images/journals/CVu216Cover.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 354px;" src="http://accu.org/content/images/journals/CVu216Cover.png" border="0" alt="" /&gt;&lt;/a&gt;The January issue of &lt;a href="http://www.accu.org/"&gt;ACCU&lt;/a&gt;'s &lt;a href="http://accu.org/index.php/aboutus/aboutjournals"&gt;CVu&lt;/a&gt; magazine is hitting doormats around the world. It contains the latest in my &lt;i&gt;Professionalism in Programming&lt;/i&gt; series - &lt;b&gt;Live To Love To Learn&lt;/b&gt;. This article is the first in a mini-series investigating how we learn as software developers.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-6216087485946249154?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/6216087485946249154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=6216087485946249154' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6216087485946249154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/6216087485946249154'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/01/writing-new-article-in-cvu.html' title='Writing: New article in CVu'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-698375671105786525</id><published>2010-01-07T08:17:00.000-08:00</published><updated>2010-01-07T08:26:50.783-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='writing'/><title type='text'>Writing: 97 Things Every Programmer Should Know</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_0KMnzNqRq8Y/S0YLIFUslbI/AAAAAAAACkc/JBEpYAmEAwI/s1600-h/O+Reilly+Logo.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 145px; height: 134px;" src="http://1.bp.blogspot.com/_0KMnzNqRq8Y/S0YLIFUslbI/AAAAAAAACkc/JBEpYAmEAwI/s200/O+Reilly+Logo.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5424035034710185394" /&gt;&lt;/a&gt;The &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/97_Things_Every_Programmer_Should_Know"&gt;97 Things Every Programmer Should Know&lt;/a&gt; book from &lt;a href="http://oreilly.com/"&gt;O'Reilly&lt;/a&gt;, edited by &lt;a href="http://www.curbralan.com/"&gt;Kevlin Henney&lt;/a&gt; has almost come to completion; it's due for publication next month.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;They've just posted the list of &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Contributions_Appearing_in_the_Book"&gt;contributions appearing in the book&lt;/a&gt;. I'm pleased to say that three of my five submissions are in the list. You'll be able to purchase a paper copy of the following entries:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;You've Gotta Care about the Code (&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/You_Gotta_Care_about_the_Code"&gt;link&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Improve Code by Removing It (&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Improve_Code_by_Removing_It"&gt;link&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Don't Ignore That Error! (&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Ignore_that_Error%21"&gt;link&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7481875957453356650-698375671105786525?l=goodliffe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goodliffe.blogspot.com/feeds/698375671105786525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7481875957453356650&amp;postID=698375671105786525' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/698375671105786525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7481875957453356650/posts/default/698375671105786525'/><link rel='alternate' type='text/html' href='http://goodliffe.blogspot.com/2010/01/writing-97-things-every-programmer.html' title='Writing: 97 Things Every Programmer Should Know'/><author><name>Pete Goodliffe</name><uri>http://www.blogger.com/profile/11084090457826022937</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_0KMnzNqRq8Y/S9dRkiMqTYI/AAAAAAAACl8/zERGN2yIhu4/S220/pete_upper_head.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_0KMnzNqRq8Y/S0YLIFUslbI/AAAAAAAACkc/JBEpYAmEAwI/s72-c/O+Reilly+Logo.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7481875957453356650.post-6205906860128489577</id><published>2010-01-05T01:33:00.000-08:00</published><updated>2010-01-05T02:06:55.898-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iPhone: Application preferences/defaults/settings. With defaults.</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;i&gt;How to extend NSUserDefaults with default values.&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;Time for more iPhone shenanigans. Lots of people have contacted me saying these posts are useful - thanks. As I do more iPhone development I discover things that aren't immediately obvious from the &lt;a href="http://developer.apple.com/iphone/library/"&gt;SDK documentation&lt;/a&gt; (excellent as it is). I'm documenting some of them in my blog partly to find out if I've missed the obvious, and partly to give back to the community - &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt; has certainly pointed me to plenty of other people's blogs with useful answers.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today's installment: &lt;i&gt;application settings&lt;/i&gt;. Or &lt;i&gt;preferences&lt;/i&gt;, if that's what you want to call them. Or &lt;i&gt;settings&lt;/i&gt;, if you prefer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Finding the preferred term&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The iPhone SDK provides a neat API for persisting simple sets of application settings. It's easy enough to find, if you know what it's called when you search for it. &lt;b&gt;Don't&lt;/b&gt; search for &lt;i&gt;preferences&lt;/i&gt;, like I did, or you'll be sent down the Core Foundation dead-end of &lt;a href="http://developer.apple.com/iphone/library/documentation/CoreFoundation/Conceptual/CFPreferences/CFPreferences.html"&gt;Preferences Programming Topics&lt;/a&gt;. This is a rich and fairly heavyweight API for persisting state. But for a simple iPhone app it's overkill.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What you &lt;b&gt;do&lt;/b&gt; need to look for is the Cocoa &lt;a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/occ/cl/NSUserDefaults"&gt;NSUserDefaults&lt;/a&gt; class. That's the puppy you want. It's simple when you know what to look for. This class provides an easy way to read and write fundamental data types (integers, floats, bools, NSStrings, etc).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;What's missing? NSUserDefault's defaults.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Again, perhaps I've missed something. But this class is missing something fairly obvious. It has a simple set of APIs to write values against a given NSString "key" name, e.g. &lt;a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/occ/instm/NSUserDefaults/setInteger:forKey:"&gt;setInteger:forKey:&lt;/a&gt; It has a set of APIs to read those values back for a given NSString "key" name, e.g. &lt;a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/occ/instm/NSUserDefaults/integerForKey:"&gt;integerForKey:&lt;/a&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, there is no way to discover whether or not a setting has been saved yet. This is important since the first time your application is run no preferences have been saved, and you'll need to fall back on a set of well-chosen default values. The NSUserDefaults accessors return "default initialised" values if a key has not been set yet; e.g. &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;0&lt;/span&gt; for integers, &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;0.0&lt;/span&gt; for floats, or a &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;nil&lt;/span&gt; string. You can't always inspect an integer for zero and replace it with a default - sometimes zero is a valid setting value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what can you do about this?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Adding defaults to "defaults"&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We &lt;i&gt;can&lt;/i&gt; add this functionality to NSUserDefaults easily enough. The first trick is to determine whether a value has been stored for a particular key or not. It turns out that, no matter what kind of key has been stored, internally everything can be accessed as an object and the &lt;a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/occ/instm/NSUserDefaults/objectForKey:"&gt;objectForKey:&lt;/a&gt; method returns &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;nil&lt;/span&gt; if no value has been stored.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So you can see whether an integer, for example, has been stored by calling objectForKey: with its key name. The ret
