<?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:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkANQXs4eCp7ImA9WhRVE0w.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326</id><updated>2012-01-11T16:53:10.530-05:00</updated><category term="bs" /><category term="git" /><category term="clojure" /><category term="DSL" /><category term="antlr" /><category term="tdd" /><category term="productive programmer" /><category term="tooling" /><category term="eclipse" /><category term="selenium" /><category term="productivity" /><category term="testing" /><category term="philosophy" /><category term="proverbs" /><title>zdsbs</title><subtitle type="html">Zachary D. Shaw&lt;br&gt;
Just Another Software Developer</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://zdsbs.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>59</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/zdsbs" /><feedburner:info uri="blogspot/zdsbs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C0QBQXo7fSp7ImA9Wx9VFk0.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7792957570405889012</id><published>2011-02-01T17:41:00.003-05:00</published><updated>2011-02-01T18:02:30.405-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-01T18:02:30.405-05:00</app:edited><title>Code reviews suck</title><content type="html">&lt;p&gt;I don't know about you but when ever I hear someone talking about doing or participating in a code review I'm always skeptical of the value people will get out of it. I have visions of a bunch of people sitting around , criticizing code, or focusing on boring parts... I don't know exactly what I envision, except for bad times. The words don't have negative connotation, but the history of the activity is focused on the negative and not the positive. You know what? That sucks, code reviews suck! I want to get excited about your code because I'm sure you're doing some awesome stuff.

&lt;p&gt;Code has warts, it always does, but you're also doing some cool shit. I'm not going to participate in code reviews any longer, if your code is so bad that I can't get excited about it then the last thing I was to do is look at in a group. No more code reviews, just show me the awesome stuff you did. That sounds like fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7792957570405889012?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/Cn3AcePirIo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7792957570405889012/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7792957570405889012" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7792957570405889012?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7792957570405889012?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/Cn3AcePirIo/code-reviews-suck.html" title="Code reviews suck" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2011/02/code-reviews-suck.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUMRXc9fyp7ImA9Wx5REkk.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-458399295728450700</id><published>2010-08-19T16:03:00.003-04:00</published><updated>2010-08-19T16:04:44.967-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-19T16:04:44.967-04:00</app:edited><title>Starting an XP Team</title><content type="html">&lt;p&gt;Driving home on July 4th weekend I had the sudden realization, not only did I desperately want to work as a part of an XP team, I thought it might be possible. If I could get two other devs, they could move into my office, we could get one more computer and we could all practice XP. Do pair programming, become a tight knit team, everything a guy could ask for. The challenge was convincing management and getting the two other people. I had a feeling getting the resources was going to be the most difficult part.

&lt;p&gt;I had a few prerequisites for forming an XP team that was going to make it hard:
&lt;ol&gt;
&lt;li&gt;Everyone needed to be full-time on the team
&lt;li&gt;No remote devs
&lt;li&gt;I wanted particular devs to be on the team
&lt;/ol&gt;

&lt;p&gt;
Why these prerequisites?
&lt;ul&gt;
&lt;li&gt;"Everyone needed to be full-time on the team" - To me this was a no brainer. I wanted to build a team, and I couldn't see how to build a cohesive group when you had people popping on and off constantly.
&lt;li&gt;"No remote devs" - I've never been on an XP team or any team for that matter, never mind starting one. Having the additional challenge of working with remote people I felt would have set me up for failure. No point in trying if it's going to fail.
&lt;li&gt;"I wanted particular devs to be on the team" - First off, I like and enjoy working with all my co-workers (Hi all!). There were going to be plenty of issues to work out that come with starting a new team. I felt it was important that we didn't spend too much time arguing about XP practices (TDD, pairing, etc.). There were a few co-workers I had worked closely with and I felt confident we were on the same page. For this first attempt at an XP team I thought it was important to have them be a part of it.
&lt;/ul&gt;

&lt;p&gt;
Why were these challenges for my company?
&lt;ul&gt;&lt;li&gt;"Everyone needed to be full-time on the team" - Traditionally people work on 2-3 projects at one time, this means getting full-time resources requires some serious shifting of work.
&lt;li&gt;"No remote devs" - Every project leader at my company prefers on-site devs. Giving my project 2 full-time devs means other projects have to rely more on remote devs. I like the other project leaders, I didn't want to make them mad by "stealing" their resources (Nor did management).
&lt;li&gt;"I wanted particular devs to be on the team" - The two developers had some other commitments to projects, so it was going to be difficult to free them from those commitments.
&lt;/ul&gt;
&lt;p&gt;
Anyway enough background. Monday morning I was still bubbling with excitement. I talked with our VP of Operations to see if she thought I was crazy or if it might be possible. She seemed to think the idea was interesting, but there was a wrinkle, a big wrinkle. I could get a smattering of part time in house devs or some full-time remote devs, but getting two full-time in house devs on one project was just impossible. The question I asked myself was, "Is there something that can be done to still make this team a reality?" The company didn't have the resources to have three people full-time on one project, but what if the team worked on two projects? Two projects, three people, two computers and one office. Two projects would be more challenging for the team, but it still seemed doable. Our VP also thought it was a possibility. 
&lt;p&gt;
I floated the idea a little more, people seemed interested especially our new VP of Technology. He was fully on-board and championed the creation of the team. Everyone thought it was an experiment worth trying, and now I'm a member of a three person XP team. Last Friday we completed our first iteration and I couldn't be having more fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-458399295728450700?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/fvJgBV7mwco" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/458399295728450700/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=458399295728450700" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/458399295728450700?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/458399295728450700?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/fvJgBV7mwco/starting-xp-team.html" title="Starting an XP Team" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2010/08/starting-xp-team.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QDRXY4cCp7ImA9WxFRGU8.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-2657193483617243265</id><published>2010-05-03T18:58:00.005-04:00</published><updated>2010-05-03T19:29:34.838-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-03T19:29:34.838-04:00</app:edited><title>I hate looping / iterating / eaching</title><content type="html">&lt;p&gt;I really hate looping. I mean I really hate looping. Why is that you ask? Because most of the time our looping is not looping. You're filtering, you're transforming or you're calculating, you're not looping. Looping is a means to an end. You loop to perform those actions. But syntactically it's quite common in many languages to see something like: for (blah in blahs) do some filtering / transforming / what ever. Why does the statement "for (blah in blahs)" come first? why isn't it blahs.filter(some predicate) or filter(blahs predicate) or blahs.transform(some stuff) or really so many other options. Why isn't the intent of transforming / filtering / calculating brought to the forefront? 
&lt;p&gt;
I love clojure's solutions to the issue: filter, map, reduce. You can get rid of 99% of all your looping and describe better what you're trying to do. I've been trying this in java (I know I know it's a mistake)... with &lt;a href="http://code.google.com/p/google-collections/"&gt;google collections&lt;/a&gt;. I mean great they have filter, transform, this will look great. It really doesn't:

&lt;pre&gt;&lt;blockquote&gt;
  List&lt;Foo&gt; filtered = new ArrayList&lt;Foo&gt;(
    Collections2.filter(foos, new Predicate&lt;Foo&gt;() {
     @Override
     public boolean apply(Foo foo) {
      return foo.isBar() &amp;&amp; foo.isBaz();
     }
    }));
&lt;/blockquote&gt;&lt;/pre&gt;
vs
&lt;pre&gt;&lt;blockquote&gt;
  List&lt;foo&gt; filtered = new ArrayList&lt;Foo&gt;();
  for (Foo foo : foos) {
   if (foo.isBar() &amp;&amp; foo.isBaz()) {
    filtered.add(foo);
   }
  }
