<?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:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Atomic Spin - Home</title>
  <id>tag:spin.atomicobject.com,2010:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  
  <link href="http://spin.atomicobject.com/" rel="alternate" type="text/html" />
  <updated>2010-07-29T19:24:45Z</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/atomic_spin" /><feedburner:info uri="atomic_spin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>42.955944</geo:lat><geo:long>-85.644983</geo:long><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/atomic_spin" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fatomic_spin" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Marissa Christy</name>
      <uri>http://www.atomicobject.com/pages/Marissa+Christy</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-29:46725</id>
    <published>2010-07-29T18:11:00Z</published>
    <updated>2010-07-29T19:24:45Z</updated>
    <category term="Business of Software" />
    <category term="Professional Development" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/s9DIDtJTOrA/a-new-ao-library" rel="alternate" type="text/html" />
    <title>A New AO Library </title>
<content type="html">
            &lt;p&gt;Atomic Object has always embraced the scholarly side of Computer Science. We encourage conference attendance and participation,  writing for trade journals, and sharing technical expertise through our company blog. During the lunch hour, employees frequently give “brown bag” talks—presentations on a particular technology, problem, or methodology. When they’re not developing software at work, employees are expected to develop professionally, that is, to investigate new technologies and hone their skills.  And before founding Atomic, our president, Carl Erickson, was a professor of Computer Science at &lt;a href="http://gvsu.edu"&gt;&lt;span class="caps"&gt;GVSU&lt;/span&gt;&lt;/a&gt;, making it safe to say that AO’s had these scholastic sympathies from the very beginning.&lt;/p&gt;


	&lt;p&gt;Another symbol of our academic bent is our rather large library – yes, a physical library – of books, made available for use by Atomic employees. We have books on, to name a few, operating systems, system administration, visual design principles, agile methodologies, project management, and oh so many programming languages. In fact, our burgeoning library was outgrowing its space on our &lt;span class="caps"&gt;IKEA&lt;/span&gt; shelving, not designed to withstand the weight of such CS tomes as Knuth’s 3 volume set, &lt;a href="http://www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1280415732&amp;sr=8-1"&gt;The Art of Computer Programming&lt;/a&gt;. Also, the classification system was getting muddled, with newer books horizontally stacked atop older books being the only recognizable taxonomy.&lt;/p&gt;


	&lt;p&gt;And so we needed a new solution. Luckily for us, our Business Manager, &lt;a href="http://atomicobject.com/pages/Mary+O'neill"&gt;Mary&lt;/a&gt;, has a background in commercial interior design and was able to use her skills in drafting to design an entire wall of built-in bookcases. With all the &lt;a href="http://spin.atomicobject.com/2010/02/08/information-radiators"&gt;information radiators&lt;/a&gt; around the office, wall space has become an increasingly scarce commodity, so the final design left an opening for the whiteboard currently occupying the wall in addition to ample shelving. [Nerdy art history sidebar: The design references the facade of our building, symmetrical, with a large entablature supported by two engaged pilasters.] Our friend Ken Idema (of &lt;a href="http://www.kenidemabuilders.com/"&gt;Ken Idema Builders&lt;/a&gt;) created the library shelves, continuing his habit of beautifying our space.&lt;/p&gt;


	&lt;p&gt;The lot of re-”cataloging” our books – unfortunately – fell on me. Lacking a technical background, you can imagine how mind-boggling it must have been to rely on reason alone to organize books on  C, C++, C# and Objective-C. (Let alone Cocoon?)&lt;/p&gt;


	&lt;p&gt;With the help of a friend, the oversight of an intern, and a little sweat equity, we have made the library easier to navigate (usable) and gave it ample room for growth (scalable).&lt;/p&gt;


	&lt;p&gt;Through the process of moving and organizing the books, I became rather fond of these books so foreign to &lt;a href="http://www.calvin.edu/academic/art/"&gt;my own education&lt;/a&gt; – or were they? I couldn’t help but notice the prejudice for modern art cover designs among the books. They featured works by Pete Mondrain, Wassily Kandinsky, M.C. Escher, Georges Seurat (the connection of pointillism to pixels is a given), to name a few.&lt;/p&gt;


	&lt;p&gt;So please – admire with me the final product – an homage to order, learning, and to &lt;a href="http://www.atomicobject.com/pages/Software+as+a+Craft"&gt;craftsmanship&lt;/a&gt; (of all kinds).&lt;/p&gt;


	&lt;p&gt;&lt;/br&gt;&lt;/p&gt;


&lt;div&gt;
&lt;img title="Atomic Object's Library" src="http://farm5.static.flickr.com/4083/4841334326_ce70a4b95d.jpg" alt="Atomic Object's Library" /&gt;

	&lt;p&gt;&lt;img title="Typography Book" src="http://farm5.static.flickr.com/4104/4840515695_857b0284da.jpg" alt="Atomic Object Typography Book" /&gt;
&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=s9DIDtJTOrA:MKoUe9fdVDw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=s9DIDtJTOrA:MKoUe9fdVDw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=s9DIDtJTOrA:MKoUe9fdVDw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=s9DIDtJTOrA:MKoUe9fdVDw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=s9DIDtJTOrA:MKoUe9fdVDw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=s9DIDtJTOrA:MKoUe9fdVDw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=s9DIDtJTOrA:MKoUe9fdVDw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=s9DIDtJTOrA:MKoUe9fdVDw:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/s9DIDtJTOrA" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/29/a-new-ao-library</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Dustin Tinney</name>
      <uri>http://www.atomicobject.com/pages/Dustin+Tinney</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-28:46674</id>
    <published>2010-07-28T19:52:00Z</published>
    <updated>2010-07-28T20:03:36Z</updated>
    <category term="Books, Papers, Articles &amp; Links" />
    <category term="UI/UX" />
    <category term="User Experience" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/CNYM9aLFiQE/simplicity-is-not-the-answer" rel="alternate" type="text/html" />
    <title>Simplicity is Not the Answer</title>
<content type="html">
            &lt;p&gt;Don Norman writes about why &lt;a href="http://bit.ly/9Ng1lu"&gt;Simplicity Is Not the Answer&lt;/a&gt;&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;If my cellphone only had one button it certainly would be simple, but, umm, all I could do would be to turn it on or off: I wouldn’t be able to make a phone call. Is the piano too complex because it has 88 keys and three pedals? Should we simplify it? Surely no piece of music uses all of those keys. The cry for simplicity misses the point.&lt;/p&gt;
	&lt;/blockquote&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=CNYM9aLFiQE:JmFG4B_tKl8:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=CNYM9aLFiQE:JmFG4B_tKl8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=CNYM9aLFiQE:JmFG4B_tKl8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=CNYM9aLFiQE:JmFG4B_tKl8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=CNYM9aLFiQE:JmFG4B_tKl8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=CNYM9aLFiQE:JmFG4B_tKl8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=CNYM9aLFiQE:JmFG4B_tKl8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=CNYM9aLFiQE:JmFG4B_tKl8:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/CNYM9aLFiQE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/28/simplicity-is-not-the-answer</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Justin Kulesza</name>
      <uri>http://www.atomicobject.com/pages/Justin+Kulesza</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-28:46421</id>
    <published>2010-07-28T13:29:00Z</published>
    <updated>2010-07-28T17:12:24Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/bSP2XAxCEng/converting-to-utf-16-ucs-2-with-iconv" rel="alternate" type="text/html" />
    <title>Converting to UTF-16 and UCS-2 with Iconv</title>
<content type="html">
            &lt;p&gt;Recently the &lt;a href="http://www.smetoolkit.org"&gt;SME Toolkit&lt;/a&gt;, a project sponsored by the &lt;a href="http://www.ifc.org"&gt;International Finance Corporation&lt;/a&gt; (a member of the &lt;a href="http://www.worldbankgroup.org"&gt;World Bank Group&lt;/a&gt;), was attempting to send international SMS messages.  This gave everyone on the team a good lesson in character encodings.  We had previously utilized &lt;a href="http://en.wikipedia.org/wiki/UTF-16"&gt;UTF-16&lt;/a&gt; to send our SMS messages to the telephone company which we were partnering with for international messages.  However, when we tried to send our SMS messages to a telco in Sri Lanka, they requested that we use a predecessor to UTF-16 known as &lt;a href="http://en.wikipedia.org/wiki/UCS-2"&gt;UCS-2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since we knew UTF-16 and UCS-2 were very similar, we didn't anticipate any problems.  (The major differences between UTF-16 and UCS-2 occur for characters which we were not concerned about).  We dutifully converted our messages to UCS-2, and sent them off -- only to find that no one in Sri Lanka could read them.  They showed up as gibberish on our testers phones, or were not even accepted by the telco's SMS gateway -- being rejected as malformed. What had happened?  UTF-16 and UCS-2 are supposed to be similar, right?  Well, they are similar.  Unfortunately, character encodings are widely misunderstood, and implementations differ widely.  A particular program may handle even similar encodings in very different fashions.&lt;/p&gt;
