Why Do We Continue To Implement Bad Features?

March 28th, 2008 by James Carr

While I was reading through my RSS feeds today I came across a post by David Walsh describing how to make a link to set the current page as the users home page (bad feature) with the remark:

The unfortunate part about creating websites for customers is that no matter what recommendation I make, if they want it, I have to give it.

I smirked a bit as I know I’ve implemented features customers have requested that I KNEW were bad features… but then I thought about it a bit, why do we continue to implement features for customers despite knowledge that such features are wrong?

The Customer is NOT King!

The common adage may be that “The customer is king.” but with software development nothing could be much further from the truth. The role of a software developer is to best realize the customer’s business needs via software. This may even go further for web development… a businesses website reflect their image and brand worldwide and with that in mind, poorly thought out features can tarnish that image.

Blindly following customer demands can be a quick and slippery slope to either project suicide or a bad end result. If we implement annoying and irritating features without questioning why, the customer may lose a lot of potential business. Further, I’ve been guilty in the past of accepting request after request of feature changes (because the customer is king) till the point the project either shipped incomplete or was aborted outright. :(

The Relationship Should Be Collaborative

As a professional, a developer should keep the customer’s best interest in mind and the relationship with the customer and developer should be collaborative rather than hierarchical. In my opinion, if a customer requests a feature that is ill conceived or that is known to be against proper design practices, say it! If they request blinking text to capture the visitor’s attention, tell them the truth… blinking text will irritate the hell out of any visitor and there are better alternatives for drawing attention. Don’t let them blindly dictate poor design decisions.

Work with your customer… find out the why of their feature request. Finding the true root of what they want can allow you to give them better alternatives, or even drill down to what they really want and avoid numerous feature changes in the future. Remember it’s all about collaboration! ;)

So Now What?

We’ve established that the relationship with our customers when developing software should be collaborative, that we should work with them to create the best possible solution. However, I still can’t help but question… why do we continue to implement bad features our customer requests?

I guess in the short run, we just want to get paid. What do you think? ;)

Where Is Java Going to Go From Here?

February 13th, 2008 by James Carr

Ever since I attended the NFJS Gateway Symposium almost 2 years ago, I’ve been hearing the same theme over and over:

Java is the new COBOL.

Everywhere you go, you can’t seem to avoid hearing this. An ex-coworker commented when I ran into him at Agile 2007: “I’m surprised you guys aren’t using JRuby.” Two sessions I attended there also had speakers throwing in a little rant that Java is a dinosaur that is going way. With all the new languages that can run on top of the JVM now, there has been a lot of fuss on what is going to become the next language of choice for Java developers.

DZone’s Steven Devijver is placing his bets on Groovy. This was brought up quite a bit at NFJS last year as well. It’s hard to argue against it… with JRuby, java developers have to learn a completely new language with different characteristics than what their used to, whereas Groovy combines the best of both worlds with all of the nice characteristics Ruby has (and more) as well as a familiar syntax… java code is completely valid in Groovy.

Scala has also captured my interest as of late and I really think that 2008 will be the year that it breaks into the mainstream (much like a year or two ago was for Groovy). Only time would tell I suppose… I like both languages so it is difficult to place any bets on which is going to become the new replacement for Java.

What do you think?

What It Takes to Get In the TDD Mentality

January 10th, 2008 by James Carr

Uncle Bob recently made an interesting post on TDD and test generators, and I couldn’t agree more! I’ve always despised test generators myself, mostly for the same reasons Martin makes.

In my opinion, desiring to use a test generator on fresh code is an attempt to cut corners and bypass testing, which really is counterproductive. From my experience thus far, writing code test first has helped me write more loosely couple code, while both legacy code and code written test last usually end up being a tightly coupled mess. Even if you design nice, loosely coupled code and generate the tests for it, there is still the problem that the test generator is not really going to be smart enough to figure out your domain logic, and TDD is a helpful tool for expressing domain logic in the form of both test inputs/outputs and object behavior.

