Thursday, August 19, 2010

Starting an XP Team

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.

I had a few prerequisites for forming an XP team that was going to make it hard:

  1. Everyone needed to be full-time on the team
  2. No remote devs
  3. I wanted particular devs to be on the team

Why these prerequisites?

  • "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.
  • "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.
  • "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.

Why were these challenges for my company?

  • "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.
  • "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).
  • "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.

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.

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.

Monday, May 3, 2010

I hate looping / iterating / eaching

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?

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 google collections. I mean great they have filter, transform, this will look great. It really doesn't:

List filtered = new ArrayList( Collections2.filter(foos, new Predicate() { @Override public boolean apply(Foo foo) { return foo.isBar() && foo.isBaz(); } }));
vs
List filtered = new ArrayList(); for (Foo foo : foos) { if (foo.isBar() && foo.isBaz()) { filtered.add(foo); } }

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.

Thursday, April 8, 2010

TDD Starting Points + Roman Numerals Kata

I worked on the roman numerals kata 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.

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.

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.

I'm thinking TDD is like a hill climber where you start really matters. In a way that is the challenge TDD presents you with: What is simplest thing to start with?

Saturday, January 30, 2010

Generating EJB3 classes from a database

Generating EJB3 classes from a database is not that hard. Yay! First you need to download and unzip hibernate tools. You'll want to have the hibernate tools docs 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.

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

Now create your build.xml file:

<?xml version="1.0" encoding="UTF-8"?> <project name="my-proj" default="gen_hibernate" basedir="."> <property name="src" location="src" /> <property name="build" location="build" /> <property name="generated" location="generated" /> <path id="toolslib"> <fileset dir="${basedir}"> <include name="lib/*.jar"/> </fileset> </path> <taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="toolslib" /> <target name="gen_hibernate"> <hibernatetool> <jdbcconfiguration packagename="com.my.proj" configurationfile="hibernate.cfg.xml" detectManytoMany="true" detectOptimisticLock="true"> </jdbcconfiguration> <hbm2hbmxml destdir="${generated}" /> </hibernatetool> </target> <target name="gen_java" depends="gen_hibernate"> <hibernatetool destdir="${src}"> <annotationconfiguration configurationfile="hibernate.cfg.xml"> <fileset dir="${generated}"> <include name="**/*.hbm.xml"/> </fileset> </annotationconfiguration> <hbm2java jdk5="true" ejb3="true"/> </hibernatetool> </target> <target name="compile" depends="gen_java"> <mkdir dir="${build}/classes" /> <javac srcdir="${src}" destdir="${build}/classes" classpathref="toolslib" /> </target> <target name="jar" depends="compile"> <jar destfile="my-proj.jar" basedir="${build}/classes" /> </target> <target name="clean"> <delete dir="${build}" /> <delete dir="${src}" /> <delete dir="${generated}" /> </target> </project>

If you're using postgres your hibernate.cfg.xml file should look like:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="myproj"> <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> <property name="hibernate.connection.url">jdbc:postgresql://your-url</property> <property name="hibernate.connection.username">your-username</property> <property name="hibernate.connection.password">your-password</property> <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> </session-factory> </hibernate-configuration> </pre></blockquote>

run ant jar and you should be good to go!

Depending on how you're setup you should also consider running <hbm2cfgxml ejb3="true"> it creates a nice hibernate.cfg.xml file with all the classes and your DB connection info.

Tuesday, January 19, 2010

Dependency Injection Frameworks - A Rant

Uncle Bob has a great post on dependency injection frameworks. 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.

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.

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.

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.

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.

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.

 
Web Statistics