&lt;p&gt;After discovering we were sending nonsense messages, we decided to examine the logs.  To our surprise, we discovered that not only was the telco receiving messages from us without a byte order mark (&lt;a href="http://en.wikipedia.org/wiki/Byte_order_mark"&gt;BOM&lt;/a&gt;), they were receiving our messages as if they were &lt;a href="http://en.wikipedia.org/wiki/Endianness"&gt;little endian&lt;/a&gt; -- with the least significant byte first!  This was a major surprise to us as we had anticipated that our messages would be sent just like UTF-16: with a BOM so that the actual byte order was not an issue.&lt;/p&gt;
&lt;p&gt;It turns out that there is a snag with the Unix &lt;a href="http://en.wikipedia.org/wiki/Iconv"&gt;Iconv&lt;/a&gt; library (libiconv) on certain systems depending on the system's endianness.  We converted our messages in Ruby using the Iconv library which utilizes the local system's library.  It seems that Iconv silently omits the BOM when converting messages to UCS-2, but does include the BOM when converting messages to UTF-16.  This is surprising (and somewhat concerning), as the UCS-2 encoding is byte order sensitive, just like UTF-16.  In addition, the default byte order is supposed to be big endian.  Unfortunately, we couldn't find a good explanation for this behavior, so we simply adapted.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We recognized the problem when doing a trial a conversion with the Iconv library in IRB from UTF-8 to UCS-2:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On a local system:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;
irb(main):001:0&gt; Iconv.conv("UCS-2","UTF-8","a")&lt;br /&gt;
=&gt; "\000a"
&lt;/code&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On our production server:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;
irb(main):001:0&gt; Iconv.conv("UCS-2","UTF-8","a")&lt;br /&gt;
=&gt; "a\000"
&lt;/code&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;For comparison, the Iconv library in IRB does include the BOM when converting from UTF-8 to UTF-16:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On a local system:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;
irb(main):002:0&gt; Iconv.conv("UTF-16","UTF-8","a")&lt;br /&gt;
=&gt; "\376\377\000a"
&lt;/code&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On our production server:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;
irb(main):002:0&gt; Iconv.conv("UTF-16","UTF-8","a")&lt;br /&gt;
=&gt; "\377\376a\000"
&lt;/code&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this type of behavior in Iconv may be intended, it certainly is confusing and unhelpful since it isn't documented.  I could find no information regarding intended behavior of Iconv other than the odd forum post which referred to UCS-2 conversion in Iconv being "broken."  The UCS-2 standard allows a BOM, but it can be omitted.  This wouldn't be such a problem if Iconv always converted into the same variant of UCS-2 rather than switching between big endian and little endian depending on the current architecture.&lt;/p&gt;
&lt;p&gt;Somewhat cryptically, Ruby outputs the contents of a byte as the ASCII equivalent, or the octal value if that will not be visible.  So, in our case, the character "a"  gets displayed as "\000a" on one machine, and "a\000" on the other machine.  This is endianness in action.  One machine is clearly putting the most significant byte first, the other the least significant byte first.  This is a problem since the UCS-2 standard specifies that in the absence of a BOM, the bytes should be interpreted as big endian.&lt;/p&gt;
&lt;p&gt;Instead of receiving the character "a" (&lt;a href="http://en.wikipedia.org/wiki/Unicode"&gt;Unicode&lt;/a&gt;: 0x00 0x61), the telco would have received the character "愀" (Unicode: 0x61 0x00) -- a Han ideograph.  No wonder the Sri Lankan phones couldn't display it!&lt;/p&gt;
&lt;p&gt;Discussion with the telco in Sri Lanka revealed what we had come to suspect: they wanted the UCS-2 messages to be big endian.  I suppose it would have been helpful if they would have specified this in the first place, but they might have (rightfully) expected that we would use the default -- big endian.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In order to force our server to use big endian, we specified it explicitly when doing our conversions with Iconv:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On our production server:&lt;/strong&gt;&lt;br /&gt;
&lt;code&gt;
irb(main):0003:0&gt; Iconv.conv("UCS-2BE","UTF-8","a")&lt;br /&gt;
=&gt; "\000a"
&lt;/code&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This effectively solved our problem.  No longer did we have to worry about whether our machine was representing characters differently than the telco's machines -- we specified exactly which encoding and byte order to use.  Sadly, documentation of character encoding issues like this is very sparse and we had to do much research and testing ourselves before coming to this conclusion.&lt;/p&gt;
&lt;h2&gt;Further reading:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An excellent introduction to character encodings, by Joel Spolsky:&lt;br /&gt;
&lt;a href="http://www.joelonsoftware.com/articles/Unicode.html"&gt;The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Unicode standard and associated documentation, by the The Unicode Consortium:&lt;br /&gt;
&lt;a href="http://www.unicode.org/standard/WhatIsUnicode.html"&gt;What is Unicode?&lt;/a&gt;&lt;br /&gt;
(Be careful not to read the full standard -- you &lt;em&gt;will&lt;/em&gt; fall asleep.)
&lt;/li&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=bSP2XAxCEng:PfQ9JANEMuE:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=bSP2XAxCEng:PfQ9JANEMuE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=bSP2XAxCEng:PfQ9JANEMuE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=bSP2XAxCEng:PfQ9JANEMuE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=bSP2XAxCEng:PfQ9JANEMuE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=bSP2XAxCEng:PfQ9JANEMuE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=bSP2XAxCEng:PfQ9JANEMuE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=bSP2XAxCEng:PfQ9JANEMuE:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/bSP2XAxCEng" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/28/converting-to-utf-16-ucs-2-with-iconv</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Drew Colthorp</name>
      <uri>http://www.atomicobject.com/pages/Drew+Colthorp</uri>
    </author>
    <contributor>
      <name>Karlin Fox</name>
      <uri>http://www.atomicobject.com/pages/Karlin+Fox</uri>
    </contributor>
    <id>tag:spin.atomicobject.com,2010-07-27:46317</id>
    <published>2010-07-27T13:18:00Z</published>
    <updated>2010-07-27T13:39:52Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/lE_SvMdni-4/polyglot-persistence-and-rails-3" rel="alternate" type="text/html" />
    <title>Polyglot Persistence and Rails 3</title>
<content type="html">
            &lt;p&gt;Developers at Atomic really value using the right tool for the job. That’s why we occasionally get together outside of work to learn and teach new technologies. Keeping up with the latest tools and approaches is easiest with a group of friends and a couple of &lt;a href="http://www.foundersbrewing.com"&gt;beers&lt;/a&gt;, so last month we organized an after-work exploration of some non-relational databases. The experience got us thinking about persistence in the new world of NoSQL and Rails 3.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt; agnosticism has recently become a core principle of Rails. An &lt;span class="caps"&gt;ORM&lt;/span&gt; is a mapping between objects and relations, but in Rails 3 this can mean more than just alternative syntax for the same relational operations. Now your models can be persisted in an entirely different data storage paradigm, or a combination of new and old. That means more flexibility to think about your application outside of tables and columns, without sacrificing the familiarity and convention of Rails.&lt;/p&gt;


	&lt;p&gt;As with any newcomer to your application stack, you’ll need time to get familiar with  performance and operational characteristics of a NoSQL database, so don’t put all your persistence eggs in the same basket. Our own approach to integrating these new tools is to take baby steps: apply them where their novel features can shine instead of completely throwing out the standard approach. Use MongoDB for the part of your app that needs a more flexible schema, and keep using Postgres for payment processing, where its transactions and durability keep it in the game.&lt;/p&gt;


	&lt;p&gt;This integrated approach to using multiple data stores is often called “polyglot persistence”. It’s more than just a transitional step towards replacing your database. It means letting you always use the right tool for the job and not falling into a monocultural mindset. The salient conclusion of our recent foray was that each database makes its own tradeoffs. Web apps wear MongoDB well, but it’s not best for critical transactions involving multiple records. Neo4j doesn’t pretend to be a whole-app data store, but might be the best way to query your huge social network. Redis is extremely flexible but it may take more work to solve your common problems: it’s more of a general-purpose toolkit than an out-of-box solution. &lt;span class="caps"&gt;SQL&lt;/span&gt; databases are still useful and mature tools for many problems, especially where transactions are necessary.&lt;/p&gt;


	&lt;p&gt;The new directions in Rails 3 aren’t just about letting you replace ActiveRecord. They entirely decouple the &lt;span class="caps"&gt;ORM&lt;/span&gt; from the core framework, so you can pick the right tools and have them all coexist in harmony. But to fully realize the dream, the greater Rails’ gem ecosystem needs to shift a bit. On a recent project combining Rails 3, ActiveRecord, and &lt;a href="http://mongoid.org/"&gt;Mongoid&lt;/a&gt;, we’ve noticed a few common problems.&lt;/p&gt;


	&lt;p&gt;The first is gems too targeted toward ActiveRecord. Mongoid is extremely similar to Rails’ default &lt;span class="caps"&gt;ORM&lt;/span&gt;, but some gems focus so much on providing magic that they lack the configurability necessary to adapt to new storage paradigms. Too much magic without configurability can lead to too strong a tie to ActiveRecord. Rails 3 offers the convenience of convention without sacrificing the flexibility of configuration, which is a good model to follow.&lt;/p&gt;


	&lt;p&gt;Another problem we’ve seen is gems that try to accommodate multiple ORMs, but assume only one will be present. This is an acknowledged limitation of &lt;a href="http://github.com/bmabey/database_cleaner"&gt;Database Cleaner&lt;/a&gt;, which would otherwise make fixture cleanup in a multiple database scenario easy and straightforward.&lt;/p&gt;


	&lt;p&gt;Once we got through these issues, working in a our polyglot rails application has been a fantastic experience. MongoDB has already paid off by allowing us to embed one document inside another for a surprisingly elegant solution to a modeling problem. At the same time using ActiveRecord for user accounts has let us continue using &lt;a href="http://github.com/thoughtbot/clearance"&gt;Clearance&lt;/a&gt; for breezy authentication and reserved the option for transactional payment processing.&lt;/p&gt;


	&lt;p&gt;This is really exciting.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=lE_SvMdni-4:cdIqb41T9io:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=lE_SvMdni-4:cdIqb41T9io:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=lE_SvMdni-4:cdIqb41T9io:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=lE_SvMdni-4:cdIqb41T9io:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=lE_SvMdni-4:cdIqb41T9io:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=lE_SvMdni-4:cdIqb41T9io:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=lE_SvMdni-4:cdIqb41T9io:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=lE_SvMdni-4:cdIqb41T9io:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/lE_SvMdni-4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/27/polyglot-persistence-and-rails-3</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Melissa Bugai</name>
      <uri>http://www.atomicobject.com/pages/Melissa+Bugai</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-21:46294</id>
    <published>2010-07-21T15:45:00Z</published>
    <updated>2010-07-21T15:47:01Z</updated>
    <category term="Books, Papers, Articles &amp; Links" />
    <category term="UI/UX" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/9sTdztyb__Q/how-to-talk-about-user-experience-with-clients" rel="alternate" type="text/html" />
    <title>How to Talk About User Experience With Clients</title>
<content type="html">
            &lt;p&gt;The language that we as UX practitioners use to talk to each other isn’t always useful to our customers. Author David Sherwin suggests having a cheat sheet for talking to clients about the business value of UX and shares his own cheatsheet as a guide.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.alistapart.com/articles/can-you-say-that-in-english-explaining-ux-research-to-clients/"&gt;Can You Say That in English? Explaining UX Research to Clients&lt;/a&gt;&lt;/p&gt;