Like Bob mentions, it’s helpful to use generators to provide coverage for a legacy code base (especially when refactoring… I once spent a couple days writing tests around a legacy system to prepare it for refactoring!) but if you’re using them for a fresh code base, you’re of course not doing TDD… and you lose all the benefits you could reap from practicing TDD!

As an aside, I noticed he mentioned that 33% of the codebase for fitnesse was unit tests… I’d go further and argue that one should aim for 50-60% of their codebase being composed of unit tests! I’m just extreme like that. ;)

Using AOP for Measuring Elapsed Time

December 27th, 2007 by James Carr

Recently I’ve been knee deep in some legacy code doing a fair bit of refactoring, and one of the patterns I keep coming across is processes that need their elapsed time measured. You know what I’m talking about… a procedural mess shock full of primitive obsession all over, something like the following (except imagine that the for loop is some time intensive process):

public class TimeWaster {

	public SomeResponse makeLongRequest(){
		long start = System.currentTimeMillis();
		for(long i = 0L; i < 200000000L;i++);
		SomeResponse resp = new SomeResponse("FOO");
		long end = System.currentTimeMillis();
		resp.setElapsedTime(end - start);
		return resp;
	}
}

Of course, the knee jerk response will be to hide the primitive long values manipulated all over behind some kind of abstraction, such as:

	private static final StopWatch TIMER = new StopWatch();

	public SomeResponse makeLongRequest(){
		TIMER.start();
		for(long i = 0L; i < 200000000L;i++);
		SomeResponse resp = new SomeResponse("FOO");
		TIMER.stop();
		resp.setElapsedTime(TIMER.getTime());
		return resp;
	}

A little better… but there’s still something fishy here… why does my class (despite the fact I selected the random name of timewaster) need to know about a timer? It has two roles now… generating the SomeResponse (again, remember the for loop is an assumed time intensive process of generating SomeResponse) and timing the time it takes to generate that response.

To solve this problem, we can move the timing process to an aspect, measuring the execution of the makeLongRequest using an around advice, which allows us to invoke the target method as well as modify any input and output values before returning (this is also ideal for contraint checking). So to begin, and especially since aspects can be a little tricky, we construct a very simple aspect… containing only a pointcut and a sysout in an after advice (which is called after the method finishes):

public aspect TimeWasterTimer {
	pointcut makeCall(): call(SomeResponse TimeWaster.makeLongRequest());

	after(): makeCall(){
		System.out.println("Pointcut worked..");
	}
}

I run the tests and see that yep…. that worked. So, to start small, we’ll make an around advice that simply returns the return value and run the tests to make sure they pass.

public aspect TimeWasterTimer {
	pointcut makeCall(): call(SomeResponse TimeWaster.makeLongRequest());

	SomeResponse around():makeCall(){
		SomeResponse resp = proceed();
		return resp;
	}
}

Tests pass, so let’s remove the timing code completely and run tests.

public class TimeWaster {
	public SomeResponse makeLongRequest(){
		for(long i = 0L; i < 200000000L;i++);
		return new SomeResponse("FOO");
	}
}

Now all of our tests related to elapsed time fail… perfect. Now to finish things off, we simply move the timing code to the aspect and set the elapsed time on the response before it’s returned.

public aspect TimeWasterTimer {
	private static final StopWatch TIMER = new StopWatch();

	pointcut makeCall(): call(SomeResponse TimeWaster.makeLongRequest());

	SomeResponse around():makeCall(){
		TIMER.start();
		SomeResponse resp = proceed();
		TIMER.stop();
		resp.setElapsedTime(TIMER.getTime());
		return resp;
	}
}

Rerun tests, and everything is green. Sweet! ;)

In this case, we were able to split out the responsibility of measuring execution time to a separate module by using an Aspect, allowing for a better separation of concerns. We could take this a step further an make it generic enough to be used in all cases that elapsed time is measured, perhaps by having an interface for classes that record elapsed time and a pointcut with some complex joinpoint matching magic. I’d also be interested in any alternative solutions others have come up with to solve this problem (I know Spring AOP is another way of tackling it).

Stay turned for more posts on Aspect Oriented Programming. :-P

JRuby, Groovy, and Other Dynamic Languages On the JVM

