<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xml:lang="en-US" xml:base="http://www.symphonious.net/wp-atom.php"><title type="text">Symphonious</title> <subtitle type="text">Living in a state of accord.</subtitle> <updated>2013-05-10T08:42:25Z</updated><link rel="alternate" type="text/html" href="http://www.symphonious.net" /> <id>http://www.symphonious.net/feed/atom/</id> <generator uri="http://wordpress.org/" version="3.5.1">WordPress</generator> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/symphonious" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="symphonious" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Ant Dependencies Running Twice]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2013/05/10/ant-dependencies-running-twice/" /> <id>http://www.symphonious.net/?p=1767</id> <updated>2013-05-10T08:42:25Z</updated> <published>2013-05-10T08:42:25Z</published> <category scheme="http://www.symphonious.net" term="Build Systems" /><category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /> <summary type="html"><![CDATA[Most people believe that ant will only ever execute a target once per execution of ant. So if we have targets A, B, C and D, where A depends on B and C and C and D both depend on D. &#60;target name="A" dependencies="B, C"/&#62;&#60;target name="B" dependencies="D"/&#62;&#60;target name="C" dependencies="D"/&#62;&#60;target name="D"/&#62; &#160; When we run &#8216;ant [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2013/05/10/ant-dependencies-running-twice/">&lt;p&gt;Most people believe that ant will only ever execute a target once per execution of ant. So if we have targets A, B, C and D, where A depends on B and C and C and D both depend on D.&lt;/p&gt;&lt;pre&gt;&amp;lt;target name="A" dependencies="B, C"/&amp;gt;&lt;br /&gt;&amp;lt;target name="B" dependencies="D"/&amp;gt;&lt;br /&gt;&amp;lt;target name="C" dependencies="D"/&amp;gt;&lt;br /&gt;&amp;lt;target name="D"/&amp;gt;&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;When we run &amp;#8216;ant A&amp;#8217;, we expect each task to execute once, D first, then B  and C, ending with A. Since there is no dependency between B and C, they may execute in any order, so we might also get D, C, B, A. All pretty straight forward.&lt;/p&gt;&lt;p&gt;Similarly, if we run &amp;#8216;ant B&amp;#8217; we expect (and get) D then B and &amp;#8216;ant C&amp;#8217; gives D then C. Most people expect that if you run &amp;#8216;ant B C&amp;#8217;, the execution path would be D, B, C but that&amp;#8217;s &lt;em&gt;not&lt;/em&gt; what happens. Instead we get D, B, D, C. Each target passed to the command line creates a new dependency chain and runs all targets in that chain.&lt;/p&gt;&lt;p&gt;The other case that catches people out is when using antcall. The antcall task actually sets up essentially a new execution of ant (by default inheriting any properties that have already been set). It never inherits the dependency chain or list of targets that have already been executed. So if our targets were:&lt;/p&gt;&lt;pre&gt;&amp;lt;target name="A"&amp;gt;&lt;br /&gt;  &amp;lt;antcall target="B"/&amp;gt;&lt;br /&gt;  &amp;lt;antcall target="C"/&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&amp;lt;target name="B" dependencies="D"/&amp;gt;&lt;br /&gt;&amp;lt;target name="C" dependencies="D"/&amp;gt;&lt;br /&gt;&amp;lt;target name="D"/&amp;gt;&lt;/pre&gt;&lt;p&gt;Then the execution order for &amp;#8216;ant A&amp;#8217; would be A,D,B,D,C.&lt;/p&gt;&lt;p&gt;The cost of running targets twice is reduced because most ant tasks do nothing if their inputs haven&amp;#8217;t changed (so javac only compiles files once), but for a large project there can still be a significant cost in checking over all the files to determine if anything needs to be done. So whenever possible, use actual dependencies to build up a chain of targets instead of antcall or specifying multiple targets on the command line.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/lHEV8uqr_WQ" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2013/05/10/ant-dependencies-running-twice/#comments" thr:count="1" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2013/05/10/ant-dependencies-running-twice/feed/atom/" thr:count="1" /> <thr:total>1</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Doctypes, Compatibility Modes, Charsets and Fonts]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2013/04/26/doctypes-compatibility-modes-charsets-and-fonts/" /> <id>http://www.symphonious.net/?p=1763</id> <updated>2013-04-26T01:08:22Z</updated> <published>2013-04-26T01:08:22Z</published> <category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /><category scheme="http://www.symphonious.net" term="HTML" /><category scheme="http://www.symphonious.net" term="Internationalisation" /> <summary type="html"><![CDATA[This information is all covered in much more detail elsewhere on the web but for my own future reference, here&#8217;s a primer on doctypes, compatibility modes, charsets and fonts which was required to explain why certain Chinese characters weren&#8217;t showing up in IE8. Of course the best answer is that you need to have the [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2013/04/26/doctypes-compatibility-modes-charsets-and-fonts/">&lt;p&gt;This information is all covered in much more detail elsewhere on the web but for my own future reference, here&amp;#8217;s a primer on doctypes, compatibility modes, charsets and fonts which was required to explain why certain Chinese characters weren&amp;#8217;t showing up in IE8. Of course the best answer is that you need to have the East Asian Font pack installed and then it just works (usually) but this tends to be useful background and saves &amp;#8220;server side&amp;#8221; folks from a number of gotchas.&lt;/p&gt;&lt;h2&gt;Doctypes and Compatibility Modes&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;IE 7 and above has an insane array of compatibility modes which are out to get you. The most common gotcha is that it will use compatibility mode (emulating IE7) if the website is in the &amp;#8220;intranet zone&amp;#8221;. There&amp;#8217;s an option to disable this somewhere in the preferences dialogs.  You wind up in the intranet zone if you&amp;#8217;re accessing a site via any domain name that doesn&amp;#8217;t look like a real one (e.g. http://dog/ is in the intranet zone).&lt;/li&gt;&lt;li&gt;If you can avoid falling into compatibility mode, any pages including the DOCTYPE as &lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&amp;gt;&lt;/code&gt; will render in standards compliant mode (where the world is as sane as it gets in web development). Go with the shorter version unless you have a reason not to.&lt;/li&gt;&lt;li&gt;&lt;a
href="http://hsivonen.iki.fi/doctype/#"&gt;http://hsivonen.iki.fi/doctype/&lt;/a&gt; is the gold standard for information about browser modes.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Character Sets and Fonts&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;If you&amp;#8217;re tracking down problems with foreign languages there are two major categories of problems &amp;#8211; encoding corruption (where characters come out garbled or as ?) and missing glyphs in fonts (where characters come out as little boxes).&lt;/li&gt;&lt;li&gt;Corruption is fixed by specifying the same character encoding everywhere. It is a security issue if any webpage is missing a meta tag defining the character set (smallest variant is &lt;code&gt;&amp;lt;meta charset="UTF-8"&amp;gt;&lt;/code&gt;). It must be the first tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of the document.&lt;/li&gt;&lt;li&gt;Little square boxes mean that either the font currently in use doesn&amp;#8217;t have a glyph for that particular character and the font fallback routine was unable to find any font on the system which supports that character. &lt;/li&gt;&lt;li&gt;Browsers have a default stylesheet which is automatically applied to every page which commonly sets a specific font-family and font-size for text input elements, so adding the style &lt;code&gt;body { font-family: 'Arial Unicode MS' }&lt;/code&gt; may get some Asian characters working in the main content but not in text boxes unless you also add &lt;code&gt;input { font-family: inherit; }&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The security issue mentioned above is that any page which doesn&amp;#8217;t define a character set but includes any form of user supplied content is vulnerable to a cross site scripting injection attack &amp;#8211; even if the user supplied content is escaped properly, because the content may include a character that causes the browser to incorrectly switch to UCS-7 or other weird character sets and drastically change the meaning of the content on the page (hence the user content is no longer correctly escaped). There have been steps taken by modern browsers to remove this risk (including removing support for UCS-7 I believe) but its good practice to specify your charset explicitly anyway.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/O0RqytJMLsA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2013/04/26/doctypes-compatibility-modes-charsets-and-fonts/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2013/04/26/doctypes-compatibility-modes-charsets-and-fonts/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Media Release or Bug Report?]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/12/10/media-release-or-bug-report/" /> <id>http://www.symphonious.net/?p=1751</id> <updated>2012-12-10T23:58:20Z</updated> <published>2012-12-10T23:58:20Z</published> <category scheme="http://www.symphonious.net" term="General" /> <summary type="html"><![CDATA[Ah Apple maps, ever the source of a good sensationalist headline. This time the Victorian police have warned people not to use Apple Maps to get to Mildura. This is definitely a bug with Apple maps, no question it should be and has been fixed.  What&#8217;s interesting though is that the Victorian police thought it [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/12/10/media-release-or-bug-report/">&lt;p&gt;Ah Apple maps, ever the source of a good sensationalist headline. This time the &lt;a
href="http://www.abc.net.au/news/2012-12-10/apple-maps-strands-motorists-looking-for-mildura/4418400"&gt;Victorian police have warned people not to use Apple Maps to get to Mildura&lt;/a&gt;. This is definitely a bug with Apple maps, no question it should be and &lt;a
href="http://www.theregister.co.uk/2012/12/10/apple_maps_ghost_mildura/"&gt;has been fixed&lt;/a&gt;.  What&amp;#8217;s interesting though is that the Victorian police thought it would be easier to attempt to notify every iOS 6 user about the problem via the media and get them to use an alternate mapping application than it would be to call Apple and get them to fix the source data.&lt;/p&gt;&lt;p&gt;Users complaining publicly instead of being constructive and reporting the problem to the manufacturer certainly isn&amp;#8217;t new, but in the age of web services its more self-defeating than ever.  Apple can fix the problem in one place and its fixed for every user, surely the Victorian police have a better way of getting in touch with Apple than through the media?&lt;/p&gt;&lt;p&gt;And lets not even start asking why anyone would blindly follow GPS directions into the Australia bush despite the fact that they are looking at a satellite photo that clearly shows there isn&amp;#8217;t a town there.&lt;/p&gt;&lt;p&gt;The power of user feedback and cloud hosted data was very clear with my recent experience of using Apple maps &amp;#8211; on the way to my destination was some road works which diverted the road and replaced a round about with a set of lights. Despite the fact that the roadworks were actually still in progress, Apple maps gave exactly correct instructions for the new layout. Meanwhile my TomTom GPS will still think there&amp;#8217;s a round about there for up to another year and then require me to pay nearly $100 to get the updated maps. It wasn&amp;#8217;t too long ago that I&amp;#8217;d be looking up a book of maps to get my outdated driving instructions (and then have to memorise it or stop regularly to have another look).&lt;/p&gt;&lt;p&gt;Makes you realise what an incredible time we live in.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/JfIGHYYMd_o" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/12/10/media-release-or-bug-report/#comments" thr:count="1" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/12/10/media-release-or-bug-report/feed/atom/" thr:count="1" /> <thr:total>1</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Brawling on a Plane]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/09/05/brawling-on-a-plane/" /> <id>http://www.symphonious.net/?p=1743</id> <updated>2012-09-05T04:49:07Z</updated> <published>2012-09-05T04:48:30Z</published> <category scheme="http://www.symphonious.net" term="General" /> <summary type="html"><![CDATA[From Straights Times: A flier aboard Sunday&#8217;s Swiss airline flight &#8211; a 57-year-old Chinese man [...] felt disturbed during his meal when the passenger in front of him reclined his chair.[...] &#8220;The older of the two felt disturbed during his dinner. When the younger did not respond to his protests, he hit him on the [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/09/05/brawling-on-a-plane/">&lt;p&gt;From &lt;a
href="http://www.straitstimes.com/breaking-news/world/story/swiss-sky-scuffle-caused-seat-back-altercation-media-20120904"&gt;Straights Times&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;A flier aboard Sunday&amp;#8217;s Swiss airline flight &amp;#8211; a 57-year-old Chinese man [...] felt disturbed during his meal when the passenger in front of him reclined his chair.[...]&lt;/p&gt;&lt;p&gt;&amp;#8220;The older of the two felt disturbed during his dinner. When the younger did not respond to his protests, he hit him on the head with the flat of his hand. It was a real slap,&amp;#8221; said the guide, Ms Valerie Sprenger.&lt;/p&gt;&lt;p&gt;A fight then broke out between the two men, who rolled in the plane&amp;#8217;s aisle. A crew member and a well-muscled passenger restrained the aggressor, bound his hands and placed him at the back of the plane, where he shouted for an hour, the newspaper said.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I can sympathise. In fact I&amp;#8217;d have probably tied up the douchebag who put his seat back during meal service.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/v-xU5wP4-Yc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/09/05/brawling-on-a-plane/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/09/05/brawling-on-a-plane/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Demystifying Doubles: Consistent Inaccuracy]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/08/29/demystifying-doubles-consistent-inaccuracy/" /> <id>http://www.symphonious.net/?p=1733</id> <updated>2012-08-29T03:36:19Z</updated> <published>2012-08-29T03:36:19Z</published> <category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /> <summary type="html"><![CDATA[Of all the data types, double is probably one of the most misunderstood. A huge amount of folk lore has been built up around it to help protect developers from falling into its many pitfalls.  Lately I&#8217;ve done a lot of work replacing usage of BigDecimal with double and learnt a lot about where those [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/08/29/demystifying-doubles-consistent-inaccuracy/">&lt;p&gt;Of all the data types, double is probably one of the most misunderstood. A huge amount of folk lore has been built up around it to help protect developers from falling into its many pitfalls.  Lately I&amp;#8217;ve done a lot of work replacing usage of BigDecimal with double and learnt a lot about where those pitfalls are and how the folk lore can be misleading.&lt;/p&gt;&lt;p&gt;The great challenge with double is that it has a degree of inaccuracy because of the way the number is actually stored.  For example, the number 2983792734924.2293 actually winds up being stored as 2983792734924.2295, a tiny difference but with far reaching consequences. All of the folk lore around doubles is designed to deal with this potential for inaccuracy.&lt;/p&gt;&lt;p&gt;One piece of folk lore is that you should never do a strict comparison of double values (e.g. with == or !=).  Due to the inaccuracy of doubles you should always compare them with a level of tolerance:&lt;/p&gt;&lt;pre&gt;abs(doubleA - doubleB) &amp;lt; tolerance&lt;/pre&gt;&lt;p&gt;It&amp;#8217;s important to realise however, that this inaccuracy isn&amp;#8217;t random, it&amp;#8217;s perfectly consistent and predictable.  The number 2983792734924.2293 &lt;em&gt;always&lt;/em&gt; comes out as 2983792734924.2295.  The same applies if you parse it from a string: parseDouble(&amp;#8220;2983792734924.2293&amp;#8243;) &lt;em&gt;always&lt;/em&gt; comes out as 2983792734924.2295.  As a result the following are consistently true:&lt;/p&gt;&lt;pre&gt;2983792734924.2293 == 2983792734924.2293
parseDouble("2983792734924.2293") == 2983792734924.2293
parseDouble("2983792734924.2293") == parseDouble("2983792734924.2293")&lt;/pre&gt;&lt;p&gt;Introducing tolerance to the comparison can lead to subtle bugs. For example, if we were updating our model with user input we might have something like:&lt;/p&gt;&lt;pre&gt;// In our model:
public void setAmount(double amount) {
  this.amount = amount;
  fireChangeEvent();
}
// In our UI code:
model.setAmount(parseDouble(widget.getText()));&lt;/pre&gt;&lt;p&gt;So far so good, but what if we want to avoid firing the change event if the value hadn&amp;#8217;t really changed?  We might change the model code to:&lt;/p&gt;&lt;pre&gt;public void setAmount(double amount) {
  if (abs(amount - this.amount) &amp;gt; 0.01) {
    this.amount = amount;
    fireChangeEvent();
  }
}&lt;/pre&gt;&lt;p&gt; It follows the double folk lore, but also introduces a bug. Let&amp;#8217;s say the user first enters the amount &amp;#8217;1&amp;#8242;.  Then they change the amount to &amp;#8217;1.001&amp;#8242;.  The second amount is within the tolerance so it&amp;#8217;s not considered an actual change. The user is now looking at a text field that says 1.0001, but the model thinks the value is still 1.   You can make the tolerance smaller but that just means the user has to enter more zeros to trigger the problem.&lt;/p&gt;&lt;p&gt;The right answer is to take advantage of the fact that inaccuracy with doubles is consistent and do the comparison using strict comparison:&lt;/p&gt;&lt;pre&gt;public void setAmount(double amount) {
  if (about != this.amount) {
    this.amount = amount;
    fireChangeEvent();
  }
}&lt;/pre&gt;&lt;p&gt;So when doesn&amp;#8217;t this work? When the two values are calculated in different ways. So:&lt;/p&gt;&lt;pre&gt;&lt;strong&gt;(1491896367462.1147 * 29.837927349242293)&lt;/strong&gt; / 2.3982983923
= 18561116318075.207
1491896367462.1147 * &lt;strong&gt;(29.837927349242293 / 2.3982983923)&lt;/strong&gt;
= 18561116318075.203&lt;/pre&gt;&lt;p&gt;The only difference between the two equations is the order of evaluation &amp;#8211; they &lt;em&gt;should&lt;/em&gt; give the same answer, but because doubles have a degree of inaccuracy the intermediate result is rounded to something that will fit in a double, so the order of evaluation matters because it affects what rounding is done to the intermediate result. Repeating the exact same calculation will always give the exact same result, but if there&amp;#8217;s any chance that the values were calculated in different ways, comparisons must be done with tolerance.&lt;/p&gt;&lt;p&gt;So the folk lore about needing to compare doubles with some tolerance is perfectly valid, good advice, but be aware that it introduces its own inaccuracy which may cause problems. You should consider what the impact of falsely deciding that the values are different vs falsely deciding that the values are the same; which side should you err on?&lt;/p&gt;&lt;p&gt;Sometimes you really do want a strict comparison, even between doubles.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/yTMGReB65Rs" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/08/29/demystifying-doubles-consistent-inaccuracy/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/08/29/demystifying-doubles-consistent-inaccuracy/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[The Myth of Measurable Productivity]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/08/14/the-myth-of-measurable-productivity/" /> <id>http://www.symphonious.net/?p=1730</id> <updated>2012-08-14T01:04:02Z</updated> <published>2012-08-14T01:04:02Z</published> <category scheme="http://www.symphonious.net" term="Productivity" /> <summary type="html"><![CDATA[Farnam Street Blog holds up a coding competition as evidence that: If you want to make your computer programmers and engineers more effective give them “privacy, personal space, control over their physical environments, and freedom from interruption.” The only trouble is, the coding competition is fatally flawed as a measure of normal developer productivity. It&#8217;s [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/08/14/the-myth-of-measurable-productivity/">&lt;p&gt;&lt;a
href="http://www.farnamstreetblog.com/2012/08/increasing-the-productivity-of-computer-programmers-and-engineers/"&gt;Farnam Street Blog holds up a coding competition&lt;/a&gt; as evidence that:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;If you want to make your computer programmers and engineers more effective give them “privacy, personal space, control over their physical environments, and freedom from interruption.”&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The only trouble is, the coding competition is fatally flawed as a measure of normal developer productivity. It&amp;#8217;s setup such that developers work on their own:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Each participant was also assigned a partner from the same company. The partners worked separately, however, without any communication, a feature of the games that turned out to be critical.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So what we actually learn is that if you&amp;#8217;re working by yourself without interacting with anyone else, you will perform better if you don&amp;#8217;t have anyone else around – that&amp;#8217;s not overly surprising.&lt;/p&gt;&lt;p&gt;What happens in the real world however is that a team of developers work together to build software. The research is unable to shed any light on the conditions that benefit that mode of development because it measured something completely different.&lt;/p&gt;&lt;p&gt;And this isn&amp;#8217;t the only example – experiments are constantly being put forward as proving or disproving things that affect productivity, but all of them are fatally flawed in one or both of two key ways:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The activity being performed in the experiment is not the same as what we&amp;#8217;re trying to optimise in the real world.&lt;/li&gt;&lt;li&gt;The way they measure productivity is flawed – usually because it only measures a subset of tasks and attributes that would matter in the real world over the long term.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This shouldn&amp;#8217;t be surprising, any repeated task is best optimised by automating it and removing humans altogether. The remaining work then is dealing with exceptions and is inherently unique (if the same exception kept happening we&amp;#8217;d automate it). More importantly though, the idea that productivity of modern office workers can be measured is a myth. Any metrics you put around productivity are inevitably incomplete and lead to people gaming the system, working only on the measured parts of productivity and to the detriment of anything that isn&amp;#8217;t measured. Measured productivity goes up, but those results aren&amp;#8217;t reflected in the business&amp;#8217;s bottom line – they&amp;#8217;re fictional.&lt;/p&gt;&lt;p&gt;The only viable option is to experiment in your own workplace with your actual work and see what works for you. Use measurements as a guide but also follow some gut feel to account for the unmeasurable elements. Maybe individual offices are best for your workers, doing your work or maybe open plan is. Unless you&amp;#8217;re in the business of completing abstract coding competitions, you probably should work that out for yourself instead of believing the research.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/RlVyHvp6xPs" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/08/14/the-myth-of-measurable-productivity/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/08/14/the-myth-of-measurable-productivity/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Continuous Integration Requires Integrating Continuously]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/07/31/continuous-integration-requires-integrating-continuously/" /> <id>http://www.symphonious.net/?p=1724</id> <updated>2012-07-31T03:39:44Z</updated> <published>2012-07-31T03:31:19Z</published> <category scheme="http://www.symphonious.net" term="Build Systems" /><category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /><category scheme="http://www.symphonious.net" term="XP" /> <summary type="html"><![CDATA[Sarah Goff-Dupont has a post on the Atlassian blog about how Atlassian is using feature branches and still doing continuous integration: In the not-so-recent past, continuous integration in the context of story branching was considered so impractical as to be outright incompatible.  Who has time to manually configure a CI scheme for dozens of active branches [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/07/31/continuous-integration-requires-integrating-continuously/">&lt;p&gt;&lt;a
href="http://blogs.atlassian.com/2012/07/feature-branching-continuous-integrationgit-bamboo/"&gt;Sarah Goff-Dupont has a post on the Atlassian blog&lt;/a&gt; about how Atlassian is using feature branches and still doing continuous integration:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;In the not-so-recent past, continuous integration in the context of story branching was considered so impractical as to be outright incompatible.  Who has time to manually configure a CI scheme for dozens of active branches that will only live a couple of days?  Nobody –that’s who.  And story branch-loving teams would frequently encounter *ahem* “surprises” when merging work onto the main code line –”master”, in Git-speak.  But recent versions of Bamboo have essentially removed that overhead and allowed these two frenenmies to become genuinely harmonious partners in our development lifecycle.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Unfortunately, what Sarah describes is not continuous integration. At best, it&amp;#8217;s regular integration but really it&amp;#8217;s just automated testing. The key principal of continuous integration is that all developers are merging all changes, all the time. That way you see the messy combinatorial effects of concurrent changes and can fix them before you waste a lot of time going down incompatible paths. Anything that reduces the frequency of doing that integration is a step away from continuous integration, regardless of how often automated tests are run.&lt;/p&gt;&lt;p&gt;Let&amp;#8217;s take a look at the basic process they&amp;#8217;re using:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Next, we go into development and testing cycles on the story branch.  The developer is making local commits on her workstation.  [...]  When she reaches a point where she wants to run tests against her work, the developer pushes those local commits up to the repository –still on the story branch, of course.  Bamboo sees that there’s been a change, and starts building the corresponding Plan branch/es.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This is not continuous integration. The developer&amp;#8217;s changes are being kept away from the main team and not integrated while they&amp;#8217;re being developed, while they sitting just in the local git repository and while they&amp;#8217;re in the story branch. Even though Bamboo runs tests against the code, there has been no integration done here. This is just automated testing, not continuous integration.&lt;/p&gt;&lt;p&gt;It seems that Atlassian have discovered this lack of integration and have developed ways of combating it:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;To help find conflict before merging to master, the developer can choose to have Bamboo merge master into her story branch each time she pushes changes to the repo, then run through the CI Plan against the merged code. If the Plan passes, Bamboo will commit the merged code to her branch.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Finally we get some integration happening, but only one way. Since everyone&amp;#8217;s off working on feature branches this is really only integrating with completed stories. All the work going on in parallel on other stories is still not integrated so we have no idea if they will work when combined.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Some teams are taking this workflow a step further and requiring developers to merge to an integration branch during development, before finally merging the completed story to master. This practice ferrets out integration issues even faster. Developers get to mash their in-progress stories together several times a day, rather than waiting until one has merged a completed story to master (which may happen only every 2-3 days) and the other has pulled code from master onto their story branch.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The key lesson here is that if we integrate more often, it&amp;#8217;s easier to ferret out integration issues. It&amp;#8217;s like continuous integration but with the extra fun of managing branches&amp;#8230;&lt;/p&gt;&lt;p&gt;Of course, Atlassian aren&amp;#8217;t alone in the use of feature branches &amp;#8211; it&amp;#8217;s become all the rage since DVCS supposedly made branching cheap and merging painless. Unfortunately while DVCS has eliminated many of the basic mechanics of merging, they haven&amp;#8217;t done anything to reduce the risk of different developers push the codebase in incompatible directions at a structural level. The only way to avoid that is to integrate all changes as often as possible &amp;#8211; that&amp;#8217;s continuous integration.&lt;/p&gt;&lt;p&gt;The only way that feature branching and continuous integration can be at all compatible is if the build system automatically builds and tests every possible combination of branches, all the time &amp;#8211; a massive waste of build system resources. Anything less leaves potential combinations untested until they are finally merged on to master and all the problems are discovered.&lt;/p&gt;&lt;p&gt;Or you know, we could just do continuous integration&amp;#8230;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/VkEXkXxAOHg" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/07/31/continuous-integration-requires-integrating-continuously/#comments" thr:count="1" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/07/31/continuous-integration-requires-integrating-continuously/feed/atom/" thr:count="1" /> <thr:total>1</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Golden Rule of Dependency Management]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/06/19/golden-rule-of-dependency-management/" /> <id>http://www.symphonious.net/?p=1707</id> <updated>2012-06-19T01:54:48Z</updated> <published>2012-06-19T01:54:48Z</published> <category scheme="http://www.symphonious.net" term="Build Systems" /><category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /> <summary type="html"><![CDATA[There&#8217;s a huge amount of complaining and problem solving for various dependency management solutions (particularly maven, but ivy and friends certainly aren&#8217;t immune). Problems range from having optional dependencies unnecessarily included  to having duplicate classes or class conflicts and the solutions tend to be complex and involve a lot of trade offs. All these problems [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/06/19/golden-rule-of-dependency-management/">&lt;p&gt;There&amp;#8217;s a huge amount of complaining and problem solving for various dependency management solutions (particularly maven, but ivy and friends certainly aren&amp;#8217;t immune). Problems range from having optional dependencies unnecessarily included  to having duplicate classes or class conflicts and the solutions tend to be complex and involve a lot of trade offs. All these problems stem from breaking the golden rule of dependency management:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Own your own repository&lt;/strong&gt;&lt;/p&gt;&lt;p
style="padding-left: 30px;"&gt;&amp;#8211; Sutton&amp;#8217;s golden rule of dependency management&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The vast majority, if not all, problems with dependency management comes from having incorrect, conflicting or imprecise meta-data in the repository of dependencies. Maintaining a public repository of perfectly accurate, precise and flexible dependency metadata is next to impossible &amp;#8211; there are just too many libraries and the interrelationships are too complex. Fortunately, even extremely large companies only use a tiny subset of these libraries. With the scope reduced it&amp;#8217;s much easier to ensure the metadata is correct and consistent.&lt;/p&gt;&lt;p&gt;Any time you need to introduce a new dependency, very carefully review the metadata associated it and correct any errors or inconsistencies before importing it into the repository you administer and control.&lt;/p&gt;&lt;p&gt;You don&amp;#8217;t let anyone commit to your source code repository, don&amp;#8217;t let anyone commit to your dependency repository either.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/aIcJI5VnV28" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/06/19/golden-rule-of-dependency-management/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/06/19/golden-rule-of-dependency-management/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Minimise Configuration]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/06/05/minimise-configuration/" /> <id>http://www.symphonious.net/?p=1701</id> <updated>2012-06-05T05:27:47Z</updated> <published>2012-06-05T05:27:47Z</published> <category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /> <summary type="html"><![CDATA[Having configuration differences between development and production is largely unavoidable, but it&#8217;s important to keep the number of differences to a minimum to avoid unexpected bugs appearing in production that don&#8217;t occur in development mode. More than that though, it&#8217;s important to minimise configuration. Configuration is Code Often things are put in configuration files so [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/06/05/minimise-configuration/">&lt;p&gt;Having configuration differences between development and production is largely unavoidable, but it&amp;#8217;s important to keep the number of differences to a minimum to avoid unexpected bugs appearing in production that don&amp;#8217;t occur in development mode. More than that though, it&amp;#8217;s important to minimise configuration.&lt;/p&gt;&lt;h2&gt;Configuration is Code&lt;/h2&gt;&lt;p&gt;Often things are put in configuration files so that they are easy to change later, often without a full redeployment of the software, but that also implies it can be changed without going through the full testing that a release would usually be subject to. It&amp;#8217;s rare for automated tests to cover more than one possible setting for these configuration options so changing them in production is equivalent to deploying completely untested code. What&amp;#8217;s worse, it&amp;#8217;s quick and easy to do with no audit trail of what happened and when.&lt;/p&gt;&lt;p&gt;These settings should be avoided altogether and the values hard coded in the built product and deployed along with it.  That may be as simple as embedding the existing config file in the built software &amp;#8211; the aim isn&amp;#8217;t necessarily to mix configuration and code, only to remove the options to change the configuration outside of the normal development and deployment process.&lt;/p&gt;&lt;p&gt;For settings that are designed to be changed by the user as a normal part of using the software, make sure that the full range of values is tested, just like any other system input should be.&lt;/p&gt;&lt;h2&gt;Soft Coding&lt;/h2&gt;&lt;p&gt;The most extreme form of configuration is &amp;#8220;soft coding&amp;#8221; where the system becomes so configurable its essentially a poor-man&amp;#8217;s programming language. &lt;a
href="http://thedailywtf.com/Articles/Soft_Coding.aspx"&gt;The Daily WTF has an excellent explanation of soft coding and how even the best of intentions can lead to it.&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Dealing with Production Problems&lt;/h2&gt;&lt;p&gt;One of the biggest reason people make options configurable by administrators is so that they can quickly reconfigure things to resolve issues in production. Sadly, the worst time you could be making untested changes in production is when things are already behaving in unexpected ways. Instead, make the build, test and deployment process for your software so fast and so seamless that you can make the change in code, fully test it and get it out to production fast enough to resolve the issue. Doing so isn&amp;#8217;t easy, but it delivers immense value beyond just resolving production issues.  It allows you to more reliably and more rapidly deploy any code change into production. That means spending less time wrangling releases and more time improving the product.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/UcnS984DOdE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/06/05/minimise-configuration/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/06/05/minimise-configuration/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> <entry> <author> <name>Adrian Sutton</name> <uri>http://www.symphonious.net</uri> </author><title type="html"><![CDATA[Default to Development Settings]]></title><link rel="alternate" type="text/html" href="http://www.symphonious.net/2012/05/28/default-to-development-settings/" /> <id>http://www.symphonious.net/?p=1698</id> <updated>2012-05-28T06:17:19Z</updated> <published>2012-05-28T05:55:00Z</published> <category scheme="http://www.symphonious.net" term="Code and Geek Stuff" /><category scheme="http://www.symphonious.net" term="System Administration" /> <summary type="html"><![CDATA[Most systems have multiple configuration profiles &#8211; one for production, one for development and often other profiles for staging, testing etc.  Minimising differences between these configurations is critical but there are inevitably some things that just have to be different. This then leaves the question, what should the default settings be? There are three main [...]]]></summary> <content type="html" xml:base="http://www.symphonious.net/2012/05/28/default-to-development-settings/">&lt;p&gt;Most systems have multiple configuration profiles &amp;#8211; one for production, one for development and often other profiles for staging, testing etc.  Minimising differences between these configurations is critical but there are inevitably some things that just have to be different. This then leaves the question, what should the default settings be?&lt;/p&gt;&lt;p&gt;There are three main options:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Default to production values&lt;/li&gt;&lt;li&gt;Default to development values&lt;/li&gt;&lt;li&gt;Refuse to start unless an environment has been explicitly chosen&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;My preference is to default to development values. Why?&lt;/p&gt;&lt;p&gt;Development values should be &amp;#8220;safe&amp;#8221; in terms of any external integrations. So a developer isn&amp;#8217;t going to accidentally start sending real buy or sell instructions to your stock broker.&lt;/p&gt;&lt;p&gt;There are more developers than production systems. If you default to production systems, every developer needs to remember to switch to development mode whenever they setup a new checkout. Defaulting to development mode means it just works for the most common case.&lt;/p&gt;&lt;p&gt;Checking authentication credentials for external systems into your source control system is generally considered a bad security practice, so the default values are unlikely to actually work in production anyway.&lt;/p&gt;&lt;p&gt;The down side with defaulting to development is it&amp;#8217;s possible to accidentally deploy to production with development values causing an outage. This can be pretty easily prevented with automated deployments or using tools like RPM where files can be marked as config and thus avoid overwriting them when doing updates.&lt;/p&gt;&lt;p&gt;Refusing to start is the worst of all worlds &amp;#8211; every developer has to specify a configuration mode &lt;em&gt;and&lt;/em&gt; you still risk production outages by not specifying a mode.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/symphonious/~4/qlUbIf35lFM" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.symphonious.net/2012/05/28/default-to-development-settings/#comments" thr:count="0" /><link rel="replies" type="application/atom+xml" href="http://www.symphonious.net/2012/05/28/default-to-development-settings/feed/atom/" thr:count="0" /> <thr:total>0</thr:total> </entry> </feed><!-- Dynamic page generated in 0.467 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-12 07:40:55 --><!-- Compression = gzip -->