&lt;blockquote&gt;
As much as I’d like to tell my clients to go read &lt;em&gt;The Elements of User Experience&lt;/em&gt; and call me back when they’re done, that won’t cut it in a professional services environment. The whole team needs a common language and a philosophy that’s easy to grok.
&lt;/blockquote&gt;

&lt;blockquote&gt;
I created a cheat sheet to help you pitch UX research using plain, client-friendly language that focuses on the business value of each exercise.
&lt;/blockquote&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=9sTdztyb__Q:h2WYOwZmY8A:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=9sTdztyb__Q:h2WYOwZmY8A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=9sTdztyb__Q:h2WYOwZmY8A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=9sTdztyb__Q:h2WYOwZmY8A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=9sTdztyb__Q:h2WYOwZmY8A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=9sTdztyb__Q:h2WYOwZmY8A:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=9sTdztyb__Q:h2WYOwZmY8A:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=9sTdztyb__Q:h2WYOwZmY8A:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/9sTdztyb__Q" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/21/how-to-talk-about-user-experience-with-clients</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Daniel Hast</name>
      <uri>http://www.atomicobject.com/pages/Daniel+Hast</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-19:45298</id>
    <published>2010-07-19T13:31:00Z</published>
    <updated>2010-07-19T13:32:49Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/y13pAXA08sI/programming-for-wikipedia" rel="alternate" type="text/html" />
    <title>Programming for Wikipedia</title>
<content type="html">
            &lt;p&gt;As one of the top ten sites on the Internet, &lt;a href="http://wikipedia.org"&gt;Wikipedia&lt;/a&gt; is well known both for being the largest encyclopedia in the world and for having a highly unconventional editorial process.  What far fewer people know about is the community of editors that has built up around the project.&lt;/p&gt;


	&lt;p&gt;While occasional, often anonymous contributions comprise the majority of article content on Wikipedia, tens of thousands of regular editors &amp;mdash; the core community &amp;mdash; deal with such internal tasks as article cleanup, coordinating efforts, fixing bad edits, and managing the site.  I have edited Wikipedia since 2006 (though with varying degrees of activity), and it is quite an interesting and useful experience.  Wikipedia’s organizational structure is extremely decentralized out of necessity, but there are numerous procedures governed mostly by convention.  There is no central authority; the Wikimedia Foundation, while officially controlling the project, rarely goes beyond facilitating volunteer editors’ work.&lt;/p&gt;


	&lt;p&gt;I mostly chose to involve myself with cleaning up existing articles, monitoring new edits, and writing editing tools.  Wikipedia allows users to add scripts written in JavaScript to their account in a manner similar to &lt;a href="http://en.wikipedia.org/wiki/Greasemonkey"&gt;Greasemonkey&lt;/a&gt;.  There are a number of these scripts, ranging widely in purpose: modifying the interface, automating common tasks, and giving easy access to technical information are some of the most common uses.&lt;/p&gt;


	&lt;p&gt;When I first started editing, I had little knowledge of programming.  Some of my first experience with programming came as a result of installing a Wikipedia script that gives information about an article’s quality while viewing the article.  (This isn’t as fancy as it sounds; Wikipedia has a process for assessing articles, e.g. as “B-class,” “C-class,” etc., and most articles have this information readily available but not very visible.)  It was quite useful, but it had bugs, and the script’s original editor had stopped working on it.  Since all user contributions to Wikipedia can be freely modified, I copied the script and tried to fix the problems with it, learning JavaScript in the process.&lt;/p&gt;


	&lt;p&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/30/wikipedia_script.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;The script was quite basic and only used by a few people when I started working on it.  Over time, I ended up rewriting most of it and adding features, mostly for my own use, but every now and then at another editor’s request.  It’s now a pretty useful tool, providing a summary of an article’s passage through various editorial processes, as well as the ratings given to it by groups of editors dealing with specific topics; it’s gained more users, too, though there isn’t an easy way to tell how many.&lt;/p&gt;


	&lt;p&gt;To most people, Wikipedia is simply a useful resource, but to those who spend some time contributing to it, Wikipedia is a place to both find information and improve your own knowledge and skills by working on it.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=y13pAXA08sI:IYPVYXc68K4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=y13pAXA08sI:IYPVYXc68K4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=y13pAXA08sI:IYPVYXc68K4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=y13pAXA08sI:IYPVYXc68K4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=y13pAXA08sI:IYPVYXc68K4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=y13pAXA08sI:IYPVYXc68K4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=y13pAXA08sI:IYPVYXc68K4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=y13pAXA08sI:IYPVYXc68K4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/y13pAXA08sI" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/19/programming-for-wikipedia</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Carl Erickson</name>
      <uri>http://www.atomicobject.com/pages/Carl+Erickson</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-16:46015</id>
    <published>2010-07-16T14:55:00Z</published>
    <updated>2010-07-22T17:37:47Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/-RcHG4tAFH0/grand-rapids-agile-ux-retreat" rel="alternate" type="text/html" />
    <title>Grand Rapids Agile UX Retreat </title>
<content type="html">
            &lt;p&gt;&lt;a href="http://atomicobject.com/"&gt;Atomic Object&lt;/a&gt; hosted a second Agile UX Retreat in Grand Rapids, Michigan over the weekend of July 10-11, 2010. The first retreat was hosted earlier this year by &lt;a href="http://www.cooper.com/"&gt;Cooper&lt;/a&gt; in San Francisco. The group was initially brought together by &lt;a href="http://www.andersramsay.com/"&gt;Anders Ramsay&lt;/a&gt; and &lt;a href="http://www.linkedin.com/pub/lane-halley/0/17/358"&gt;Lane Halley&lt;/a&gt; to focus on creating a new blend of user experience (UX) practices and agile software development practices.&lt;/p&gt;


	&lt;p&gt;I’ll happily admit to having more than one “pinch me” moments over the weekend as I looked around the room at the thought leaders represented in the participants who’d come to Grand Rapids from all across the country. [Side note: in our experience with bringing software professionals from major metropolises to Grand Rapids, the near universal response is compliments and utter surprise on how much GR has going on and how attractive a city it is. If GR was a company, it would desperately need a marketing strategy.] I haven’t had my brain stretched this much for some time. On the other hand, I don’t know what else I should have expected considering the talent and personalities in the room, the fact that we represented distinct disciplines each with its own history, terminology, and perspective, and the incredibly ambitious nature of the work we’re doing. Potentially so ambitious, in fact, that the idea that what we were really discussing was a post-industrial approach to collaborative, interdisciplinary, creative team work was given serious debate.&lt;/p&gt;


	&lt;p&gt;The group of twenty participants included developers, designers, testers, researchers, company owners, consultants, and employees. Approximately half of us had participated in the &lt;a href="http://www.andersramsay.com/2010/02/04/notes-from-the-agile-ux-retreat-at-cooper"&gt;first retreat&lt;/a&gt;, and half of us were new to the group. I felt we had a great balance between new and old, and a useful diversity of experience and opinion. The spirit of mutual respect and collaboration was both remarkable and productive. The group self-organized, with a few people naturally and effectively facilitating as necessary. &lt;a href="http://workthefactory.com/"&gt;The Factory&lt;/a&gt; in downtown Grand Rapids provided a great physical space for our work.&lt;/p&gt;


	&lt;p&gt;The majority of our time (at least if you don’t count dining and drinking at &lt;a href="http://www.sanchezbistro.com/"&gt;San Chez Bistro&lt;/a&gt; on Saturday night) was spent on two initiatives. The first was to craft a statement of values. The second was to organize and summarize a list of brainstormed problems we’ve all experienced. We concluded the retreat with a plan for continuing the work we started, and a strong desire to meet again soon and push this important effort forward.&lt;/p&gt;



&lt;a href="http://www.flickr.com/photos/39995732@N04/4793598690/" title="AUX Retreat Grand Rapids by Atomic Object, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4097/4793598690_f1e8a07c95.jpg" height="333" alt="AUX Retreat Grand Rapids" width="500" /&gt;&lt;/a&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=-RcHG4tAFH0:vr63DeCGcEg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=-RcHG4tAFH0:vr63DeCGcEg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=-RcHG4tAFH0:vr63DeCGcEg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=-RcHG4tAFH0:vr63DeCGcEg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=-RcHG4tAFH0:vr63DeCGcEg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=-RcHG4tAFH0:vr63DeCGcEg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=-RcHG4tAFH0:vr63DeCGcEg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=-RcHG4tAFH0:vr63DeCGcEg:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/-RcHG4tAFH0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/16/grand-rapids-agile-ux-retreat</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Matt Fletcher</name>
      <uri>http://www.atomicobject.com/pages/Matt+Fletcher</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-13:45811</id>
    <published>2010-07-13T14:12:00Z</published>
    <updated>2010-07-13T16:32:37Z</updated>
    <category term="Embedded Corner" />
    <category term="Embedded Software" />
    <category term="Presenter First" />
    <category term="Test Driven Development" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/BSwck6leen8/presenter-first-in-gtk-and-c" rel="alternate" type="text/html" />
    <title>Presenter First in GTK and C</title>
<content type="html">
            &lt;p&gt;Recently &lt;a href="http://www.atomicobject.com/pages/Mike+Karlesky"&gt;Mike Karlesky&lt;/a&gt; and I spent a week in the Baltimore area leading up a workshop-style training course. The intent of the workshop was to demonstrate Agile techniques applied in the embedded domain.&lt;/p&gt;


	&lt;p&gt;As part of the workshop, I created a small &lt;span class="caps"&gt;GTK&lt;/span&gt; application to demonstrate &lt;a href="http://www.atomicobject.com/pages/Presenter+First"&gt;Presenter First&lt;/a&gt; and Model-View-Presenter. (Although a &lt;span class="caps"&gt;GUI&lt;/span&gt; application may not seem particularly embedded, the principle is the same: the view walls off some untestable library; the presenter and model allow us to test around it.) &lt;span class="caps"&gt;GTK&lt;/span&gt; turned out to be a good choice, since the events flying out of its widgets were much like the asynchronous events that come out of other windowing toolkits or hardware devices.&lt;/p&gt;