November 15th, 2007 by James Carr

Lately (thanks to Spring) I’ve been toying with dynamic languages a little bit running on top of java. I haven’t delved into JRuby on Rails yet, but I have been using them as scripted beans injected into java classes, largely in a way that exposes an application API to either a scripted environment, or to take advantage of their dynamic features. I have always loved Groovy, Ruby, and Javascript for two things: closures and the ability to add methods to a class at runtime. Something strikes me as great being able to to code something like:

tomorrow = 1.day.from.now;

Being able to write code that is so expressive like that is somewhat satisfactory, and I like being able to quickly prototype ideas with out the painful build process JEE development always entails. Let’s face it… JEE development is sometimes overly complex. Maybe we overcomplicate things by making or programs too abstract. Maybe we just need better “killer frameworks” to minimize the “plumbing work” (this is why I like Spring). Although the Ruby zealots will brag about what a breeze development is, imho they miss the point that the reason it’s such a breeze is because Ruby on Rails takes away all the boring work. Recently I almost felt like JEE is getting close while doing a Stuts 2 + Spring 2 + JPA + AJAX tutorial. Maybe we need Spring on Rails.

I don’t know… maybe I’m rambling, maybe Dave Thomas, Bob Martin and all are right saying “Java is the new COBOL.” Maybe JEE just needs to adapt to keep up with high paced development.

One thing is for sure… each time I use scripted beans with JRuby and Groovy to quickly prototype ideas I can’t help but think to myself, “Why not just write applications like that?” ;)

Accidental DSL

July 18th, 2007 by James Carr

Something kind of funny happened on a project that I am currently wrapping up at work. We had been doing acceptance testing with fitnesse, and written many custom fixtures that were specific to the domain problem (DoFixture is great for this). Further, there were quite a few RowEntryFixtures, SubsetFixtures, and RowFixtures that provided quick and dirty access to the underlying DAOs for adds/updates/deletes that allowed for quick modification of data, and each of our tests tried to mimic a user story as much as possible with minimal technical details.

Anyhow, during our daily stand up meeting with our customer, they asked if we could put something together so they could quickly create scenarios for them to test manually, and interestingly enough this didn’t take much time as we were able to show them to use the existing fixtures to interact with the system to do whatever environment setup they needed for their tests.

I think this kind of earmarks a good acceptance testing harness… one that mimics a DSL so much that you can even use your test harness for other purposes to interact with the application. Even more important, when you have an acceptance test that reads like a DSL, it means it is more customer friendly and conveys information in a useful manner. When tests are clear, concise, and easily readable by domain experts, it is much more easier to tighten the feedback loop and make changes very very quickly.

The only drawback with a testing DSL is that the initial setup can sometimes be burdensome… it may not seem worthwhile, and it may even require a little devotion to get going in the beginning and require a little maintenance to be useful. One problem we have had with our new fangled group of fixtures and tests is that development was rather quick in the beginning, but then we reached a plateau where the tests became a bit fragile and required some extra hard work to maintain and improve. Another smell that arose was that our original DoFixture, which contained sentences and statements representative of the domain, soon grew to over 400 lines and felt like a God Object. :(

However, continuous maintenance and perfection improves quality, as with anything. Test DAOs solely used in the fixtures were refactored out and replaced with the real ones from the system, with a dash of “in memory” DAOs to inject when desired. The DoFixture was broken up a little bit to seperate fixtures represetnative of the different aspects of the domain being tested. And overall, to improve testability sometimes some redesign of the system was required to allow for better inspection of the system under test, which lead to a more solid API.

The final reasult? Although a little dedication was required up front and in the middle stages, writing new tests is a piece of cake. One of our customers called yesterday complaining about a missing feature that was part of a story we recently finished, but seemed not to work. How come? The tests are green. So I worked with him, and he mentioned the product code he was using was ZZZ, which was something slightly different… our test was using product code CCC, which to my knowledge represented the product needed for the story. “Oh… CCC is the product code for that product, but so is ZZZ. ZZZ is a subset of CCC, but in the context of [proprietary domain] they are essentially the same thing.” In only about 10 seconds I was able to add the product code and verify that the expected behavior didn’t take place, then my partner and I quickly fixed, ran tests, and released.

Writing new tests with a test DSL in place is so much faster, it felt like we were writing many tests quickly in later iterations after getting past the plateau of broken or inconsistent fixtures. Perhaps the only problem we have right now is our customers don’t run the tests… they just like to look at them to see what test coverage we have, which has been good because they can see at a glance what we are doing and often make corrections and comments in daily stand ups. They call our acceptance tests our “Test Plan”. :)