&lt;/blockquote&gt;&lt;/pre&gt;
&lt;p&gt;
Well fine I'm maintaining intent (I guess) by using a filter method and a predicate, but the whole filter mechanism gets completely lost in all the boiler plate java cruft. I love that I can just implement an apply method, highlighting the boolean expression, and the magic is done for me, but I need so much more code to get my work done. Sure I'm removing duplication of looping (which is nice) but at such a legibility cost. Maybe I'll get used to all the crazy syntax, and it will just fade into the background, but for the moment I'm really  doubting it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-2657193483617243265?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/Q1flcJ_bXBQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/2657193483617243265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=2657193483617243265" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/2657193483617243265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/2657193483617243265?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/Q1flcJ_bXBQ/i-hate-looping-iterating-eaching.html" title="I hate looping / iterating / eaching" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2010/05/i-hate-looping-iterating-eaching.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQNQnc4fip7ImA9WxFTF04.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-5283563584730788663</id><published>2010-04-08T10:00:00.003-04:00</published><updated>2010-04-08T10:36:33.936-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-08T10:36:33.936-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tdd" /><category scheme="http://www.blogger.com/atom/ns#" term="philosophy" /><title>TDD Starting Points + Roman Numerals Kata</title><content type="html">&lt;p&gt;I worked on the &lt;a href="http://github.com/zdsbs/roman-numerals"&gt;roman numerals kata&lt;/a&gt; this week with danp, and learned some new things about TDD and approaching a problem. Where you start with TDD and what kind of insights you can draw from a domain before you start really effect your direction. As I'm typing this it seems incredibly obvious, but it was still a good lesson for me to learn.&lt;/p&gt;
&lt;p&gt;We started the kata few times and scrapped our code each time as we started realizing our approach wasn't quite what we were looking for. Honestly if I hadn't had a pair, I probably wouldn't have started over so many times, or pushed quite so hard to find a better way to look at the problem.&lt;/p&gt;
&lt;p&gt;What did we start with? We started with the tests. Each time we tried the problem, we picked what we thought was the simplest test and then picked what we thought was the next simplest test. What we found was that we were backing ourselves into corners in our implementation because our tests weren't actually very good starting points.&lt;/p&gt;
&lt;p&gt;I'm thinking TDD is like a &lt;a href="http://en.wikipedia.org/wiki/Hill_climbing"&gt;hill climber&lt;/a&gt; where you start really matters. In a way that is the challenge TDD presents you with: What is simplest thing to start with?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-5283563584730788663?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/3VfC5GRkbhQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/5283563584730788663/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=5283563584730788663" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5283563584730788663?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5283563584730788663?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/3VfC5GRkbhQ/tdd-starting-points-roman-numerals-kata.html" title="TDD Starting Points + Roman Numerals Kata" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2010/04/tdd-starting-points-roman-numerals-kata.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQEQ3k9cCp7ImA9WxBXGEQ.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7121305057239703946</id><published>2010-01-30T16:39:00.008-05:00</published><updated>2010-01-30T19:21:42.768-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-30T19:21:42.768-05:00</app:edited><title>Generating EJB3 classes from a database</title><content type="html">&lt;p&gt;Generating EJB3 classes from a database is not that hard. Yay! First you need to download and unzip &lt;a href="https://www.hibernate.org/6.html"&gt;hibernate tools&lt;/a&gt;. You'll want to have the &lt;a href="https://www.hibernate.org/hib_docs/tools/reference/en/html/ant.html"&gt;hibernate tools docs&lt;/a&gt; at hand. Next you need to grab a bunch of jars. Almost all the jars can be found in /plugins/org.hibernate.eclipse.x.x.x/lib/tools/hibernate-tools.jar . Then download ejb3-persistence.jar. Below are all the jars I collected. Don't worry about overkill, you're not going to include any of these jars in your distribution.

&lt;pre&gt;&lt;blockquote&gt;
antlr-2.7.6.jar    dom4j-1.6.1.jar    hibernate3.jar    jtidy-r8-20060801.jar
asm-attrs.jar    ehcache-1.2.3.jar   jaas.jar    log4j-1.2.15.jar
asm.jar     ejb3-persistence.jar   javassist.jar    lucene-core-2.2.0.jar
bsh-2.0b1.jar    freemarker.jar    jboss-cache.jar    oscache-2.1.jar
c3p0-0.9.1.jar    hibernate-annotations.jar  jboss-common.jar   postgresql-8.4-701.jdbc3.jar
cglib-2.1.3.jar    hibernate-commons-annotations.jar jboss-jmx.jar    proxool-0.8.3.jar
commons-collections-2.1.1.jar  hibernate-entitymanager.jar  jboss-system.jar   swarmcache-1.0rc2.jar
commons-logging-1.0.4.jar  hibernate-search.jar   jdbc2_0-stdext.jar
concurrent-1.3.2.jar   hibernate-tools.jar   jgroups-2.2.8.jar
connector.jar    hibernate-validator.jar   jta.jar
&lt;/blockquote&gt;&lt;/pre&gt;
&lt;p&gt;Now create your build.xml file:

&lt;pre&gt;&lt;blockquote&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project name=&amp;quot;my-proj&amp;quot; default=&amp;quot;gen_hibernate&amp;quot; basedir=&amp;quot;.&amp;quot;&amp;gt;
        &amp;lt;property name=&amp;quot;src&amp;quot; location=&amp;quot;src&amp;quot; /&amp;gt;
        &amp;lt;property name=&amp;quot;build&amp;quot; location=&amp;quot;build&amp;quot; /&amp;gt;
        &amp;lt;property name=&amp;quot;generated&amp;quot; location=&amp;quot;generated&amp;quot; /&amp;gt;

        &amp;lt;path id=&amp;quot;toolslib&amp;quot;&amp;gt;
          &amp;lt;fileset dir=&amp;quot;${basedir}&amp;quot;&amp;gt;
             &amp;lt;include name=&amp;quot;lib/*.jar&amp;quot;/&amp;gt;
          &amp;lt;/fileset&amp;gt;
        &amp;lt;/path&amp;gt;

        &amp;lt;taskdef name=&amp;quot;hibernatetool&amp;quot;
                 classname=&amp;quot;org.hibernate.tool.ant.HibernateToolTask&amp;quot;
                 classpathref=&amp;quot;toolslib&amp;quot; /&amp;gt;

        &amp;lt;target name=&amp;quot;gen_hibernate&amp;quot;&amp;gt;
                &amp;lt;hibernatetool&amp;gt;
                        &amp;lt;jdbcconfiguration
                                packagename=&amp;quot;com.my.proj&amp;quot;
                            configurationfile=&amp;quot;hibernate.cfg.xml&amp;quot;
                                detectManytoMany=&amp;quot;true&amp;quot;
                                detectOptimisticLock=&amp;quot;true&amp;quot;&amp;gt;
                          &amp;lt;/jdbcconfiguration&amp;gt;
                        &amp;lt;hbm2hbmxml destdir=&amp;quot;${generated}&amp;quot; /&amp;gt;
                &amp;lt;/hibernatetool&amp;gt;
        &amp;lt;/target&amp;gt;

        &amp;lt;target name=&amp;quot;gen_java&amp;quot; depends=&amp;quot;gen_hibernate&amp;quot;&amp;gt;
                &amp;lt;hibernatetool destdir=&amp;quot;${src}&amp;quot;&amp;gt;
                        &amp;lt;annotationconfiguration configurationfile=&amp;quot;hibernate.cfg.xml&amp;quot;&amp;gt;
                                &amp;lt;fileset dir=&amp;quot;${generated}&amp;quot;&amp;gt;
                                &amp;lt;include name=&amp;quot;**/*.hbm.xml&amp;quot;/&amp;gt;
                                &amp;lt;/fileset&amp;gt;
                        &amp;lt;/annotationconfiguration&amp;gt;
                        &amp;lt;hbm2java jdk5=&amp;quot;true&amp;quot; ejb3=&amp;quot;true&amp;quot;/&amp;gt;
                &amp;lt;/hibernatetool&amp;gt;
        &amp;lt;/target&amp;gt;

        &amp;lt;target name=&amp;quot;compile&amp;quot; depends=&amp;quot;gen_java&amp;quot;&amp;gt;
                &amp;lt;mkdir dir=&amp;quot;${build}/classes&amp;quot; /&amp;gt;
                &amp;lt;javac srcdir=&amp;quot;${src}&amp;quot; destdir=&amp;quot;${build}/classes&amp;quot; classpathref=&amp;quot;toolslib&amp;quot; /&amp;gt;
        &amp;lt;/target&amp;gt;

        &amp;lt;target name=&amp;quot;jar&amp;quot; depends=&amp;quot;compile&amp;quot;&amp;gt;
                &amp;lt;jar destfile=&amp;quot;my-proj.jar&amp;quot; basedir=&amp;quot;${build}/classes&amp;quot; /&amp;gt;
        &amp;lt;/target&amp;gt;
        &amp;lt;target name=&amp;quot;clean&amp;quot;&amp;gt;
                &amp;lt;delete dir=&amp;quot;${build}&amp;quot; /&amp;gt;
                &amp;lt;delete dir=&amp;quot;${src}&amp;quot; /&amp;gt;
                &amp;lt;delete dir=&amp;quot;${generated}&amp;quot; /&amp;gt;
        &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;

&lt;p&gt;If you're using postgres your hibernate.cfg.xml file should look like:
&lt;pre&gt;&lt;blockquote&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE hibernate-configuration PUBLIC
                &amp;quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&amp;quot;
                &amp;quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&amp;quot;&amp;gt;
&amp;lt;hibernate-configuration&amp;gt;
        &amp;lt;session-factory name=&amp;quot;myproj&amp;quot;&amp;gt;
                &amp;lt;property name=&amp;quot;hibernate.connection.driver_class&amp;quot;&amp;gt;org.postgresql.Driver&amp;lt;/property&amp;gt;
                &amp;lt;property name=&amp;quot;hibernate.connection.url&amp;quot;&amp;gt;jdbc:postgresql://your-url&amp;lt;/property&amp;gt;
                &amp;lt;property name=&amp;quot;hibernate.connection.username&amp;quot;&amp;gt;your-username&amp;lt;/property&amp;gt;
                &amp;lt;property name=&amp;quot;hibernate.connection.password&amp;quot;&amp;gt;your-password&amp;lt;/property&amp;gt;
                &amp;lt;property name=&amp;quot;hibernate.dialect&amp;quot;&amp;gt;org.hibernate.dialect.PostgreSQLDialect&amp;lt;/property&amp;gt;
        &amp;lt;/session-factory&amp;gt;