And here it is: the aptly named &lt;a href="http://github.com/fletcherm/pf_gtk"&gt;PF Calculator&lt;/a&gt;. Guess what? It’s a calculator. The calculator’s functionality is quite limited, in that it can only divide integers, but it still demonstrates Presenter First concepts quite well:
	&lt;ul&gt;
	&lt;li&gt;The &lt;code&gt;ApplicationPresenter&lt;/code&gt; responds to events from the &lt;code&gt;ApplicationModel&lt;/code&gt; and &lt;code&gt;ApplicationView&lt;/code&gt;.&lt;/li&gt;
		&lt;li&gt;The &lt;code&gt;ApplicationView&lt;/code&gt; fires events roughly corresponding to events coming from &lt;span class="caps"&gt;GTK&lt;/span&gt; widgets. Along the way, it does some translation to only relay the relevant information &lt;em&gt;and&lt;/em&gt; remove traces of &lt;span class="caps"&gt;GTK&lt;/span&gt; in the event.&lt;/li&gt;
		&lt;li&gt;The &lt;code&gt;ApplicationModel&lt;/code&gt; is used to compute the “business logic” (haha, I love that term, especially when applied in such a silly context). The Model delegates to the &lt;code&gt;NumberValidator&lt;/code&gt; to get some help when needed.&lt;/li&gt;
		&lt;li&gt;And last (but not least), all of the above code was written Presenter First.&lt;/li&gt;
	&lt;/ul&gt;


&lt;p&gt;
&lt;img src="http://spin.atomicobject.com/assets/2010/7/13/pf_calculator.png" alt="" /&gt;
&lt;/p&gt;

Everything is implemented in C. Here are a few notes about the implementation:
	&lt;ul&gt;
	&lt;li&gt;In a language with automatic object construction, I’d have the Presenters wire up their events in their constructor methods. Since that strategy isn’t available here, I’ve instead implemented a &lt;code&gt;Presenters_RegisterForEvents&lt;/code&gt; function. The purpose of the function is to rip through all of the Presenters and tell them to &lt;code&gt;RegisterEvents&lt;/code&gt;. It would be trivial to have the build system automatically generate this file in a project with many Presenters.&lt;/li&gt;
		&lt;li&gt;I only support one subscriptor to any single event. This is because I didn’t feel like implementing a bounded array or linked list to hold the function pointers. I did see something about a &lt;code&gt;GSList&lt;/code&gt; data structure available in the GLib documentation, but I never got around to trying it out.&lt;/li&gt;
		&lt;li&gt;I call the &lt;code&gt;gtk_init&lt;/code&gt; function in &lt;code&gt;main&lt;/code&gt; before firing up the application. I’m not wild about this &lt;span class="caps"&gt;GTK&lt;/span&gt;-specific knowledge leaking outside of the view, but for this very simple example, it was the cleanest way to handle this detail. In a real project I’d strive to keep &lt;span class="caps"&gt;GTK&lt;/span&gt; specifics confined to views.&lt;/li&gt;
	&lt;/ul&gt;


I depend on a number of libraries and tools to get them job done. More notes:
	&lt;ul&gt;
	&lt;li&gt;I’m using the &lt;a href="http://sourceforge.net/projects/ceedling"&gt;Ceedling&lt;/a&gt; build and test harness developed by Mike Karlesky, Greg Williams, and Mark VanderVoord. Ceedling gives me easy access to unit testing via &lt;a href="http://sourceforge.net/projects/embunity"&gt;Unity&lt;/a&gt;, C mock generation via &lt;a href="http://sourceforge.net/projects/cmock"&gt;CMock&lt;/a&gt;, and C exceptions via &lt;a href="http://sourceforge.net/projects/cexception"&gt;CException&lt;/a&gt;. Ceedling also weaves everything together to create the executables.
	&lt;ul&gt;
	&lt;li&gt;Ceedling hasn’t had a 1.0 release yet, but the code available from the Sourceforge project is quite functional.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
		&lt;li&gt;I used this project as an excuse to monkey around with the &lt;a href="http://www.pcre.org"&gt;&lt;span class="caps"&gt;PCRE&lt;/span&gt;&lt;/a&gt; library. I didn’t use it extensively, but it was enough to get a taste. It turns out &lt;span class="caps"&gt;PCRE&lt;/span&gt; is tasty.&lt;/li&gt;
		&lt;li&gt;I also recently heard about &lt;a href="http://bstring.sourceforge.net"&gt;bstring&lt;/a&gt; and tried it out. Again, I didn’t use it for much, but enough such that I’m sold on it.&lt;/li&gt;
	&lt;/ul&gt;


Warning: I haven’t tried to build this code on anything other than my personal Linux system, so I can’t say how portable it is. Here are some details about my system:
	&lt;ul&gt;
	&lt;li&gt;The Linux distribution is Ubuntu 10.04.&lt;/li&gt;
		&lt;li&gt;The &lt;span class="caps"&gt;GTK&lt;/span&gt; development files have been installed via the libgtk2.0-dev package.&lt;/li&gt;
		&lt;li&gt;The &lt;span class="caps"&gt;PCRE&lt;/span&gt; development files have been installed via the libpcre3-dev package.&lt;/li&gt;
		&lt;li&gt;bstring is bundled with the project.&lt;/li&gt;
		&lt;li&gt;The build system relies on Ruby and Rake.
The build system uses pkg-config commands to gather the build flags for &lt;span class="caps"&gt;PCRE&lt;/span&gt; and &lt;span class="caps"&gt;GTK&lt;/span&gt;. Hopefully this means it will be easier to build the project on an arbitrary system.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;To build and run the application, type &lt;code&gt;rake&lt;/code&gt;. To run all the tests, type &lt;code&gt;rake test:all&lt;/code&gt;. To test an individual module, like ApplicationModel, type &lt;code&gt;rake test:ApplicationModel.c&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Big thanks to Mike Karlesky for assisting with Ceedling, CMock, and Unity. Also thanks to Greg Williams and Mark VanderVoord for helping develop this great software.&lt;/p&gt;


Resources:
	&lt;ul&gt;
	&lt;li&gt;The &lt;a href="http://github.com/fletcherm/pf_gtk"&gt;pf_gtk repository&lt;/a&gt; hosted on GitHub.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/fletcherm/pf_gtk/tarball/master"&gt;pf_gtk tarball&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.atomicobject.com/pages/Presenter+First"&gt;Presenter First&lt;/a&gt; information at Atomic Object.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://sourceforge.net/projects/ceedling/"&gt;Ceedling&lt;/a&gt; build system and other useful C tools.&lt;/li&gt;
	&lt;/ul&gt;


&lt;p&gt;
&lt;img src="https://spin.atomicobject.com/assets/2010/7/13/mvp.jpg" alt="" /&gt;
&lt;/p&gt;

	&lt;p&gt;&lt;em&gt;Edit July 13, 2010: The article was initially published without the Ubuntu package names filled in. This has been corrected.&lt;/em&gt;&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=BSwck6leen8:YTHLKXb84I4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=BSwck6leen8:YTHLKXb84I4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=BSwck6leen8:YTHLKXb84I4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=BSwck6leen8:YTHLKXb84I4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=BSwck6leen8:YTHLKXb84I4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=BSwck6leen8:YTHLKXb84I4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=BSwck6leen8:YTHLKXb84I4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=BSwck6leen8:YTHLKXb84I4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/BSwck6leen8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/13/presenter-first-in-gtk-and-c</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Patrick Bacon</name>
      <uri>http://www.atomicobject.com/pages/Patrick+Bacon</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-08:45582</id>
    <published>2010-07-08T14:13:00Z</published>
    <updated>2010-07-08T14:14:49Z</updated>
    <category term="Technologies" />
    <category term="Tips" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/i0x6qZfhpa0/consolidate-multiple-filesystemwatcher-events" rel="alternate" type="text/html" />
    <title>Consolidate Multiple FileSystemWatcher Events</title>
<content type="html">
            &lt;p&gt;The .NET framework provides a &lt;code&gt;FileSystemWatcher&lt;/code&gt; class that can be used to monitor the file system for changes. My requirements were to monitor a directory for new files or changes to existing files. When a change occurs, the application needs to read the file and immediately perform some operation based on the contents of the file.&lt;/p&gt;


	&lt;p&gt;While doing some manual testing of my initial implementation it was very obvious that the &lt;code&gt;FileSystemWatcher&lt;/code&gt; was firing multiple events whenever I made a change to a file or copied a file into the directory being monitored. I came across the following in the &lt;span class="caps"&gt;MSDN&lt;/span&gt; documentation’s &lt;a href="http://msdn.microsoft.com/en-us/library/xcc1t119(VS.71).aspx"&gt;Troubleshooting FileSystemWatcher Components&lt;/a&gt;&lt;/p&gt;


&lt;blockquote&gt;
&lt;h3&gt;Multiple Created Events Generated for a Single Action&lt;/h3&gt;

&lt;p&gt;You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use a FileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the operating system activities, all events that these applications fire will be picked up.&lt;/p&gt;

&lt;p&gt;Note: Notepad may also cause other interesting event generations. For example, if you use the ChangeEventFilter to specify that you want to watch only for attribute changes, and then you write to a file in the directory you are watching using Notepad, you will raise an event. This is because Notepad updates the Archived attribute for the file during this operation.&lt;/p&gt;
&lt;/blockquote&gt;

	&lt;p&gt;I did some searching and was surprised that .NET did not provide any kind of wrapper around the FileSystemWatcher to make it a bit more user friendly. I ended up writing my own wrapper that would monitor a directory and only throw one event when a new file was created, or an existing file was changed.&lt;/p&gt;


	&lt;p&gt;In order to consolidate the multiple FileSystemWatcher events down to a single event, I save the timestamp when each event is received, and I check back every so often (using a Timer) to find paths that have not caused additional events in a while. When one of these paths is ready, a single &lt;code&gt;Changed&lt;/code&gt; event is fired. An additional benefit of this technique is that the event from the FileSystemWatcher is handled very quickly, which could help prevent its internal buffer from filling up.&lt;/p&gt;


	&lt;p&gt;Here is the code for a &lt;code&gt;DirectoryMonitor&lt;/code&gt; class that consolidates multiple Win32 events into a single &lt;code&gt;Change&lt;/code&gt; event for each change:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;35&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;45&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;55&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;65&lt;tt&gt;