I’ll try to write more on Testing DSLs… I keep thinking about other possibilities outside of FIT/Fitnesse, perhaps with tools like JBehave or even with some of the languages for creating DSLs like ANTLR or OGNL.

A Tale of Two Teams

May 23rd, 2007 by James Carr

As anyone who reads this blog knows, I’m an extreme programming enthusiast. I love pair programming, test driven development, and the constant communication with customers. it’s one of the reasons I took up a job at my current employer, because it is an “Extreme Programming Shop.” However, for awhile now I’ve heard a bit of bickering from some that “we don’t do XP”, or “we don’t do XP by the book,” or perhaps even “XP doesn’t work for us because it’s wrong.” Ouch!

An important thing I have learned is that how well your team does with XP is how much your team buys into it. It doesn’t matter if management jumps on board or not, if your team members don’t hold each other accountable to the practices, if they let each other get away with not pair programming, writing code without any tests, and limit their customer communication, OF COURSE they aren’t doing XP. And that’s the difference.

In my last department, we saw quite a few changes in team structure, and I think I hopped around to 3 or 4 different teams there. There were teams that I almost felt that we weren’t doing XP at all, and was frustrated. But then I switched to a smaller team (from 8 people to 5) that included people who were zealous about XP like me… we made it a general rule that if code isn’t checked in by the end of the day, it must be deleted. This kept us going fast and releasing small changes that could go to production after check in if need be. We kept each other from “cowboy coding,” if one of us were stuck as the odd developer, the solo person would either do some data analysis, pair up with other teams if needed, or go ahead and spend a session talking to the customers and showing them our acceptance tests.

The point I’m trying to drive to here is that it doesn’t matter what your manager tells you, it doesn’t matter if the company has bought into XP or some other agile process. If the team doesn’t truly embrace the principles, you’re right… you aren’t an XP team. Just as much as you’re not a football team if your team members aren’t willing to walk out on the field together and work with each other to win. And don’t make excuses to stop you from being as agile as you want to be…. sometimes I hear people say on (both on and off the XP mailing list) that they’d like to be agile, but their boss and customers pressure them to “just sit down and get it done!” Don’t make that excuse…. being agile is about being adaptable to change, the very definition of agile is “moving quickly and lightly with grace.” If you can’t move quickly, you’re not agile. It’s that simple.

SO, now that the ball is in your court, what do you do? Do you continue to make excuses and shove blame off on the organization, the boss, and your team members? Or do you step up and be a motivator for change, and motivate yourself and your teammates to hold each other accountable?

The Timebox

May 9th, 2007 by James Carr

Recently during one of our project retrospectives, a colleague of mine noted one of the best practices I tried to adhere to was to use a timebox when I tried something out. The issue at hand was that we were writing acceptance tests for our project, and I wanted to write a fixture to generate links that had a specially encoded date time parameter. We both had different ideas, and my partner knew that I have a knack for sometimes going overboard when writing automated tests, which was also coupled with my partner’s inexperience with fixture writing that made him fearful of going along with my idea. So to ease his worries, I simply said “it’s 2:30 now. How about we just try it only for 10 minutes, and if we don’t have something useable by 2:40, we’ll try something else.” Luckily, we wound up with a simple, yet easy on the eyes FIT test without going over the timebox.

Although timeboxes are commonly used in XP when doing a SpikeSolution, I find it also useful when trying to get “buy in” with your partner when pair programming. Additionally, it helps keep you not only focused on the task at hand, but allows you the freedom to tinker without going overboard and wasting time. And once the timebox is up, and you didn’t complete your solution, turn the keyboard over to your partner and let them try their idea out.