&amp;lt;/hibernate-configuration&amp;gt;
&amp;lt;/pre&amp;gt;&amp;lt;/blockquote&amp;gt;
&lt;/blockquote&gt;&lt;/pre&gt;
&lt;p&gt;run ant jar and you should be good to go!
&lt;p&gt;Depending on how you're setup you should also consider running &amp;lt;hbm2cfgxml ejb3="true"&amp;gt; it creates a nice hibernate.cfg.xml file with all the classes and your DB connection info.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7121305057239703946?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/dS9E6bAe3e8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7121305057239703946/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7121305057239703946" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7121305057239703946?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7121305057239703946?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/dS9E6bAe3e8/generating-ejb3-classes-from-database.html" title="Generating EJB3 classes from a database" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2010/01/generating-ejb3-classes-from-database.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08NRHc7cCp7ImA9WxBQGUs.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-6641082218875789916</id><published>2010-01-19T22:45:00.003-05:00</published><updated>2010-01-19T23:31:35.908-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-19T23:31:35.908-05:00</app:edited><title>Dependency Injection Frameworks - A Rant</title><content type="html">&lt;p&gt;Uncle Bob has a great post on &lt;a href="http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion"&gt;dependency injection frameworks&lt;/a&gt;. I'm so glad he wrote that article. There is precious little out there (maybe this is the only article) about why the DI frameworks suck and why DI is great. To be clear DI by hand works very well. And if all you need to do is DI, rolling it by hand is just as good as using a framework. In fact it wasn't until recently that I even saw a point to DI frameworks at all.

&lt;p&gt;The only argument about DI frameworks that ever made much sense to me was that DI frameworks are great if you want to run your application with different configurations. But when do you want different configurations? Seriously when? For me, the only time I've wanted different configurations is for testing. Not unit or automated testing, but testing in the sense of I want to run the app and I don't want to hit prod. 
&lt;p&gt;But why do you need a framework to do that? Maybe you have a different main method. Or maybe you have a properties file. But if all you need are different configurations, a DI framework is an expensive price to pay.

&lt;p&gt;What are the costs? Besides needing to learn a new framework, the DI frameworks are like a cancer. Once you start using them they invade and don't stop invading. You start @Autowiring and @Inject-ing and soon your whole app is cluttered with that crap. Not to mention the XML configs or Guice modules floating around. Maybe I'm doing it wrong, but why do I even want to invest the time to learn how to do it right? The benefits of using the frameworks seem so slim it's doesn't seem worth my time.

&lt;p&gt;However, I did get convinced recently that using Spring DI was the correct choice for a web app I'm working on. Why? Because when Spring manages your objects it does some magic with transactions and sessions and it's all pretty convenient. I still hate it! And it feels wrong. And I believe you can get the magic without the DI. It's a question of how much do you want to fight against your framework. For my current project the answer was clear, not that much.
&lt;p&gt;The only value I get out of using Spring's DI is the magic it does in the background. Their DI is total crap. If you don't need the magic, it's hard to understand why you need the framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-6641082218875789916?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/N2IckGEXP6M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/6641082218875789916/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=6641082218875789916" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6641082218875789916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6641082218875789916?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/N2IckGEXP6M/dependency-injection-frameworks-rant.html" title="Dependency Injection Frameworks - A Rant" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2010/01/dependency-injection-frameworks-rant.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4AQXo5cCp7ImA9WxNVGE8.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7121609022258389363</id><published>2009-10-28T17:54:00.008-04:00</published><updated>2009-10-29T11:09:00.428-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-29T11:09:00.428-04:00</app:edited><title>Abstract Class Smell</title><content type="html">&lt;p&gt;PLEASE SEE THE UPDATES BELOW, I didn't realize that my issue was with the &lt;a href="http://en.wikipedia.org/wiki/Template_method_pattern"&gt;Template Method Pattern&lt;/a&gt;.
&lt;br&gt;------------------------------------------------------------------------
&lt;br&gt;Original Post:

&lt;p&gt;I coded up a smell today, I had an abstract class who's public methods were calling the abstract implementations. Here's kind of what it looked like:

&lt;blockquote&gt;&lt;pre&gt;
public abstract class Foo {
  abstract SomeObj foo();
  abstract SomeObj bar();
  public void somethingFooDoes() {
      SomeObj a = foo();
      SomeObj b = bar();
     //do some stuff with a + b
  }
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;How did I get here you might ask.  Well, there were going to be two implementations of Foo, a prod implementation and a sandbox implementation.  I started off with Foo as an interface and began coding up the Prod + Sandbox impls.  It turned out that the prod and sandbox implementations had really similar structures.  So, I made Foo an abstract class and moved the common stuff in there.  A few more refactorings and Foo ended up looking like it does above.  It then dawned on me, Foo was really using different strategies to get at the SomeObjs, I refactored to the strategy pattern:
&lt;blockquote&gt;&lt;pre&gt;
public class Foo {
  private final SomeObjProducer someObjProducer;
  public Foo(SomeObjProducer someObjProducer) {
     this.someObjProducer = someObjProducer;
  }
  public void somethingFooDoes() {
      SomeObj a = someObjProducer.foo();
      SomeObj b = someObjProducer.bar();
     //do some stuff with a + b
  }
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now Foo has become concrete and is configurable with the different strategies for producing SomeObjs. To me this code is much more flexible and it now has collaborators.  Where in the Abstract implementation it was kind of collaborating with itself (yuck!)&lt;p&gt;What's the moral of the story? If you have an abstract class and you find yourself calling abstract methods in your concrete methods (whoa that's a mouthful) consider refactoring to the strategy pattern.

&lt;p&gt;UPDATE: a co-worker correctly pointed out that the first code snippet of Foo was the &lt;a href="http://en.wikipedia.org/wiki/Template_method_pattern"&gt;Template Method Pattern&lt;/a&gt;.  Maybe it's too broad a statement, but it seems that anytime you have a template method pattern you could refactor it into the strategy pattern.  Taking your inheritance based code and refactoring it into composition based code. Context is king, but these days I certainly favor composition over inheritance.

&lt;p&gt;UPDATE AGAIN: I received some good complaints regarding my code sample. 
&lt;p&gt;Imagine using the more standard Game example from wikipedia (but simplified for brevity)

&lt;blockquote&gt;&lt;pre&gt;
public abstract class Game {

 public void playOneGame() {
  while(!endOfGame()) {
   makePlay();
  }
 }

 public abstract boolean endOfGame();
 public abstract void makePlay();
}
&lt;/pre&gt;&lt;/blockquote&gt;

This could be refactored to use composition instead of inheritance, where Game is now an interface.

&lt;blockquote&gt;&lt;pre&gt;
public class GamePlayer {
 private Game game;
 public GamePlayer(Game game) {
  this.game = game;
 }