&lt;/tt&gt;66&lt;tt&gt;
&lt;/tt&gt;67&lt;tt&gt;
&lt;/tt&gt;68&lt;tt&gt;
&lt;/tt&gt;69&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;70&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;71&lt;tt&gt;
&lt;/tt&gt;72&lt;tt&gt;
&lt;/tt&gt;73&lt;tt&gt;
&lt;/tt&gt;74&lt;tt&gt;
&lt;/tt&gt;75&lt;tt&gt;
&lt;/tt&gt;76&lt;tt&gt;
&lt;/tt&gt;77&lt;tt&gt;
&lt;/tt&gt;78&lt;tt&gt;
&lt;/tt&gt;79&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;80&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;81&lt;tt&gt;
&lt;/tt&gt;82&lt;tt&gt;
&lt;/tt&gt;83&lt;tt&gt;
&lt;/tt&gt;84&lt;tt&gt;
&lt;/tt&gt;85&lt;tt&gt;
&lt;/tt&gt;86&lt;tt&gt;
&lt;/tt&gt;87&lt;tt&gt;
&lt;/tt&gt;88&lt;tt&gt;
&lt;/tt&gt;89&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;90&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;91&lt;tt&gt;
&lt;/tt&gt;92&lt;tt&gt;
&lt;/tt&gt;93&lt;tt&gt;
&lt;/tt&gt;94&lt;tt&gt;
&lt;/tt&gt;95&lt;tt&gt;
&lt;/tt&gt;96&lt;tt&gt;
&lt;/tt&gt;97&lt;tt&gt;
&lt;/tt&gt;98&lt;tt&gt;
&lt;/tt&gt;99&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;101&lt;tt&gt;
&lt;/tt&gt;102&lt;tt&gt;
&lt;/tt&gt;103&lt;tt&gt;
&lt;/tt&gt;104&lt;tt&gt;
&lt;/tt&gt;105&lt;tt&gt;
&lt;/tt&gt;106&lt;tt&gt;
&lt;/tt&gt;107&lt;tt&gt;
&lt;/tt&gt;108&lt;tt&gt;
&lt;/tt&gt;109&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;110&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;111&lt;tt&gt;
&lt;/tt&gt;112&lt;tt&gt;
&lt;/tt&gt;113&lt;tt&gt;
&lt;/tt&gt;114&lt;tt&gt;
&lt;/tt&gt;115&lt;tt&gt;
&lt;/tt&gt;116&lt;tt&gt;
&lt;/tt&gt;117&lt;tt&gt;
&lt;/tt&gt;118&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;using System;&lt;tt&gt;
&lt;/tt&gt;using System.Collections.Generic;&lt;tt&gt;
&lt;/tt&gt;using System.IO;&lt;tt&gt;
&lt;/tt&gt;using System.Threading;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;namespace FileSystem&lt;tt&gt;
&lt;/tt&gt;{&lt;tt&gt;
&lt;/tt&gt;  public delegate &lt;span class="pt"&gt;void&lt;/span&gt; FileSystemEvent(String path);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  public interface IDirectoryMonitor&lt;tt&gt;
&lt;/tt&gt;  {&lt;tt&gt;
&lt;/tt&gt;    event FileSystemEvent Change;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="pt"&gt;void&lt;/span&gt; Start();&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  public class DirectoryMonitor : IDirectoryMonitor&lt;tt&gt;
&lt;/tt&gt;  {&lt;tt&gt;
&lt;/tt&gt;    private readonly FileSystemWatcher m_fileSystemWatcher = &lt;tt&gt;
&lt;/tt&gt;      new FileSystemWatcher();&lt;tt&gt;
&lt;/tt&gt;    private readonly Dictionary&amp;lt;string, DateTime&amp;gt; m_pendingEvents = &lt;tt&gt;
&lt;/tt&gt;      new Dictionary&amp;lt;string, DateTime&amp;gt;();&lt;tt&gt;
&lt;/tt&gt;    private readonly Timer m_timer;&lt;tt&gt;
&lt;/tt&gt;    private &lt;span class="pt"&gt;bool&lt;/span&gt; m_timerStarted = &lt;span class="pc"&gt;false&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    public DirectoryMonitor(string dirPath)&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      m_fileSystemWatcher.Path = dirPath;&lt;tt&gt;
&lt;/tt&gt;      m_fileSystemWatcher.IncludeSubdirectories = &lt;span class="pc"&gt;false&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;      m_fileSystemWatcher.Created += new FileSystemEventHandler(OnChange);&lt;tt&gt;
&lt;/tt&gt;      m_fileSystemWatcher.Changed += new FileSystemEventHandler(OnChange);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      m_timer = new Timer(OnTimeout, null, Timeout.Infinite, Timeout.Infinite);&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    public event FileSystemEvent Change;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    public &lt;span class="pt"&gt;void&lt;/span&gt; Start()&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      m_fileSystemWatcher.EnableRaisingEvents = &lt;span class="pc"&gt;true&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    private &lt;span class="pt"&gt;void&lt;/span&gt; OnChange(object sender, FileSystemEventArgs e)&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;// Don't want other threads messing with the pending events right now&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      lock (m_pendingEvents)&lt;tt&gt;
&lt;/tt&gt;      {&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// Save a timestamp for the most recent event for this path&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        m_pendingEvents[e.FullPath] = DateTime.Now;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// Start a timer if not already started&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;if&lt;/span&gt; (!m_timerStarted)&lt;tt&gt;
&lt;/tt&gt;        {&lt;tt&gt;
&lt;/tt&gt;          m_timer.Change(&lt;span class="i"&gt;100&lt;/span&gt;, &lt;span class="i"&gt;100&lt;/span&gt;);&lt;tt&gt;
&lt;/tt&gt;          m_timerStarted = &lt;span class="pc"&gt;true&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;        }   &lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    private &lt;span class="pt"&gt;void&lt;/span&gt; OnTimeout(object state)&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      List&amp;lt;string&amp;gt; paths;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;// Don't want other threads messing with the pending events right now&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      lock (m_pendingEvents)&lt;tt&gt;
&lt;/tt&gt;      {&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// Get a list of all paths that should have events thrown&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        paths = FindReadyPaths(m_pendingEvents);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// Remove paths that are going to be used now&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        paths.ForEach(delegate(string path)&lt;tt&gt;
&lt;/tt&gt;          {&lt;tt&gt;
&lt;/tt&gt;            m_pendingEvents.Remove(path);&lt;tt&gt;
&lt;/tt&gt;          });&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// Stop the timer if there are no more events pending&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;if&lt;/span&gt; (m_pendingEvents.Count == &lt;span class="i"&gt;0&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;        {&lt;tt&gt;
&lt;/tt&gt;          m_timer.Change(Timeout.Infinite, Timeout.Infinite);&lt;tt&gt;
&lt;/tt&gt;          m_timerStarted = &lt;span class="pc"&gt;false&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;        }&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;// Fire an event for each path that has changed&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      paths.ForEach(delegate(string path)&lt;tt&gt;
&lt;/tt&gt;        {&lt;tt&gt;
&lt;/tt&gt;          FireEvent(path);&lt;tt&gt;
&lt;/tt&gt;        });&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    private List&amp;lt;string&amp;gt; FindReadyPaths(Dictionary&amp;lt;string, DateTime&amp;gt; events)&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      List&amp;lt;string&amp;gt; results = new List&amp;lt;string&amp;gt;();&lt;tt&gt;
&lt;/tt&gt;      DateTime now = DateTime.Now;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      foreach (KeyValuePair&amp;lt;string, DateTime&amp;gt; entry in events)&lt;tt&gt;
&lt;/tt&gt;      {&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// If the path has not received a new event in the last 75ms&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;// an event for the path should be fired&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="pt"&gt;double&lt;/span&gt; diff = now.Subtract(entry.Value).TotalMilliseconds;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;if&lt;/span&gt; (diff &amp;gt;= &lt;span class="i"&gt;75&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;        {&lt;tt&gt;
&lt;/tt&gt;          results.Add(entry.Key);&lt;tt&gt;
&lt;/tt&gt;        }&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;return&lt;/span&gt; results;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    private &lt;span class="pt"&gt;void&lt;/span&gt; FireEvent(string path)&lt;tt&gt;
&lt;/tt&gt;    {&lt;tt&gt;
&lt;/tt&gt;      FileSystemEvent evt = Change;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;if&lt;/span&gt; (evt != null)&lt;tt&gt;
&lt;/tt&gt;      {&lt;tt&gt;
&lt;/tt&gt;        evt(path);&lt;tt&gt;
&lt;/tt&gt;      }&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=i0x6qZfhpa0:XaQ-PiSlyBk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=i0x6qZfhpa0:XaQ-PiSlyBk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=i0x6qZfhpa0:XaQ-PiSlyBk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=i0x6qZfhpa0:XaQ-PiSlyBk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=i0x6qZfhpa0:XaQ-PiSlyBk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=i0x6qZfhpa0:XaQ-PiSlyBk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=i0x6qZfhpa0:XaQ-PiSlyBk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=i0x6qZfhpa0:XaQ-PiSlyBk:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/i0x6qZfhpa0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/08/consolidate-multiple-filesystemwatcher-events</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Justin DeWind</name>
      <uri>http://www.atomicobject.com/pages/Justin+DeWind</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-07-06:45526</id>
    <published>2010-07-06T14:39:00Z</published>
    <updated>2010-07-06T14:45:41Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/Y6GJNj6tork/catching-exceptions-via-nsinvocation-and-nsproxy-is-not-longer-possible-in-objective-c" rel="alternate" type="text/html" />
    <title>Catching exceptions via NSInvocation and NSProxy is no longer possible in Objective C</title>
<summary type="html">&lt;p&gt;This issue has already been raised in several places, but in the hopes of adding some more visibility to the issue I figured it would not hurt to post it here. Under the iOS 3.2 and iOS 4 simulator platforms it is no longer possible to catch exceptions via NSInvocation and Apple’s object proxy mechanism (NSProxy). Specifically, it makes it almost impossible to use &lt;a href="http://github.com/360/OCHamcrest"&gt;OCHamcrest&lt;/a&gt; and &lt;a href="http://www.mulle-kybernetik.com/software/OCMock/"&gt;OCMock&lt;/a&gt; as they both rely heavily on dynamic invocation and proxy objects.&lt;/p&gt;


	&lt;p&gt;The issue has already been raised here:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://pivotallabs.com/users/amilligan/blog/articles/1302-objective-c-exceptions-thrown-inside-methods-invoked-via-nsinvocation-are-uncatchable"&gt;Pivotal Labs&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://lists.apple.com/archives/objc-language//2010/Jul/msg00007.html"&gt;Objective Language Mailing List&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://openradar.appspot.com/8081169"&gt;Google Toolbox&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I created a &lt;a href="http://github.com/dewind/iOS4GoogleToolbox"&gt;sandbox project&lt;/a&gt; in an attempt to diagnose the various scenarios in which exception handling did not work. Until Apple releases a fix for the bug it is going to take some creative work-arounds in order to “move on” from the issue.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;This issue has already been raised in several places, but in the hopes of adding some more visibility to the issue I figured it would not hurt to post it here. Under the iOS 3.2 and iOS 4 simulator platforms it is no longer possible to catch exceptions via NSInvocation and Apple’s object proxy mechanism (NSProxy). Specifically, it makes it almost impossible to use &lt;a href="http://github.com/360/OCHamcrest"&gt;OCHamcrest&lt;/a&gt; and &lt;a href="http://www.mulle-kybernetik.com/software/OCMock/"&gt;OCMock&lt;/a&gt; as they both rely heavily on dynamic invocation and proxy objects.&lt;/p&gt;


	&lt;p&gt;The issue has already been raised here:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://pivotallabs.com/users/amilligan/blog/articles/1302-objective-c-exceptions-thrown-inside-methods-invoked-via-nsinvocation-are-uncatchable"&gt;Pivotal Labs&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://lists.apple.com/archives/objc-language//2010/Jul/msg00007.html"&gt;Objective Language Mailing List&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://openradar.appspot.com/8081169"&gt;Google Toolbox&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I created a &lt;a href="http://github.com/dewind/iOS4GoogleToolbox"&gt;sandbox project&lt;/a&gt; in an attempt to diagnose the various scenarios in which exception handling did not work. Until Apple releases a fix for the bug it is going to take some creative work-arounds in order to “move on” from the issue.&lt;/p&gt;
&lt;p&gt;It is still possible to catch exceptions via an NSInvocation if you fallback to using the &lt;em&gt;objc_msgSend&lt;/em&gt; function in lieu of &lt;em&gt;[invocation invoke]&lt;/em&gt;. OCHamcrest and OCMock could be patched to temporarily use that workaround until Apple releases a fix. The &lt;a href="http://code.google.com/p/google-toolbox-for-mac/"&gt;Google Toolbox&lt;/a&gt; guys have already rolled this workaround into their test runner.&lt;/p&gt;


	&lt;p&gt;For example,&lt;/p&gt;


	&lt;h3&gt;Uncatchable Implementation&lt;/h3&gt;


&amp;lt;script src="http://gist.github.com/465438.js"&gt;&amp;lt;/script&gt;

	&lt;h3&gt;Workaround&lt;/h3&gt;


&amp;lt;script src="http://gist.github.com/465435.js"&gt;&amp;lt;/script&gt;

	&lt;p&gt;This will get around the NSInvocation issue (for the most part), but throwing exceptions within an NSProxy object is still broken. The only workaround I can envision would be to use &lt;em&gt;objc_exception_throw&lt;/em&gt;; which appears to be undocumented. It is anyone’s guess if that will work around the issue. But it might be worth a try.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=Y6GJNj6tork:fsPrx_V45c4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=Y6GJNj6tork:fsPrx_V45c4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=Y6GJNj6tork:fsPrx_V45c4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=Y6GJNj6tork:fsPrx_V45c4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=Y6GJNj6tork:fsPrx_V45c4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=Y6GJNj6tork:fsPrx_V45c4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=Y6GJNj6tork:fsPrx_V45c4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=Y6GJNj6tork:fsPrx_V45c4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/Y6GJNj6tork" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/07/06/catching-exceptions-via-nsinvocation-and-nsproxy-is-not-longer-possible-in-objective-c</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Mike Karlesky</name>
      <uri>http://www.atomicobject.com/pages/Mike+Karlesky</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-06-30:45302</id>
    <published>2010-06-30T23:07:00Z</published>
    <updated>2010-07-06T21:52:16Z</updated>
    <category term="Embedded Software" />
    <category term="Languages" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/fhRYzQn4Uqk/d-little-language-that-could" rel="alternate" type="text/html" />
    <title>D - The little language that could</title>
<content type="html">
            &lt;p&gt;(So, in reality, D probably isn’t all that little, but here’s to it &lt;a href="http://en.wikipedia.org/wiki/The_Little_Engine_That_Could"&gt;making it up the mountain&lt;/a&gt;.)&lt;/p&gt;


	&lt;p&gt;A good while ago I wrote a post about my hope for &lt;a href="/2007/04/22/d-programming-language-for-systems-embedded-programming"&gt;the D programming language as an up-and-comer in systems and embedded programming&lt;/a&gt;. D promises to bring a number of modern language concepts and constructs to low-level systems while yet producing a fairly efficient runtime. It’s 3 years on since my original post, but I’m still hopeful.&lt;/p&gt;


	&lt;p&gt;Just a few days ago a comment came in on my original post. My friend &lt;a href="http://twitter.com/mvandervoord"&gt;Mark VanderVoord&lt;/a&gt; responded in that comment thread. I thought I’d make the content of the thread a bit more visible (below) as it’s concerned with using D in the real world.&lt;/p&gt;


	&lt;p&gt;There’s been &lt;a href="http://en.wikipedia.org/wiki/D_programming_language"&gt;respectable progress toward D becoming viable in the mainstream&lt;/a&gt;. I’ll venture a guess that it’s going to be several more years until it truly is.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; (7/1/2010): We don’t often attract a great many comments on our posts. But we have here. I point it out because there’s good resources, background, and perspective on D in the comments. Take a read. The original comment thread that sparked this post can still be found beneath this update.&lt;/p&gt;


Since our comments can’t contain links, I’m listing &amp; linkifying here what our commenters have referenced:
	&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://steveklabnik.com/"&gt;Steve Klabnik&lt;/a&gt; pointed out &lt;a href="http://xomb.org/"&gt;a new kernel project written in D&lt;/a&gt; (Steve is one of the authors)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.kev009.com/"&gt;Kevin Bowling&lt;/a&gt; recommends the book &lt;a href="http://www.amazon.com/D-Programming-Language-Andrei-Alexandrescu/dp/0321635361"&gt;The D Programming Language&lt;/a&gt; written by another of our commenters &lt;a href="http://erdani.com/"&gt;Andrei Alexandrescu&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.dsource.org/projects/descent"&gt;Descent is an Eclipse plugin for D&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Several have compared/contrasted D to the &lt;a href="http://code.google.com/p/go/"&gt;new Go programming language by Google&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; (7/6/2010): Commenter &lt;a href="#comment-45381"&gt;devdanke suggested Apple as a D corporate backer&lt;/a&gt;. Google seems to be pursuing Go; why not Apple getting behind D? Apple certainly has a lot invested in &lt;span class="caps"&gt;LLVM&lt;/span&gt; of late. &lt;a href="http://waffle.wootest.net/2010/06/19/surpass/"&gt;Apple may just be up to something&lt;/a&gt;—though I’m doubtful it’s D. Time will tell…&lt;/p&gt;


	&lt;p&gt;&lt;br /&gt;&lt;blockquote&gt;
&lt;a href="http://slide-o-blog.blogspot.com/"&gt;slide&lt;/a&gt; Says:&lt;br /&gt;June 25th, 2010 at 07:35 PM&lt;br /&gt;&lt;br /&gt;
Is there any active development that you know of to get D running on embedded, bare-metal type platforms?
&lt;/blockquote&gt;&lt;/p&gt;


	&lt;p&gt;&lt;br /&gt;&lt;/p&gt;


&lt;blockquote&gt;
Mark Says:&lt;br /&gt;June 25th, 2010 at 11:01 PM

	&lt;p&gt;slide:&lt;/p&gt;


	&lt;p&gt;This is the current state of things as far as I know:&lt;/p&gt;


	&lt;p&gt;The official D versions (&lt;a href="http://www.digitalmars.com/d/1.0"&gt;D1&lt;/a&gt; and &lt;a href="http://www.digitalmars.com/d/2.0"&gt;D2&lt;/a&gt;) by &lt;a href="http://digitalmars.com/"&gt;Digital Mars&lt;/a&gt; (DMD) are only x86 so far&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://dgcc.sourceforge.net/"&gt;&lt;span class="caps"&gt;GDC&lt;/span&gt;&lt;/a&gt; – this is a D front-end with a gcc backend. Theoretically this means you can target anything gcc can (which is almost everything). The work I’ve done with it (mostly &lt;span class="caps"&gt;ARM&lt;/span&gt;) has been pretty tricky to get working, though.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.dsource.org/projects/ldc"&gt;&lt;span class="caps"&gt;LDC&lt;/span&gt;&lt;/a&gt; – this is a D front-end to &lt;span class="caps"&gt;LLVM&lt;/span&gt;. Again, this means you should be able to target anything &lt;span class="caps"&gt;LLVM&lt;/span&gt; can. &lt;span class="caps"&gt;LLVM&lt;/span&gt; has a lot of momentum lately… and this port seems to be pretty active too. I have done some small experiments with getting it to target an &lt;span class="caps"&gt;ARM9&lt;/span&gt;. It seemed to work well. I hope to have more time to work on that in the future.&lt;/p&gt;


	&lt;p&gt;For either &lt;span class="caps"&gt;LDC&lt;/span&gt; or &lt;span class="caps"&gt;GDC&lt;/span&gt;, you’re getting D version 1, which is missing some of the new (in-progress) features. But, they’re more stable, so that’s nice.&lt;/p&gt;


	&lt;p&gt;D links easily to C, so bringing in libraries, &lt;span class="caps"&gt;RTOS&lt;/span&gt;’s etc is pretty easy.&lt;/p&gt;


	&lt;p&gt;I hope this helps.&lt;/p&gt;


Mark
&lt;/blockquote&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=fhRYzQn4Uqk:L6Lq2HncfcM:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=fhRYzQn4Uqk:L6Lq2HncfcM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=fhRYzQn4Uqk:L6Lq2HncfcM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=fhRYzQn4Uqk:L6Lq2HncfcM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=fhRYzQn4Uqk:L6Lq2HncfcM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=fhRYzQn4Uqk:L6Lq2HncfcM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=fhRYzQn4Uqk:L6Lq2HncfcM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=fhRYzQn4Uqk:L6Lq2HncfcM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/fhRYzQn4Uqk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/06/30/d-little-language-that-could</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Grant Gumina</name>
      <uri>http://www.atomicobject.com/pages/Grant+Gumina</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-06-18:45159</id>
    <published>2010-06-18T14:24:00Z</published>
    <updated>2010-06-18T14:24:14Z</updated>
    <category term="Embedded Software" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/MuyxvbOAHp4/soccer-playing-robot-wins-world-cup" rel="alternate" type="text/html" />
    <title>Soccer-playing robot wins World Cup</title>
<content type="html">
            &lt;p&gt;When asked what sports they play, most high school students typically respond “football,” “baseball,” “basketball,” or “soccer.” I, however, get to respond with something much more interesting: “robotics.”&lt;/p&gt;


	&lt;p&gt;The sport I am referring to is the &lt;a href="http://usfirst.org/roboticsprograms/frc/default.aspx?id=966"&gt;&lt;span class="caps"&gt;FIRST&lt;/span&gt; Robotics Competition&lt;/a&gt;, a high school level competitive robot building competition. Teams from around the world, 1,808 to be exact, compete against each other every year in a world wide challenge that culminates at the Championship held in Atlanta, Georgia.&lt;/p&gt;


	&lt;p&gt;I first started competing with the only &lt;span class="caps"&gt;FRC&lt;/span&gt; team in Grand Rapids, &lt;a href="http://creston904.com/"&gt;Creston High School’s robotics team&lt;/a&gt;, but eventually several members and I began looking into forming our own team closer to where we lived. In late October of 2009, those of us who lived in the Forest Hills, Ada, and Cascade areas of Grand Rapids decided to form the &lt;a href="http://comets.firstobjective.org/"&gt;&lt;span class="caps"&gt;COMETS&lt;/span&gt;&lt;/a&gt; (Creating Outstanding Minds Embracing Technology and Science) only a couple months before the 2010 season began.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/18/robot_two.jpg?1276870883"&gt;&lt;/div&gt;

	&lt;p&gt;This year our challenge was to build a robot that could play a game called &lt;a href="http://comets.firstobjective.org/aboutchallenge.html"&gt;Breakaway&lt;/a&gt; basically a mixture of soccer and steeplechase, where robots competed against other robots in games of three vs. three. With the help of many local area &lt;a href="http://comets.firstobjective.org/sponsors.html"&gt;sponsors&lt;/a&gt;, and great &lt;a href="http://comets.firstobjective.org/aboutmentors.html"&gt;mentors&lt;/a&gt; (local engineers, programmers, and businessmen who guide team members in their efforts), we were able to build a highly competitive robot in the six weeks we were given. In fact, we won the West Michigan District event, placed 20th in the state, and won our division in the Championship. Not too bad for a rookie team.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/18/robot.jpg?1276869070"&gt;&lt;/div&gt;

	&lt;p&gt;But the most important part of the season was definitely not our win/loss record. It was the fact that students learned new skills in &lt;a href="http://comets.firstobjective.org/cadmetalfabrication.html"&gt;&lt;span class="caps"&gt;CAD&lt;/span&gt; and metal fabrication&lt;/a&gt;, &lt;a href="http://comets.firstobjective.org/programming.html"&gt;programming&lt;/a&gt;, &lt;a href="http://comets.firstobjective.org/webdesign.html"&gt;web design&lt;/a&gt;, &lt;a href="http://comets.firstobjective.org/3danimation.html"&gt;3D animation&lt;/a&gt;, and &lt;a href="http://comets.firstobjective.org/marketing.html"&gt;marketing&lt;/a&gt;. Just as important is the fact that students experienced how much fun science and technology can be, and built partnerships throughout our community (in fact, it was through Atomic’s sponsorship of local area teams that I first became aware of their internship program).&lt;/p&gt;


	&lt;p&gt;However, it’s easy to say that in retrospect.&lt;/p&gt;


	&lt;p&gt;In the three years that I have been involved with robotics, I’ve had seasons where the team has lost almost every single match, as well as seasons (recently) where we did incredibly well. But in all honesty, I only remember a handful of matches we played. What I do remember is the important stuff.&lt;/p&gt;


	&lt;p&gt;For example, I remember how in 2008 I scoured the Internet and Home Depot to find a material that would trigger the robot’s photoeyes when our ‘bot’s elevator passed them. I remember in 2009 when the &lt;span class="caps"&gt;FRC&lt;/span&gt; switched from a &lt;span class="caps"&gt;PIC&lt;/span&gt; based microprocessor to the powerPC based cRIO from National Instruments, and how I had to learn a new, object oriented language that came with it. I also remember how this year the other programmers and I wrote multi-threaded Java software so our robot could efficiently manage user input and a live camera feed.&lt;/p&gt;


	&lt;p&gt;The &lt;span class="caps"&gt;FRC&lt;/span&gt; creates an environment where being interested in science and technology is alright. That environment then goes on to encourage problem solving, creativity, and a strong team spirit. For me, this environment gives me an outlet where I can learn and create with people who have the same interests as I do. I could go on, but I think that you get the idea: this robotics competition is actually much more than just a sport.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=MuyxvbOAHp4:GyYS-Uf2YFk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=MuyxvbOAHp4:GyYS-Uf2YFk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=MuyxvbOAHp4:GyYS-Uf2YFk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=MuyxvbOAHp4:GyYS-Uf2YFk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=MuyxvbOAHp4:GyYS-Uf2YFk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=MuyxvbOAHp4:GyYS-Uf2YFk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=MuyxvbOAHp4:GyYS-Uf2YFk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=MuyxvbOAHp4:GyYS-Uf2YFk:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/MuyxvbOAHp4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/06/18/soccer-playing-robot-wins-world-cup</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Karlin Fox</name>
      <uri>http://www.atomicobject.com/pages/Karlin+Fox</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-06-11:45082</id>
    <published>2010-06-11T00:05:00Z</published>
    <updated>2010-06-11T00:06:34Z</updated>
    <category term="Tips" />
    <category term="Tools" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/OsTqYX9JJyA/working-faster-with-working-directory" rel="alternate" type="text/html" />
    <title>Working Faster with Working Directory</title>
<content type="html">
            &lt;p&gt;I always have a shell open. Most of my daily project navigation and file-system work is done in Bash. If I can do something with a &lt;span class="caps"&gt;GUI&lt;/span&gt; or a terminal, I’ll prefer the terminal. I’m a polyglot programmer who often uses Windows, Linux, and Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; all in the same day. There’s a tool I need whenever I work on the command-line: &lt;a href="http://github.com/karlin/working-directory"&gt;Working Directory&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Here’s a scenario:&lt;/p&gt;


	&lt;p&gt;Your project uses Java and Maven. That means the first useful bits of your code are buried somewhere like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So you start out a new shell in your home directory and navigate all the way down there:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ cd work&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work$ cd FooFoo&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo$ cd src/main/java/org/foo&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Whew! Maybe not a big deal once, but I hope you don’t have to do this every day! Fortunately you have command-line completion, cutting down on all that typing:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ cd wo[TAB]/Foo[TAB]/s[TAB]/m[TAB]/j[TAB][TAB][TAB]&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Wait, what? That’s still a lot of typing! This is much quicker for users of Working Directory:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ wd&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;That’s it! Let’s see how that magic works.&lt;/p&gt;


	&lt;p&gt;Whenever you start a new project or workspace, just tell Working Directory (or just “wd”) that you want to make a new &lt;em&gt;scheme&lt;/em&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ wdscheme foofoo&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This creates a set of 10 slots associated with that scheme and copies in the contents of your previous scheme. (If you don’t need a clone of the previous scheme, you can clear those out with &lt;code&gt;wdc&lt;/code&gt;.) Now you simply navigate to your project root, or wherever you most commonly need to start when you work on that project, using regular &lt;code&gt;cd&lt;/code&gt; and all the tab-completions you can tolerate. Once there, you can store that directory in the default slot like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$ wds&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;If you then look at the list of slot assignments with &lt;code&gt;wdl&lt;/code&gt;, you’ll see that you’ve stored the current directory in the 0th slot:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ wdl&lt;tt&gt;
&lt;/tt&gt;0 /Users/capt.picard/work/FooFoo/src/main/java/org/foo&lt;tt&gt;
&lt;/tt&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The first slot is special—you can access it without specifying a number at all. Just type &lt;code&gt;wd&lt;/code&gt; to navigate to that slot and &lt;code&gt;wds&lt;/code&gt; to set it to the current directory. The remaining slots require their number to retrieve or store. If you want to store the directory that holds your project tests in slot 3:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ cd work/FooFoo/src/test/java&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/test/java$ wds3&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/test/java$ wdl&lt;tt&gt;
&lt;/tt&gt;0 /Users/capt.picard/work/FooFoo/src/main/java/org/foo&lt;tt&gt;
&lt;/tt&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3 /Users/capt.picard/work/FooFoo/src/test/java&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Now you can quickly navigate between source and test on the command-line:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;/Users/capt.picard$ wd&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$ wd3&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/test/java$ wd&lt;tt&gt;
&lt;/tt&gt;/Users/capt.picard/work/FooFoo/src/main/java/org/foo$&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You can have as many schemes as you want, but each scheme only stores 10 directories. This allows for maximum accessibility on the command-line with single-word aliases for going to or storing into each slot.&lt;/p&gt;


	&lt;p&gt;Working Directory has many other features that you may start to use over time:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;wdenv&lt;/code&gt; stores the current scheme into similarily-named environment variables for easy use on the command-line for any purpose, like &lt;code&gt;cp&lt;/code&gt;.&lt;/li&gt;
		&lt;li&gt;Storing directories in slots doesn’t require that you be in the directory. Just give a directory as a parameter to &lt;code&gt;wds[0-9]&lt;/code&gt; and it will store it instead of the current directory.&lt;/li&gt;
		&lt;li&gt;wd is cross-platform, written in Bash and Perl. I’ve used it heavily over the years on Windows+cygwin, Linux, &lt;span class="caps"&gt;OS X&lt;/span&gt;, and Solaris.&lt;/li&gt;
		&lt;li&gt;wd provides a bash-completion function for its schemes. &lt;code&gt;wdscheme [TAB][TAB]&lt;/code&gt; will list of all of your existing schemes.&lt;/li&gt;
		&lt;li&gt;Since wd stores schemes and slots on disk, all of your terminals will share the same scheme, so there’s no need to set the scheme every session. Storing a directory from one terminal makes it available in any other terminal.&lt;/li&gt;
		&lt;li&gt;You can also temporarily override the working scheme in a particular shell by just setting the value of the environment variable &lt;code&gt;WDSCHEME&lt;/code&gt;. If this variable is set, it’s used instead of the current scheme on disk.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Working Directory has been available for some years and gets constant daily use by its small community. Most people who’ve started using it never stop! Lately you can fetch the &lt;a href="http://github.com/karlin/working-directory"&gt;source from github&lt;/a&gt; or &lt;a href="http://github.com/downloads/karlin/working-directory/wd-1.12.tar.gz"&gt;download the latest stable release directly&lt;/a&gt; from the project’s Downloads area.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=OsTqYX9JJyA:dUhbheAZ9t4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=OsTqYX9JJyA:dUhbheAZ9t4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=OsTqYX9JJyA:dUhbheAZ9t4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=OsTqYX9JJyA:dUhbheAZ9t4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=OsTqYX9JJyA:dUhbheAZ9t4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=OsTqYX9JJyA:dUhbheAZ9t4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=OsTqYX9JJyA:dUhbheAZ9t4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=OsTqYX9JJyA:dUhbheAZ9t4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/OsTqYX9JJyA" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/06/11/working-faster-with-working-directory</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Joseph Roth</name>
      <uri>http://www.atomicobject.com/pages/Joseph+Roth</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-06-09:45058</id>
    <published>2010-06-09T13:11:00Z</published>
    <updated>2010-06-09T14:17:31Z</updated>
    <category term="Agile Practices" />
    <category term="Test Driven Development" />
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/vSk1DbgJSaQ/an-interns-first-impressions" rel="alternate" type="text/html" />
    <title>An intern's first impressions of agile at AO </title>
<content type="html">
            &lt;p&gt;I am a student at &lt;a href="http://gvsu.edu"&gt;Grand Valley State University&lt;/a&gt;, and I have the privilege of interning at &lt;a href="http://www.atomicobject.com"&gt;Atomic Object&lt;/a&gt; this summer. AO has a good relationship with the school, and I had heard quite a bit about the company. When I was looking for an internship in the summer, I placed AO at the top of my list for local companies, but I secretly hoped that I could get accepted to a bigger corporation. Motorola labs scaled back their internship program and my interview with Apple never materialized into a job. Fortunately, Atomic was willing to invest in me this summer. After 4 weeks, I am glad that the other companies turned me down.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Agile is people-centric.&lt;/strong&gt; On my first day, when the employees welcomed me at the &lt;a href="http://spin.atomicobject.com/2009/07/07/10-reasons-we-have-daily-stand-up-meetings"&gt;standup meeting&lt;/a&gt;, the focus on relationships was evident. The office is free of cubicles and open to everyone. This creates an atmosphere where ideas are easily transferable and people are free to communicate. I was pleased to attend an Atomic Spin Down, where the employees and their families enjoyed a Friday night at the office socializing and playing Rock Band. The employees clearly love their job and working with each other.&lt;/p&gt;


	&lt;p&gt;The care for the individual continues with Atomic’s clients. It is evident that AO works hard to make sure the clients’ projects succeed. On my second day at work, I was able to participate in a &lt;a href="http://www.atomicobject.com/pages/Strategy"&gt;Research, Design, and Planning&lt;/a&gt; session where we analyzed the potential users of an application. The client arrived to the meeting with their ideas already formulated for the application. After a little bit of prodding, they were excitedly creating &lt;a href="http://spin.atomicobject.com/2009/04/06/personas-are-design"&gt;personas&lt;/a&gt; of the users. When they left, all parties involved had a deeper understanding of the application. Instead of working with stacks of requirements, AO seeks to understand people.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Agile is test-driven.&lt;/strong&gt; I have to admit that when I first saw &lt;a href="http://www.atomicobject.com/pages/Testing"&gt;test-driven development&lt;/a&gt;, I was a little skeptical. The tests seemed really narrow in scope and I thought you had to write twice as much code. I am still learning a lot about testing, but I definitely appreciate a full suite of tests double-checking our code. Programmers like to trick themselves into believing that they never make mistakes and can always remember what every method does. In reality, we are not perfect. Writing test may take a little more initial investment, but it reduces time tracking down bugs. My current project has made major changes mid-stride. Refactoring code is usually an arduous task, but the tests ease the process.&lt;/p&gt;


	&lt;p&gt;I have soaked up a ton of information in 4 weeks, and I hope to continue learning across the remainder of the summer. If you are looking to learn more about agile practices, I recommend reading some of the books I have read this past month.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.amazon.com/Pragmatic-Programmer-Andrew-Hunt/dp/020161622X/"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658/"&gt;Extreme Programming Explained&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=vSk1DbgJSaQ:kzzyevptUUg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=vSk1DbgJSaQ:kzzyevptUUg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=vSk1DbgJSaQ:kzzyevptUUg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=vSk1DbgJSaQ:kzzyevptUUg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=vSk1DbgJSaQ:kzzyevptUUg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=vSk1DbgJSaQ:kzzyevptUUg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=vSk1DbgJSaQ:kzzyevptUUg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=vSk1DbgJSaQ:kzzyevptUUg:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/vSk1DbgJSaQ" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/06/09/an-interns-first-impressions</feedburner:origLink></entry>
  <entry xml:base="http://spin.atomicobject.com/">
    <author>
      <name>Mary O'Neill</name>
      <uri>http://www.atomicobject.com/pages/Mary+O'Neill</uri>
    </author>
    <id>tag:spin.atomicobject.com,2010-06-07:45021</id>
    <published>2010-06-07T17:14:00Z</published>
    <updated>2010-06-07T17:15:12Z</updated>
    <link href="http://feedproxy.google.com/~r/atomic_spin/~3/5xoY5k7cd0k/a-good-year-for-the-AO-roses" rel="alternate" type="text/html" />
    <title>A Good Year for the AO Roses</title>
<summary type="html">&lt;p&gt;&lt;a href="http://www.elviscostello.com"&gt;Elvis Costello&lt;/a&gt; sings the melancholy tune, “A Good Year for the Roses.”  The song has stuck with me, but the sad sentiment doesn’t match the colorful riot of rose blooms showing in &lt;a href="http://www.atomicobject.com/pages/Find+Us"&gt;Atomic Object’s&lt;/a&gt; parking lot this summer.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/7/Single_White_Rose.jpg?1275927466"&gt;&lt;/div&gt;</summary><content type="html">
            &lt;p&gt;&lt;a href="http://www.elviscostello.com"&gt;Elvis Costello&lt;/a&gt; sings the melancholy tune, “A Good Year for the Roses.”  The song has stuck with me, but the sad sentiment doesn’t match the colorful riot of rose blooms showing in &lt;a href="http://www.atomicobject.com/pages/Find+Us"&gt;Atomic Object’s&lt;/a&gt; parking lot this summer.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/7/Single_White_Rose.jpg?1275927466"&gt;&lt;/div&gt;
&lt;p&gt;About five years ago, in the midst of the &lt;a href="http://spin.atomicobject.com/2010/01/19/human-activity-in-our-old-building"&gt;monster renovation&lt;/a&gt; of our building, it was obvious we needed to clean up and green up the parking lot area near the entrance to &lt;span class="caps"&gt;AOHQ&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Having lived in homes surrounded by shade trees, I was excited about the opportunity to plant this narrow strip so graced with sun most of the day.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://gardening.about.com/od/rose1/a/Rose_Gardening.htm"&gt;Roses&lt;/a&gt; love sun. I have always loved roses, especially old-fashioned climbing roses. My mom was an accomplished rose gardener in her time and I was inspired to honor her in a way that all our parking lot visitors could also enjoy.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/7/roses.jpg?1275927151"&gt;&lt;/div&gt;

	&lt;p&gt;So, with the help of my friend Mary Bereza, I planted a long row of deep red (&lt;a href="http://davesgarden.com/guides/pf/go/55944/"&gt;Don Juan&lt;/a&gt;), soft white (&lt;a href="http://davesgarden.com/guides/pf/go/160946/"&gt;White Eden&lt;/a&gt;) and petal pink (&lt;a href="http://davesgarden.com/guides/articles/view/1203/"&gt;Zephurin Drouhin&lt;/a&gt;) climbing roses along our sun-drenched fence.&lt;/p&gt;


	&lt;p&gt;Our neighbors, &lt;a href="http://www.bazzani.com"&gt;Bazzani Associates&lt;/a&gt; added more roses to their section of the long fence garden.  The name of this lovely pink and white stripe rose escapes me at the moment.&lt;/p&gt;


&lt;div&gt;&lt;img src="https://spin.atomicobject.com/assets/2010/6/7/Pink-White_Rose.jpg?1275927601"&gt;&lt;/div&gt;

	&lt;p&gt;It has taken awhile for the roses to really come into their own.  Each year the cains strengthen, send out new branches and produce a few more blooms than last year. This year has truly been a good year for our roses.&lt;/p&gt;


	&lt;p&gt;Thanks to my mom, JoAnn O’Neill, for showing me what’s to love about roses and thanks to Rose Van Reken, &lt;a href="http://www.atomicobject.com/pages/Marissa+Christy"&gt;Marissa Christy’s&lt;/a&gt; mom, for taking these pictures and capturing the beauty of &lt;a href="http://www.atomicobject.com"&gt;AO’s&lt;/a&gt; roses this year.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=5xoY5k7cd0k:bOae1hKt33g:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=5xoY5k7cd0k:bOae1hKt33g:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=5xoY5k7cd0k:bOae1hKt33g:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=5xoY5k7cd0k:bOae1hKt33g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=5xoY5k7cd0k:bOae1hKt33g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=5xoY5k7cd0k:bOae1hKt33g:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?i=5xoY5k7cd0k:bOae1hKt33g:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/atomic_spin?a=5xoY5k7cd0k:bOae1hKt33g:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/atomic_spin?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/atomic_spin/~4/5xoY5k7cd0k" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://spin.atomicobject.com/2010/06/07/a-good-year-for-the-AO-roses</feedburner:origLink></entry>
</feed>