Of course, a timebox is good for anything really… it underlies the urgency to do {insert whatever needs to be done here} within x amount of time, forcing you to focus only on the most important details while keeping the cruft to a minimum. This also why we try to limit our morning huddles to 15 minutes, to avoid turning it into a 1 hour meeting where someone goes into great depth and detail on an issue rather than just flat out saying “We were unable to do X because of Y”, in which someone can simply say “I have an idea on what we could do, lets pair up first session!” ;)

Rant: Copy and Paste Programming

April 27th, 2007 by James Carr

Let me forwarn you that you may be offended by this post… it may come off as a bit hostile and derogatory, but it’s just something I need to get off my chest. When someone thinks it’s entirely acceptable to write a 300 line method and call it “the quickest and simplest thing to do that works” and then copy and paste those 300 lines 10 times and modify maybe one or two variables to cover other scenarios, you don’t deserve to even have a job programming.

I’m sorry, but I don’t care what your time constraints are. I don’t care that you just learned the language. And I don’t care you sat down and thought “OMGZ! I need to get this done yesterday!” The fact that you did not just try to use that thing you call a brain and THINK about what you were doing and just reduced yourself to a CTRL+C and CTRL+V keyboard monkey reduces any possiblity that I could respect you as a programmer. Honestly, did you get through school by copying homework assignments? Did you get the genius next door to do your work for you while you were out partying, and luckily had awesome memorization skills to pass exams?

A skilled craftsman is one who devotes their time and energy to honing their skill. They may start out knowing very little, but through dedication and at least using their brain they improve, and even if their code isn’t perfect, at least they gave it effort. By just mindlessly copy and pasting you didn’t even make an effort… you’re just lazy.

When you need to do something similar to something else, maybe it’s okay to copy and paste the first time, change a few things, then look at what you can do to consilidate both tasks and make the same code useable in both situations. But doing the whole copy and paste and saying “I’ll refactor it later” is idiotic… you know that “later” is never going to come, and with that attitude you’re just going to keep doing it over and over to the point that “refactoring it later” will take you 30 days.

Let’s just be honest to ourselves… there’s really no reason you should copy and paste your code. Period.

OOPSLA 2006: Design Fest Round 2

November 4th, 2006 by James Carr

As I mentioned earlier, I had attended the day long DesignFest session at OOPSLA my first day there. Since the whole experience picqued my interest, I decided to go ahead and attend a second session on Tuesday afternoon in an effort to perhaps inject myself more, and give it another shot.

I spotted Eric Evans sitting at one of the tables, so I decided to join them in hopes to get to see Eric tackle whatever design problem that was given, but unforunately he was only a moderator so he couldn’t participate much. :(

At first, things started a little shaky as they had at the previous DesignFest, although (thankfully) we all agreed on certain ground rules at the start, such as not being concearned about performance and such. There was quite a bit of debate on certain designs at first, and Eric even commented a bit that he felt like it was “maddening” because he couldn’t jump in and start working on the design with us. ;)

However, as time passed, we tended to find lots of common ground in our design, and suddenly everything began to mesh together in the design and it began to rapidly surface. We began quickly sketching out various sequence diagrams to show the object interactions that completed different user stories, and very interesting designs began to emerge.

The session wasn’t as long as the first one I attended, only being half a day (I believe the duration was possibly 3 hours or so). The interesting aspect was that despite the short amount of time, we actually accomplished quite a bit more than the team I was on did the first day.

Not to say anything bad of the team members of the previous team I was on, it really just boiled down to team cohesiveness. Although we were a little disjointed at first (as to be expected with a group that doesn’t know each other), as soon as we all broke the ice a bit, things began to run a bit more smoothly.

Another insight I gained from this is just about every group has “The Leader”, someone who tends to dominate the discussion at first and kind of drive the team. However, although we did have a “leader” at first, the role kind of melted away with many of us taking turns with the role, and sometimes even seeing it disappear entirely. The result was we were able to collaborate quicker and easier.

Definately a great experience.