 public void playOneGame() {
  while(!game.endOfGame()) {
   game.makePlay();
  }
 }
}
&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7121609022258389363?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/9hYU-qYibv4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7121609022258389363/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7121609022258389363" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7121609022258389363?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7121609022258389363?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/9hYU-qYibv4/abstract-class-smell.html" title="Abstract Class Smell" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/10/abstract-class-smell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIGRX08cCp7ImA9WxNWFU4.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-492053689481709222</id><published>2009-10-13T22:52:00.007-04:00</published><updated>2009-10-14T11:18:44.378-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-14T11:18:44.378-04:00</app:edited><title>Hollywood Dilemma</title><content type="html">At &lt;a href="http://sdtconf.com"&gt;sdtconf&lt;/a&gt; over the weekend I led an open spaces discussion about the Hollywood Principle and testing. &lt;a href="http://www.agiledeveloper.com"&gt;Venkat Subramaniam&lt;/a&gt; took the time to post a really thoughtful &lt;a href="http://www.agiledeveloper.com/blog/CommentView.aspx?guid=8b6d0c24-1b69-4df2-9ddd-de86c3556688"&gt;article about it&lt;/a&gt;. I'll quote it below, but it is worth reading!
&lt;p&gt;
The discussion was around the cost and reason for inverting control, Venkat provided a toy problem which we twisted for our own purposes, we modeled a paper boy. The paper boy requests payment from a customer and the customer can either pay or stiff the paper boy.
&lt;p&gt;
I argued for the following:
&lt;p&gt;
&lt;blockquote&gt;&lt;pre&gt;
public class PaperBoy {
  public void collectPayments(List customers) {
    for(Customer customer : customers) {
      customer.getPayment(this, 200);
    }
  }
  //...
&lt;/blockquote&gt;&lt;/pre&gt;

And the test
&lt;blockquote&gt;&lt;pre&gt;
Customer customer = mock(Customer.class);
PaperBoy paperBoy = new PaperBoy();
//set up a payment to be collected;
paperBoy.collectPayments(customer);
verify(customer).getPayment(paperBoy,$$$);
&lt;/blockquote&gt;&lt;/pre&gt;

and the Customer
&lt;blockquote&gt;&lt;pre&gt;
public class Customer {
  public void getPayment(PaperBoy paperBoy, int amount) {
    if (hasNoMoney || doesNotCareToPay)
      paperBoy.stiff(this);
    else {
      deductMoney(amount);
      paperBoy.acceptPayment(this, amount);
    }
  }
  //...
&lt;/blockquote&gt;&lt;/pre&gt;

and the Test
&lt;blockquote&gt;&lt;pre&gt;
Customer customer = new Customer(someMoney and a bad attitude);
PaperBoy paperBoy = mock(PaperBoy.class);
customer.getPayment(paperBoy,$$$);
verify(paperBoy).stiff(customer);
&lt;/blockquote&gt;&lt;/pre&gt;

etc. for the other cases.

Venkat points out some issues with this kind of implementation that I'd like to address:
&lt;blockquote&gt;
Problem 1. The above code has some unnecessary coupling and bi-directional relationship. The Customer depends
on PaperBoy. That is a coupling that I would seriously question.
&lt;p&gt;
Problem 2. The unit test is now made to do more. It has to create a mock of the PaperBoy. Even if you tell me it is not
much code, a single line of code that is not absolutely needed is a lot of code IMHO. You don't have to maintain code
that you do not write.
&lt;p&gt;
Problem 3. Are you really stiffing the PaperBoy? Who decides that? Can a paperboy decide that under very hard economic
conditions, a loyal customer may be deserves a break? I have no problem the customer deciding to pay or not, but if that is
stiffing or not is for the paperboy to decide IMO.
&lt;/blockquote&gt;
&lt;p&gt;
I'd like to address problem 3 first.  The paper boy can still cut the guy a break, he just does it in his stiff method.  Or maybe it shouldn't be a stiff method, maybe it should be an iWontPayMethod().
&lt;p&gt;
Problem 1. I really don't like the coupling! The coupling would be limited if the Customer was talking to a debt collector interface, and the PaperBoy was talking to a Payee(uhg) interface. But it's still a little smelly. I don't fundamentally see a problem with the bi-directional relationship, but maybe that's just because I haven't coded too much with bi-directional relationships (and maybe there's a good reason for that).
&lt;p&gt;
Problem 2. Let's take a look at Venkat's code + what some tests would look like.

&lt;blockquote&gt;&lt;pre&gt;
public class PaperBoy {
  public void collectPayments(List customers) {
    for(Customer customer : customers) {
      int payment = customer.getPayment(200);
      if (payment &gt; 0)
        acceptPayment(customer, payment);
      else
        stiff(customer);
    }
  }
  //...

public class Customer
{
  public int getPayment(int amount) {
    if (hasNoMoney || doesNotCareToPay)
      return 0;
    else {
      deductMoney(amount);
      return amount;
    }
  }
  //...
&lt;/blockquote&gt;&lt;/pre&gt;

The Customer Tests:
&lt;blockquote&gt;&lt;pre&gt;
Customer customer = new Customer(someMoney and a bad attitude);
assertEquals(0,customer.getPayment($$$);
&lt;/blockquote&gt;&lt;/pre&gt;

So Venkat is correct in this example the mocks add 2 extra lines per test which isn't great. But that's not the whole story.  Let's take a look at the PaperBoy tests.
&lt;blockquote&gt;&lt;pre&gt;
Customer customer = new Customer(someMoney and a bad attitude);
PaperBoy paperBoy = new PaperBoy();
//set up a payment to be collected, let's assume this is one line
paperBoy.collectPayments(customer);
assertTrue(paperBoy.wasStiffedBy(customer);

Customer customer = new Customer(someMoney and a good attitude);
PaperBoy paperBoy = new PaperBoy();
//set up a payment to be collected, let's assume this is one line
paperBoy.collectPayments(customer);
assertTrue(paperBoy.collectedPaymentFrom(customer, $$$);
&lt;/blockquote&gt;&lt;/pre&gt;

I have two issues with the PaperBoy tests:
&lt;ol&gt;
&lt;li&gt;There is an extra test needed, which in terms of maintence is not such a good thing.
&lt;li&gt;The PaperBoy tests are highly coupled to the implementation of the Customer.  This means anytime you change some behavior of the Customer you might have to change your PaperBoy test, not such a big problem for the 2 tests, but if there are 50? if there are 100? that can be bad news.
&lt;/ol&gt;
&lt;p&gt;It's not clear to me that inverting the control is the "right" thing to do, but I think if you're careful (and you want 100% unit test coverage), inverting the control and using mocks can help you cut down on test complexity and test maintenance, so... mock-on?
&lt;p&gt;
Thanks everyone who participated in the discussions!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-492053689481709222?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/Zu0EIiEcZ1o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/492053689481709222/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=492053689481709222" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/492053689481709222?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/492053689481709222?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/Zu0EIiEcZ1o/hollywood-dilemma.html" title="Hollywood Dilemma" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/10/hollywood-dilemma.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IMRHo_cSp7ImA9WxNQF0Q.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-3276511253203667407</id><published>2009-09-22T17:34:00.003-04:00</published><updated>2009-09-24T08:33:05.449-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-24T08:33:05.449-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="philosophy" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="bs" /><title>Contract Tests</title><content type="html">&lt;p&gt;I had a post almost a year ago &lt;a href="http://zdsbs.blogspot.com/2008/11/hard-contracts-vs-soft-contracts.html"&gt;Hard Contracts vs Soft Contracts&lt;/a&gt; that was I reminded of when I came across this post on &lt;a href="http://www.markhneedham.com/blog/2009/09/18/tdd-testing-with-generic-abstract-classes/"&gt;Testing with generic abstract classes&lt;/a&gt;.  At our company we've been using the abstract test case pattern for a while, but have been struggling with naming... why not just call it FooAbstractTest you ask?  Because, well, our build looks for classes that are named Foo*Test* in our test package and tries to run the abstract test cases and it breaks our build.  So like any good software engineer instead of solving the problem, we just tried to work around it (sigh).

&lt;p&gt;Anyway, we were struggling for a good naming convention, the best we could come up with was FooBase (terrible) but then as I mentioned I came across Mark's post, which in turn lead me to this wonderful page on c2 &lt;a href="http://c2.com/cgi-bin/wiki?AbstractTestCases"&gt;http://c2.com/cgi-bin/wiki?AbstractTestCases&lt;/a&gt;.  The first line says it all, "Contract Tests" and really I knew it all along. I had been thinking of them in terms of hard contracts vs. soft contracts.  So now I can feel good about myself and continue being a good software engineer, I have a better name, FooContract.

&lt;p&gt;UPDATE - If you followed the link to the c2 page, you'll see that J. B. Rainsberger is referenced all over the place. Well he just republished his initial thoughts on the &lt;a href="http://www.jbrains.ca/permalink/281"&gt;Contract Test&lt;/a&gt;.  Also, if it wasn't clear, I was being very tongue in cheek about not fixing our build, we should do it, but finding a good name for these kinds of tests is also important.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-3276511253203667407?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/9EaPIMTvN8U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/3276511253203667407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=3276511253203667407" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3276511253203667407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3276511253203667407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/9EaPIMTvN8U/contract-tests.html" title="Contract Tests" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/09/contract-tests.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4NSXczcCp7ImA9WxNSE0U.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-855374499318882330</id><published>2009-08-27T09:57:00.003-04:00</published><updated>2009-08-27T10:23:18.988-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-27T10:23:18.988-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="clojure" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><title>Builder Pattern in Clojure</title><content type="html">&lt;p&gt;We've been working steadily on our toy &lt;a href="http://github.com/zdsbs/trafficsimulation"&gt;traffic simulator&lt;/a&gt; and doing TDD along the way.  Of course a major concept in a traffic simulator is a car, so we of course have a car struct + cars have some behavior patterns so we also have a behavior struct.  They look like:

&lt;blockquote&gt;&lt;pre&gt;
(defstruct behavior :accel-dist :decel-dist)
(defstruct car :name :position :length :speed :behavior)
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;So to construct a valid car you need to do something like:
&lt;blockquote&gt;&lt;pre&gt;
(struct car :a 1 1 1 (struct behavior 10 5)))
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Yikes, we constantly wanted cars for our tests and constructing a car like that was often more code than the real stuff we wanted to test.  So, we made a bunch of convenience methods (object mother type stuff), like:

&lt;blockquote&gt;&lt;pre&gt;
(defn slow-car [name position]
 (struct car name position 1 1 (struct behavior 10 5)))

(defn car-with-speed-position [speed position]
 (struct car :a position 1 speed (struct behavior 10 5)))
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Suddenly we started creating lots of car-with-* methods.  We got annoyed and accidentally started implementing the builder pattern.

&lt;blockquote&gt;&lt;pre&gt;
(defn default-car []
 (struct car :a 1 1 1 (struct behavior 10 5)))

(defn car-with 
 ([key value]
  (assoc (default-car) key value))
 ([key1 value1 key2 value2]
  (assoc (car-with key1 value1) key2 value2)))
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Ignore the total ugliness of the car-with function for a moment, this let us do things like:
&lt;blockquote&gt;&lt;pre&gt;
(def a-car (car-with :speed 1 :position 4))
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;as opposed to:

&lt;blockquote&gt;&lt;pre&gt;
(def a-car (car-with-speed-position 1 4))
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Our new version, was not only easier to read, and didn't make us create new methods for each different thing we wanted to do, but hey, that looks really similar to the builder pattern.  Now I'm sure there are better ways to implement car-with, but it works for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-855374499318882330?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/s-wFDPHWUPw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/855374499318882330/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=855374499318882330" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/855374499318882330?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/855374499318882330?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/s-wFDPHWUPw/builder-pattern-in-clojure.html" title="Builder Pattern in Clojure" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/08/builder-pattern-in-clojure.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYAQH07fCp7ImA9WxNSEkQ.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-8842807459749420642</id><published>2009-08-26T08:22:00.002-04:00</published><updated>2009-08-26T09:09:01.304-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-26T09:09:01.304-04:00</app:edited><title>Null once again</title><content type="html">&lt;p&gt;InfoQ has a nice talk by &lt;a href="http://en.wikipedia.org/wiki/C._A._R._Hoare"&gt;Tony Hoare&lt;/a&gt;, &lt;a href="http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare"&gt;Null References: The Billion Dollar Mistake&lt;/a&gt;.  I've been in a few arguments in that past that languages would be much better without null, so it's nice to hear someone much smarter than myself, who also happens to have invented the null reference regret their existence.  But he doesn't feel as bad as he thinks the C language designers should feel, because he says, they allowed the for the buffer overflow by abusing the get routine.  And that allowed for viruses, which have cost industry much more than his billion dollar mistake.  He's tough on the language designers (and himself): "Language designers should be responsible for the mistakes programmers make".  Thanks Tony, for giving me someone to blame when I muck things up :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-8842807459749420642?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/nqpib42bgFA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/8842807459749420642/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=8842807459749420642" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/8842807459749420642?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/8842807459749420642?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/nqpib42bgFA/null-once-again.html" title="Null once again" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/08/null-once-again.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEAQ3w9fyp7ImA9WxJaEUU.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-4090909766719227451</id><published>2009-08-01T23:20:00.002-04:00</published><updated>2009-08-01T23:27:22.267-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-01T23:27:22.267-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="bs" /><title>Returing Null... again</title><content type="html">&lt;p&gt;so... thinking more about returning null. I'm thinkin' returning null is allowing you to return a second type from a method.  And a null pointer exception is equivalent to a class cast exception. AND a null check if (foo == null) is the same as an instance of check.  

&lt;p&gt;nulls are syntactic sugar for a type!  I refuse to think of them as values for references any longer.  They are types, returning them from functions is returning multiple types from a function (not in a polymorphic way, but in a type system abusing way) and null checks are instance checks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-4090909766719227451?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/LaBnGuA-upQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/4090909766719227451/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=4090909766719227451" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/4090909766719227451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/4090909766719227451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/LaBnGuA-upQ/returing-null-again.html" title="Returing Null... again" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/08/returing-null-again.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEADQX44eyp7ImA9WxJaEUg.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-6997983903821631666</id><published>2009-08-01T14:17:00.005-04:00</published><updated>2009-08-01T14:52:50.033-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-01T14:52:50.033-04:00</app:edited><title>Returning Null</title><content type="html">&lt;p&gt;I've always had a problem with returning null from a method.  And I was reminded of this when reading a post at Misko Hevery's blog about &lt;a href="http://misko.hevery.com/2009/07/31/how-to-think-about-oo/"&gt;how to think about OO&lt;/a&gt;

&lt;p&gt;I think returning null is a problematic, it's often abused as a way to have two different return types from one method.  A quick googling of "returning null" has the suggestion of returning a null object implementation of your return type. Returning a Null Object is appropriate in some cases, but not when you need to signal to your client two different things. Misko's code refactoring show's an example of this. He refactors some login code (I really like the steps he took btw) down to something like:

&lt;blockquote&gt;&lt;pre&gt;
  Cookie login(Ldap ldap) {
    if ( ldap.auth(user, password) )
      return new Cookie(user);
    return null;
  }

&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;When I read this code I see two things (structurally that is)
&lt;ol&gt;&lt;li&gt;If authentication succeeds then notify the client of the successful authentication with a new Cookie
&lt;li&gt;If authentication fails notify the client by returning null
&lt;/ol&gt;
&lt;p&gt;What could a client of this method look like?
&lt;blockquote&gt;&lt;pre&gt;
  public void authenticateUser(User user) {
     Cookie userCookie = user.login(ldap);
     if (userCookie == null) {
           //notify someone that auth failed
     } eles {
           //register them as logged in
     }
  }
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;We're doing the same work twice in each place, but with slightly different syntax, each place we need to check if login failed or not.  What if instead we used &lt;a href="http://martinfowler.com/bliki/InversionOfControl.html"&gt;IoC&lt;/a&gt; / "Tell Don't Ask" / "Hollywood Principle"
&lt;blockquote&gt;&lt;pre&gt;
  Cookie login(Ldap ldap, AuthenticationRegistry authenticationRegistry) {
    if ( ldap.auth(user, password) )
      authenticationRegistry.authSucceeded(new Cookie(user));
    authenticationRegistry.authFailed(user);
  }

&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;and the client
&lt;blockquote&gt;&lt;pre&gt;
  public void authenticateUser(User user) {
     user.login(ldap,this);
  }

  public void authSucceeded(Cookie cookie) {
     //register them as logged in
  }

  public void authFailed(User user) {
     //register them as auth failed
  }
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;This new code is a little more complicated, but I think it is clearer, and more straight forward to implement.  Now we have two entities that are communicating with each-other and we've defined the way in which they are communicating.  Again I liked Misko's refactorings, I'd just take it one step further.  It's all definitely arguable, but I think if you're ever in a situation where you want to be returning two types of data from a method using IoC is the way to go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-6997983903821631666?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/Wa6z9Ub3CzA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/6997983903821631666/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=6997983903821631666" title="16 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6997983903821631666?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6997983903821631666?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/Wa6z9Ub3CzA/returning-null.html" title="Returning Null" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>16</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/08/returning-null.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAGRn05fip7ImA9WxJbEk4.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-2410699448186545267</id><published>2009-07-21T22:43:00.005-04:00</published><updated>2009-07-21T23:18:47.326-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-21T23:18:47.326-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="clojure" /><title>Clojure + Bowling Kata</title><content type="html">&lt;p&gt;Just the other day (yesterday) Uncle Bob had a post about &lt;a href="http://blog.objectmentor.com/articles/2009/07/19/uncle-bob-jsps-learning-clojure"&gt;Learning Clojure&lt;/a&gt;.  He implemented &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata"&gt; a bowling scoring kata&lt;/a&gt;.  So Dan P. and I decided to try it ourselves, but since we're from Boston we implemented candle pin bowling rules:
&lt;p&gt;
As we were talking through designs for this, and as we talked about scoring frames, we realized that there were three cases:
&lt;ol&gt;
&lt;li&gt;Strike – score the first ball, plus the next two ‘bonus’ balls, then remove the first ball (the strike) from the list, then continue scoring.
&lt;li&gt;Spare – score the first two balls, plus the next ‘bonus’ ball, then remove the first two balls (the spare) from the list, then continue scoring.
&lt;li&gt;No-mark – score all three balls in the frame, then remove them from the list, then continue scoring. (Remember: candlepin!)
&lt;/ol&gt;
In all these cases you want to score three balls, the only difference was in how many balls you remove from the list before you continue scoring (i.e., how many balls were in the frame you are removing from the yet-to-be-scored list). So this is what we came up with:

&lt;a href="http://github.com/zdsbs/candlepin-bowling/tree/master"&gt;http://github.com/zdsbs/candlepin-bowling/tree/master&lt;/a&gt;

&lt;blockquote&gt;
&lt;pre&gt;
(ns scorecard)

(defn third [rolls]
    (first (next (next rolls))))

(defn first-two [rolls]
    (+ (first rolls) (second rolls)))

(defn strike? [rolls]
    (= 10 (first rolls)))

(defn spare? [rolls]
    (= 10 (first-two rolls)))

(defn remove-strike [rolls]
    (rest rolls))

(defn remove-spare [rolls]
    (rest (rest rolls)))

(defn remove-normal-frame [rolls]
    (rest (rest (rest rolls))))

(defn remove-frame [rolls]
        (if (strike? rolls)
            (remove-strike rolls)
            (if (spare? rolls)
                (remove-spare rolls)
                (remove-normal-frame rolls))))

(defn score [input-rolls]
    (loop [rolls input-rolls score 0 frame-counter 0]
        (if (or (empty? rolls) (= 10 frame-counter))
            score
            (recur 
                (remove-frame rolls) 
                (+ score (first rolls) (second rolls) (third rolls)) (inc frame-counter)))))

&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the tests:

&lt;blockquote&gt;
&lt;pre&gt;
(ns scorecard-test
    (:use clojure.contrib.test-is 
        scorecard))

(deftest test-third
    (is (= 3 (third [1 2 3 4]))))

(deftest test-first-two
    (is (= 3 (first-two [1 2 3]))))

(deftest test-remove-frame
    (is (= [3 4 5] (remove-frame [0 1 2 3 4 5])))
    (is (= [3 4] (remove-frame [10 3 4])))
    (is (= [5] (remove-frame [6 4 5]))))

(deftest test-remvo-two-frames
    (is (= [] 
        (remove-frame 
            (remove-frame [0 1 2 0 0 0])))))

(deftest test-scores
    (is (= 0 (score [])))
    (is (= 6 (score [1 2 3])))
    (is (= 15 (score [1 2 3 4 5 0])))
    (is (= 19 (score [10 1 2 3])))
    (is (= 17 (score [5 5 1 2 3])))
    (is (= 300 (score [10 10 10 10 10 10 10 10 10 10 10 10])))
    (is (= 19 (score [5 5 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ])))
    (is (= 21 (score [10 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ]))))

&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also check out:
&lt;br&gt;Stuart Halloway's  &lt;a href="http://blog.runcoderun.com/post/145675117/tdd-in-a-functional-language-uncle-bobs-bowling"&gt;implementation&lt;/a&gt;.  Besides just an implementation, he has a great discussion on how to approach the problem in a functional way. (his implementation is much nicer than this one)
&lt;br&gt;Uncle Bob's son over at 8th light also wrote up an &lt;a href="http://blog.8thlight.com/articles/2009/7/20/bowling-in-clojure"&gt;implementation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-2410699448186545267?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/mhXfb1OCHcE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/2410699448186545267/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=2410699448186545267" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/2410699448186545267?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/2410699448186545267?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/mhXfb1OCHcE/clojure-bowling-kata.html" title="Clojure + Bowling Kata" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/07/clojure-bowling-kata.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQHQ30_fip7ImA9WxJbEEs.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-5206639992927899482</id><published>2009-07-19T23:55:00.004-04:00</published><updated>2009-07-20T00:15:32.346-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-20T00:15:32.346-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="git" /><title>Git Commands Part I</title><content type="html">&lt;p&gt;I'm always forgetting a very useful git command, so I'm posting it here in the hopes that: a) writing it down will help me remember and b) if I forget again, at least I can just goto my blog.
&lt;p&gt;git add -u 
&lt;br&gt;(if you're like me and you rename or delete files without calling git rm git add -u takes care of staging the changes)
&lt;p&gt;and thank you Stack Overflow: &lt;a href="http://stackoverflow.com/questions/492558/git-rm-multiple-files-that-have-already-been-deleted-from-disk"&gt;git rm multiple files that have already been deleted from disk&lt;/a&gt;
&lt;p&gt;Oh and if you're pushing a Java project into a git repository, the .git/info/exclude file is very useful to ignore all the generated .class files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-5206639992927899482?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/qxrzqM7kuts" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/5206639992927899482/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=5206639992927899482" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5206639992927899482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5206639992927899482?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/qxrzqM7kuts/git-commands-part-i.html" title="Git Commands Part I" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/07/git-commands-part-i.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ADQng9fSp7ImA9WxJUFkU.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7425685775636317541</id><published>2009-07-15T15:07:00.002-04:00</published><updated>2009-07-15T15:22:53.665-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-15T15:22:53.665-04:00</app:edited><title>Block Editing in Eclipse Galileo</title><content type="html">&lt;p&gt;Eclipse now has block editing hooray!
&lt;p&gt;Ummm, what's the key binding for it? There's nothing in eclipse help, nothing in cmd-shift L, too many of my google searches took me to a crappy &lt;a href="http://www.reddit.com/r/programming/comments/8uksy/eclipse_galileo35_comes_out_on_wednesday_and/"&gt;reddit page&lt;/a&gt; which doesn't tell you what the key binding is.  Eventually someone decided to be helpful with &lt;a href="http://blog.goyello.com/2009/06/25/6-reasons-why-you-should-use-the-new-eclipse-galileo/"&gt; this post&lt;/a&gt;.  The key binding on OS X is cmd-alt-a
&lt;p&gt;Anyway, hooray for block editing.  Boo for wasting time looking for the keybinding, I hope this saves someone some time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7425685775636317541?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/zKm0SFTYT8g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7425685775636317541/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7425685775636317541" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7425685775636317541?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7425685775636317541?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/zKm0SFTYT8g/block-editing-in-eclipse-galileo.html" title="Block Editing in Eclipse Galileo" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/07/block-editing-in-eclipse-galileo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYMQXk9fip7ImA9WxJUEEs.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-3015801481410376826</id><published>2009-07-08T11:25:00.003-04:00</published><updated>2009-07-08T11:33:00.766-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-08T11:33:00.766-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="productivity" /><category scheme="http://www.blogger.com/atom/ns#" term="philosophy" /><title>Hawthorne Effect</title><content type="html">&lt;p&gt;
Apparently my post on &lt;a href="http://zdsbs.blogspot.com/2008/09/measuring-things.html"&gt;measuring things&lt;/a&gt; was really about the &lt;a href="http://en.wikipedia.org/wiki/Hawthorne_effect"&gt;Hawthorne Effect&lt;/a&gt;. Which in brief is: The simple action of measuring peoples productivity will increase their productivity.  If you read that article though, there are lots and lots of criticism, but I prefer the BS approach, it's a cool idea, let's run with it!  
&lt;p&gt;
I've been enjoying trying the &lt;a href="http://www.pomodorotechnique.com/"&gt;Pomodoro Technique&lt;/a&gt; and have noticed a change in my productivity. Honestly, I'm not following it strictly, I haven't even read much of the website, but I did download a little app and I'm measuring tasks.  I'm guessing one of two things is a result of the change in productivity:
&lt;ol&gt;
&lt;li&gt;The Hawthorne Effect has some merit and by measuring my tasks, and measuring my goofing off, I'm improving the amount of time I'm staying on task
&lt;li&gt;There's something about a change in process that makes you notice inefficiencies in the way you do things
&lt;/ol&gt;
&lt;p&gt;
For the time being I'm going to assume #1 is true :) and that the Hawthorne Effect probably isn't valid in a general sense.  You can always game metrics / measurements etc. etc.  But on a personal level, if the metric you're measuring is of value to you, if you don't game your own personal game, then I think those metrics do have value and the Hawthorne Effect does apply. Or at least that's the BS I'm slinging today. 

&lt;p&gt;This post took 30 minutes to write, I'm now taking a 5 minute break.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-3015801481410376826?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/te3P9eoLjpA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/3015801481410376826/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=3015801481410376826" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3015801481410376826?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3015801481410376826?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/te3P9eoLjpA/hawthorne-effect.html" title="Hawthorne Effect" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/07/hawthorne-effect.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AGR3s6eSp7ImA9WxJVE0Q.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7861032688121400674</id><published>2009-06-30T15:47:00.005-04:00</published><updated>2009-06-30T15:55:26.511-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-30T15:55:26.511-04:00</app:edited><title>Corey Haines Visit to Icosystem</title><content type="html">&lt;p&gt;Friday the 26th was a fun day at &lt;a href="http://icosystem.com"&gt;Icosystem&lt;/a&gt;. Through a random chain of events &lt;a href="http://www.coreyhaines.com/"&gt;Corey Haines&lt;/a&gt; stopped by as part of his &lt;a href="http://programmingtour.blogspot.com/"&gt;pair programming tour&lt;/a&gt;.  I had the opportunity to pair with him for a few hours and talk a lot of shop.

&lt;p&gt;Pairing is always a fun activity and it's really fun to pair with someone you've never paired with before.  Not only do you get some work done, but you get a nice view into some else's coding process, asthetic, and you always learn a few new tricks.  I picked up two things from Corey that I'll be trying out:
&lt;ul&gt;
&lt;li&gt;When doing a refactoring, only allowing one test to be failing at a time.  It's hard to do, but I liked how it felt.
&lt;li&gt;The &lt;a href="http://www.pomodorotechnique.com/"&gt;pomodoro technique&lt;/a&gt; - Work for 25 min, take a 5 min break, use a timer. I installed &lt;a href="http://www.apple.com/downloads/macosx/development_tools/pomodoro.html"&gt;Pomodoro 0.24&lt;/a&gt; for OS X. It puts a nice little timer in my application (what is that thing called?) bar. Maybe it's a great process or maybe it's just something new, but so far it's a nice tool and is keeping me focused. Another nice feature of it is you note what the task is you're working on. I don't know about you but I have to fill out timesheets for billing, any tool that helps with that is great!
&lt;/ul&gt;
I'm sure there were other things I picked up but they're not coming to me right now.
&lt;p&gt;Because of Corey's visit I met a bunch of the Ruby folk in the Boston area.  It really made me realize how lacking the Java community is in having a... community.  I might have to start going to the &lt;a href="http://bostonrb.org/"&gt;bostonrb&lt;/a&gt; meetings just to hang out with folks who like to talk about coding.  Maybe they won't mind having a Java hacker in their midst :P
&lt;p&gt;Writing this post took me, 27 minutes, I'm terrible at the Pomodoro technique&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7861032688121400674?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/5wHrkPTC8RQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7861032688121400674/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7861032688121400674" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7861032688121400674?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7861032688121400674?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/5wHrkPTC8RQ/corey-haines-visit-to-icosystem.html" title="Corey Haines Visit to Icosystem" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/06/corey-haines-visit-to-icosystem.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MARHg_eyp7ImA9WxJWGEw.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-8928683097540203008</id><published>2009-06-23T22:41:00.002-04:00</published><updated>2009-06-23T22:44:05.643-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-23T22:44:05.643-04:00</app:edited><title>The Downfall of Agile Hitler</title><content type="html">&lt;p&gt;
Who knew Agile could be so hilarious: &lt;a href="http://www.youtube.com/watch?v=l1wKO3rID9g"&gt;The Downfall of Agile Hitler&lt;/a&gt;

&lt;p&gt;
Also a little less funny but also great: &lt;a href="http://www.youtube.com/watch?v=T-Qn_-F2x1c"&gt;Hitler Does Unit Testing&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-8928683097540203008?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/pZFR73EbWvc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/8928683097540203008/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=8928683097540203008" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/8928683097540203008?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/8928683097540203008?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/pZFR73EbWvc/downfall-of-agile-hitler.html" title="The Downfall of Agile Hitler" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/06/downfall-of-agile-hitler.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NQH47cCp7ImA9WxJXGU4.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-1860988117716378407</id><published>2009-06-12T13:45:00.004-04:00</published><updated>2009-06-13T19:49:51.008-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-13T19:49:51.008-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="clojure" /><title>Learning Clojure - Calling Clojure From Java</title><content type="html">&lt;p&gt;Last night, we played with some of Clojure's interop with Java.  We tried out with great success Jay Fields little &lt;a href="http://blog.jayfields.com/2009/05/calling-clojure-from-java.html"&gt;example&lt;/a&gt;.  Next up was compiling Clojure to Java class files (this was much trickier).
&lt;p&gt;The documentation is pretty good and can be found at: &lt;a href="http://clojure.org/compilation"&gt;http://clojure.org/compilation&lt;/a&gt; and under the &lt;a href="http://clojure.org/API#gen-class"&gt;(gen-class)&lt;/a&gt; API entry.  There are two tricky bits, 1) the extra 'this' arg 2) the classes compilation directory.
&lt;p&gt;But first the code sample:

&lt;blockquote&gt;&lt;pre&gt;

(ns printer
  (:gen-class
   :methods [[printString [String] void]]
  )
)

(defn -printString [this arg]
        (println arg))

&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;:gen-class is the directive to the clojure compiler that it should compile this .clj file into a java class.  The :methods section allows us to define methods, we're defining the printString method which is a void and takes a String as it's arg.

&lt;p&gt;The clojure function must begin with a '-' and then there's the 'this' arg.  It took a little bit to find the 'this' gem in the documentation on the compilation entry (seriously, who reads everything before they start experimenting)
&lt;blockquote&gt;
hasNext and next are implementations of methods in the Iterator interface. While the methods take no args, the implementation functions for instance methods will always take an additional first arg corresponding to the object the method is called upon, called by convention 'this' here. Note how the state can be obtained using an ordinary Java field access.&lt;/blockquote&gt;
&lt;br&gt;So no matter what method you expose to java it will alway have at least one arg which is the instance of the object.  I can't tell you how many times we were so confused why we were getting wrong number of arg error messages when first trying this out.
&lt;p&gt;Now to compile:
&lt;br&gt;java -cp clojure.jar:. clojure.main -r
&lt;br&gt;user=&gt;(compile 'printer)
&lt;br&gt;java.lang.RuntimeException: java.lang.ClassNotFoundException: printer$_printString__4 (NO_SOURCE_FILE:0)
&lt;p&gt;This is because you didn't create 'classes' directory and add it to your classpath, it's exactly what the error says right?
&lt;br&gt;create the directory, add it to your class path and try again
&lt;br&gt;java -cp clojure.jar:.:classes clojure.main -r
&lt;br&gt;user=&gt;(compile 'printer)
&lt;br&gt;printer

&lt;p&gt;Great, hopefully there are no more exceptions, try javap on printer.class you should see something like:
&lt;blockquote&gt;&lt;pre&gt;
zacharyshaw$ javap classes/printer
public class printer extends java.lang.Object{
    public static {};
    public printer();
    public java.lang.Object clone();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public int hashCode();
    public void printString(java.lang.String);
    public static void main(java.lang.String[]);
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now you should be all set to call through to your printer.class
&lt;blockquote&gt;&lt;pre&gt;
public class Foo {
 public static void main(String[] args) {
  new printer().printString("hello world");
 }
}
&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;There's loads of different things you can do, like implementing interfaces, extending classes etc. I'm really looking forward to seeing how I can integrate clojure into one of my projects (only where it makes sense of course :P )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-1860988117716378407?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/Shzl-9X-9J8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/1860988117716378407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=1860988117716378407" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/1860988117716378407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/1860988117716378407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/Shzl-9X-9J8/learning-clojure-calling-clojure-from.html" title="Learning Clojure - Calling Clojure From Java" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/06/learning-clojure-calling-clojure-from.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cCQHc5eip7ImA9WxJXFEQ.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-7499251604647919425</id><published>2009-06-08T15:28:00.004-04:00</published><updated>2009-06-08T15:57:41.922-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-08T15:57:41.922-04:00</app:edited><title>Regurgitation</title><content type="html">&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.notesfromatooluser.com"&gt;Mark Levinson&lt;/a&gt; has a nice blog &lt;a href="http://www.notesfromatooluser.com/2009/06/agile-mailing-lists.html"&gt;post on agile mailing lists&lt;/a&gt;, it's a good collection of interesting lists.
&lt;li&gt;Started a new project and am using &lt;a href="infinitest.org"&gt;infinitest&lt;/a&gt; it's great! &lt;br&gt; I love how hard-core it makes testing. When I suggested to a few co-workers that they install it, I started getting questions: "so how do I turn off those compilation errors it creates?" Answer: "fix the tests or turn off the plugin"
&lt;li&gt;&lt;a href="http://www.threeriversinstitute.org/blog/"&gt;Kent Beck&lt;/a&gt; had an interesting blog post &lt;a href="http://www.threeriversinstitute.org/blog/?p=187"&gt;To Test or Not to Test? That's a Good Question.&lt;/a&gt; &lt;br&gt; I really recommend checking out his blog, the content is great (I think I'll have to suck it up soon and try out junitmax, maybe for my next project)
&lt;li&gt;My weekly Clojure learning sessions are still going strong, got my &lt;a href="http://pragprog.com/titles/shcloj/programming-clojure"&gt;Programming Clojure book&lt;/a&gt; in the mail last week, it's nice to have a paper copy. &lt;br&gt;We're &lt;a href="http://github.com/zdsbs/learningclojure/tree/master"&gt;working&lt;/a&gt; on putting penalties (in the form of delays) if you hit the direction keys too frequently.  I finally feel like I'm getting a feel for the language.
&lt;li&gt;and apparently Rich Hickey doesn't like testing:
&lt;a href="http://blog.objectmentor.com/articles/2009/06/05/rich-hickey-on-testing"&gt;http://blog.objectmentor.com/articles/2009/06/05/rich-hickey-on-testing &lt;/a&gt; 
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-7499251604647919425?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/XPILYdgBa58" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/7499251604647919425/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=7499251604647919425" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7499251604647919425?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/7499251604647919425?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/XPILYdgBa58/regurgitation.html" title="Regurgitation" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/06/regurgitation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcGRXk7fCp7ImA9WxJXEEs.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-4028162467974982251</id><published>2009-06-03T11:29:00.004-04:00</published><updated>2009-06-03T18:27:04.704-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-03T18:27:04.704-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tdd" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><title>Unit Testing in a Different Language Than Actual Code</title><content type="html">&lt;p&gt;I've been at talks before where it is encouraged if you're interested in learning a new language to write your unit tests in that language, even though your source code is in another language.  For example, if your code base is in Java the suggestion is that you should write your unit tests in &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;, or &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;, or something else that is awesome.
&lt;p&gt;I understand certain pragmatic reasons for this.  Sometimes, it's hard to find the time to learn a new language, and it's less risky to experiment with a new language in your unit tests than in your production code.
&lt;p&gt;But if you're trying to practice TDD (which I think is a pretty good idea) writing tests in a language that differs from your source code is risky.  TDD allows you to explore and try out your new APIs like the clients of those object would.  It's not only about making sure the code as you envision works, it's a methodology for writing new code.  But if you're using a different language to unit test your code, you are loosing out on that exploratory capability.  Sure you're using the API, but you're not using it in any way that resembles how your clients would use it.
&lt;p&gt;It's a different story when writing integration / acceptance tests.  These tests are at a higher level and are more about general application behavior than specific APIs.  I think it's very appropriate in these cases to use a Groovy or a Scala or a DSL or a framework (e.g. &lt;a href="http://seleniumhq.org/"&gt;selenium&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-4028162467974982251?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/ORMWoMc-Ez4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/4028162467974982251/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=4028162467974982251" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/4028162467974982251?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/4028162467974982251?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/ORMWoMc-Ez4/unit-testing-in-different-language-than.html" title="Unit Testing in a Different Language Than Actual Code" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/06/unit-testing-in-different-language-than.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UCQH47fyp7ImA9WxJSGUU.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-6765222760483106032</id><published>2009-05-10T15:59:00.005-04:00</published><updated>2009-05-10T17:01:01.007-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-10T17:01:01.007-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="tooling" /><title>Continuous Testing - Infinitest</title><content type="html">&lt;p&gt;If you check out the comments on  &lt;a href="http://misko.hevery.com/2009/05/07/configure-your-ide-to-run-your-tests-automatically"&gt;configure-your-ide-to-run-your-tests-automatically&lt;/a&gt; there are a slew of references to &lt;a href="http://www.infinitest.org/index.html/"&gt;Infinitest&lt;/a&gt; which is a continuous testing tool, which has a very similar feature list to JUnitMax, which is also free.
&lt;p&gt;I got the plugin up and running on a small - medium project (387 unit-tests). My project is laid out
&lt;br&gt;src/main
&lt;br&gt;src/test
&lt;br&gt;src/integration
&lt;br&gt;
Immediately I had a problem when trying out the plugin, it was running all my integration tests.  After much rooting around it turns out you can add the special infinitest.filters file:
&lt;p&gt;
From readme.pdf of &lt;a href="http://infinitest.googlecode.com/files/infinitest-4.0.3.zip"&gt;http://infinitest.googlecode.com/files/infinitest-4.0.3.zip&lt;/a&gt;
&lt;blockquote&gt;
You may have tests in your classpath that you don't want Infinitest to run. These tests can be
filtered out by creating a file in the working directory of your project named
infinitest.filters. It should contain one regular expression per line. Any class names
(not file names) that match any regular expressions in that file will not be run. For example:
         org\.myproject\.acceptance\..*
         .*\$.*
will filter out all the classes in the com.myproject.acceptance package, and any inner
classes (which always contain a $).
&lt;/blockquote&gt;
&lt;p&gt;I added my filters and everything seems to work. Infinitest doesn't run all your tests, just a subset of them (it does some voodoo to look for dependencies), it tells you how many it ran, but it doesn't tell you which ones it ran... which is fine (I guess) but the anal part of me really wants more insight into what tests it's running.  For example, I modified a class, Infinitest informed me that it ran 51 tests, but really which ones did it run... I just really want to know!
&lt;p&gt;Also another interesting tidbit,
from &lt;a href="http://www.benrady.com/2009/04/comparing-infinitest-and-junitmax.html"&gt;http://www.benrady.com/2009/04/comparing-infinitest-and-junitmax.html&lt;/a&gt;
&lt;blockquote&gt;
The other function that I think a CT runner needs to do is test selection. If you're doing TDD, you're probably running a single test every time you make a change. If you're doing CI, you're running all your tests on a semi regular basis. Somewhere in the middle of these two approaches is a good balance of feedback quality vs speed. I think that's where CT tools should be focused. Infinitest uses dependency analysis to determine what tests need to be run for a given change.
&lt;/blockquote&gt;
&lt;p&gt;Infinitest isn't particularly speedy, all my unit tests took .6 seconds to run, and the 51 Infinitest chose to run took 3 seconds.  So maybe it's important for Infinitest to trim what it's running, but if your unit tests are fast to run than it's more of an Infinitest implementation detail vs a real time to run issue.
&lt;p&gt;Anyway, I can't wait to start trying this tool as part of my workflow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-6765222760483106032?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/KEIOU53yM38" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/6765222760483106032/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=6765222760483106032" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6765222760483106032?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/6765222760483106032?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/KEIOU53yM38/continuous-testing-infinitest.html" title="Continuous Testing - Infinitest" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/05/continuous-testing-infinitest.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYMSHc6eip7ImA9WxJSGE0.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-3231516122863639137</id><published>2009-05-08T11:00:00.004-04:00</published><updated>2009-05-08T13:03:09.912-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-08T13:03:09.912-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><title>Running Tests On IDE Save</title><content type="html">&lt;p&gt;Misko Hevery just put up a blog &lt;a href="http://misko.hevery.com/2009/05/07/configure-your-ide-to-run-your-tests-automatically/"&gt;post&lt;/a&gt; describing how to configure Eclipse to run your test suite after every save.  It doesn't seem like a bad idea, and I'm definitely going to try it out, but even with a test suite that runs in under a second, I wonder how annoying it would be.  I'm an obsessive saver, I can't seem to help myself. Even if I'm only looking at a file I need to format it then save it... how would that be if it took a second to do.
&lt;p&gt;&lt;blockquote&gt;
"Here is a common scenario. Your tests are green and you start doing whole bunch of refactorings which you think are trivial and safe. When you are done you run the tests and it is broken. The problem is that you did ten little things and you don’t know which of the ten things you did broke the code. The solution is to run the test more often, but we just forget."
&lt;/blockquote&gt;

&lt;p&gt;I'm not sure this really is a common scenario I run into, but it's an intriguing idea to run tests on save.  I really believe that a change in process effects your product.  Run on save would certainly change my process, but how would it change my product? 
&lt;p&gt;Misko's post reminded me of &lt;a href="http://www.threeriversinstitute.org/junitmax/subscribe.html"&gt;JUnit Max&lt;/a&gt; Kent Beck's Eclipse Plugin, which has the similar feature of run tests on save.  There are a bunch of interesting features, like displaying test failures like compilation failures, and keeping JUnit unobtrusive.  There is one un-interesting feature, it's in beta, and has a monthly subscription.  I'd love to try it, even pay for a demo (I think :P), but knowing myself, whenever I subscribe to something, I never unsubscribe, even if I'm not using the software or reading the magazine.  So I'll have to wait on trying out JUnit Max.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-3231516122863639137?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/ayKNWPcuJ5c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/3231516122863639137/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=3231516122863639137" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3231516122863639137?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/3231516122863639137?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/ayKNWPcuJ5c/running-tests-on-ide-save.html" title="Running Tests On IDE Save" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/05/running-tests-on-ide-save.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ENQH48cSp7ImA9WxJTEk0.&quot;"><id>tag:blogger.com,1999:blog-7594548881489150326.post-5057507685890191468</id><published>2009-04-19T22:24:00.005-04:00</published><updated>2009-04-20T00:28:11.079-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-20T00:28:11.079-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="philosophy" /><title>Pair Programming - What makes programming different?</title><content type="html">&lt;p&gt;Pair programming is a pretty big movement in the software world and advocates of pair programming often believe all software should be worked on by two people. The question: "Why practice pair programming?", has lots of really well thought out answers.  But after some google searching I have yet to read someone talking about what makes programming different.
&lt;/p&gt;&lt;p&gt;The wikipedia entry on &lt;a href="http://en.wikipedia.org/wiki/Pair_programming"&gt;Pair Programming&lt;/a&gt; says nothing about pairing in other industries / professions. Neither does the Extreme Programming &lt;a href="http://www.extremeprogramming.org/rules/pair.html"&gt; entry&lt;/a&gt; or the C2 &lt;a href="http://c2.com/cgi/wiki?PairProgramming"&gt; entry&lt;/a&gt;

&lt;/p&gt;&lt;p&gt;Why did pairing emerge in computer programming? Why is there a lot of literature on pair programming, that doesn't reference other professions? 

Here are a few possible thoughts:
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;There are lots of professions where pairing would be as beneficial as in programming, but for what ever circumstantial reasons pairing emerged, and was squashed.
&lt;/li&gt;&lt;li&gt;Pairing exists in lots of other professions, but for some reason it's not as formalized as in programming.
&lt;/li&gt;&lt;li&gt;The pairing movement is just as big in other professions, but I just haven't heard about it or been able to find any information about it.
&lt;/li&gt;&lt;li&gt;Pairing doesn't exist nearly to the extent as it does in computer programming because there is something fundamentally different about writing software.
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;I don't really know which of those thoughts I believe is true.  But I am surprised that pairing seems to have emerged from programming, and it doesn't appear to have emerged for other industries. Is programming really that different from other kinds of knowledge professions?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7594548881489150326-5057507685890191468?l=zdsbs.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zdsbs/~4/_jfV82X1nM8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://zdsbs.blogspot.com/feeds/5057507685890191468/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7594548881489150326&amp;postID=5057507685890191468" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5057507685890191468?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7594548881489150326/posts/default/5057507685890191468?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zdsbs/~3/_jfV82X1nM8/pair-programming-what-makes-programming.html" title="Pair Programming - What makes programming different?" /><author><name>Zachary D. Shaw</name><uri>http://www.blogger.com/profile/11739142419934264380</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://zdsbs.blogspot.com/2009/04/pair-programming-what-makes-programming.html</feedburner:origLink></entry></feed>

