Sunday, January 3, 2010

Five Days with My MacBook Pro

With a few changes headed my way in the coming new year, it was once again time to get some new hardware. I took the leap and opted for a MacBook Pro. (2.66GHz/4GB/320GB/15” so not the biggest, mac_vs_pc_2baddest one.) Here are a few of my initial leaving-Windows-and-Dell thoughts.

I can say after five days that I’m pretty sure I made the right move. There are a few things I’m struggling with in the switch, mainly my fingers going to the correct keys. Years of hitting CTRL on a windows keyboard has me hitting the fn key on the MBP, which doesn’t do much. Getting used to the Command key will take some time, but the oddest keyboard issue I’m having is hitting the B key. The reach is apparently shorter because I’ve put a lot of spaces where there should be a B.

On the flip side, it didn’t take me very long to get used to the multi-touch functions on the track pad. Having an iPhone doesn’t hurt, but the two, three, and four finger operations didn’t take long to become comfortable with. Scrolling through blog readers, articles, and Tweetdeck is a lot easier.

Installing applications is a lot easier, and a lot quicker than on Windows. To be fair, I haven’t installed a lot of huge apps, but the fairly large ones I did install went really quickly. The only real side-by-side comparison of installation I have is Tweetdeck, and it was a fraction of the time getting it up and running on the Mac. Most apps are just download, mount the image, drag to applications, unmount the image, and run it.

Now on to one of the bigger reasons I was after a Mac: Ruby on Rails development.

Rails on Windows was painfully slow at times. I tried all kinds of stuff to get my specs to run in less time than it took me to go downstairs and brew a cup of coffee. After copying the git repo of one of my sample apps over, I ran the specs and it reported .7-ish seconds. And it actually WAS .7-ish seconds. Not the 45 seconds of dead time at the command prompt while it fired up servers and stuff then reporting .7-ish seconds when it was done with the tests that I was used to. I’m already looking forward to doing some more of this.

Before I start sounding like a total fan boy, it hasn’t all been awesome. There was a 2 hour fight with an iso and some printer drivers to try and get my printer at home to work. Still haven’t got it to work, so I gave up and grabbed Brendan’s netbook to print off what I needed.

I’m also not enthralled with only having 1440 x 900 resolution. But, I’m getting old and my eyes would get tired staring at the hi-res Dell I had before, so maybe I should not worry about this one too much.

Also, couldn’t find any decent blog writer that lived up to Windows Live Writer, so this is being written in Live Writer in my Windows VM. (Bootcamp + VMWare Fusion + Win7 is freaking awesome. Looking forward to some .Net dev when I get Studio installed.)

Suffice it to say, the positives out weigh the negatives so far. I’m sandals-to-work away from swallowing the blue pill with the Apple logo on the side of it. :)

Labels: , , ,

Tuesday, December 22, 2009

Beware Your Buffering

In a twitter discussion that was centering around some Kanban joy, the point of buffering came up. I offered a bit of twitter-esque advice, meaning it was short, could be interpreted as terse, and lacked the detail it needed. As any good friend would do, Jim called me out for my 140 character bit of guidance.

So, in more than 140 characters…

Be careful with your queues on your Kanban board. (I say queue here, because a buffer is just the queue for the next step.) By definition, any queue is waste. It’s a step in the process where something is waiting, therefore value isn’t being provided to your customer.

Can queues be used effectively? Yes. Quite effectively, but you have to stay on top of them. In reality, there has to be some queuing going on to give a pull system something to pull. In practice, those queues need to be as small as you can keep them to keep things flowing.

My tweet that started this mess was that I’d been burned by buffers on more than one occasion. Here’s one nasty one where the queue wasn’t a help, it was hiding the real problem.

We had a project where our developers far outnumbered our testers. This isn’t an unheard of scenario in the world of software development, but we handled it badly on our Kanban board. We ended up with not one, but two buffers between the dev team and the QA folks. The true, root cause problem was we had a resource problem because we needed more testers. Instead, we masked it with some queuing.

The biggest problem was that we lost our short feedback loop from development to demo. Early in the process, we’d complete a feature and it would demo within a day or two. As the project progressed and the developers’ momentum took off, the testing team was backed up and the feedback loop grew. Bugs were sitting open longer, code complete features waited to be tested, and the churn began.

Our solution was to swarm the test queue to get it lowered. Having a dev or two help get some testing done got our backed up test queue fixed, but it put devs in a testing role which I’m not a big fan of doing. (Devs are notorious for making sure something works rather than looking for ways something could break.) Also, this solution was very temporary as the queue naturally filled back up once the dev team was back in high gear. The actual solution: add a testing resource. Our full queues told us that, but we didn’t listen too closely for a while.

In the end, some buffers and queues are inevitable in many situations. However, make sure to do the following:

  1. Make them as small as you can, maybe half the size of the queue limit of the step that the buffer is feeding. Adjust as necessary, but don’t keep increasing it as it fills up.
  2. If you need to increase its size, ask why a couple times to clear it up. If the answer is, “Because we need more room!” then look at the next step and see why it’s backing up your process.

So, back to what started all this…buffers can bite you in the butt as they tend to mask the issue rather than solving it. Make sure your buffers aren’t hiding a bigger problem.

Labels: ,

Thursday, December 10, 2009

Rails Study Apps

I’m trying to pick up some rails in my spare time. Been plugging away at my pet project when I can, which leads to a lot of googling while I do it. If one of my known Rubyist friends is at a Code and Coffee session, I spend a fair amount of time picking their brains and pairing up to learn what I can in an hour or so.

That all works pretty well, but at my pace I’ll be forever getting my Ruby code to look less like C# and more like Ruby. So, as Steve blogged recently, why not find a few Rails apps to read? So, I hit up my twitter friends: http://twitter.com/timwingfield/status/6464205602

I got three pretty good responses, and finally got time tonight to pull them down and take a quick look at them. I don’t have a lot of info on any of them, but I did browse the source to get a feel for what was going on.

Radiant CMS

http://github.com/radiant/radiant

This one was recommended by Dugald Wilson. Decent amount of code here to look at, and uses RSpec for the test framework. This one definitely fit the bill for what I was after.

Spot.us

http://github.com/spot-us/spot-us

I got this one as a tag team recommendation from Scott Walker and Matt Darby. This is a non-profit company doing Community Funded Reporting and is coming from the folks at Hashrocket. More RSpec out of this project, and again a fair amount of code to pour over.

Redmine

http://github.com/edavis10/redmine

The third one came through Ben Wagaman. This one uses TestUnit instead of RSpec, but still some decent reading. I’m going to have to dig into the tests a bit more on this one, though, because the file names aren’t jumping out at me as model/controller/etc type tests. But, that’s the point of this exercise, to see what other folks are doing.

I’ve got a little flying and a lot of driving ahead of me this weekend, hopefully I get some time to dive deeper into what each of these apps is up to, and get some more Rails code under my belt.

If you’ve come across a few more open source Rails apps out there, please drop a link in the comments.

Labels: , ,

Saturday, November 14, 2009

ASP.Net MVC: A Step in the Right Direction

A link to Doug Copestake’s article “ASP.Net MVP: A Step Backwards?” was forwarded to me, and it made some short rounds on twitter. I read it and had a comment underway and thought, “This is WAY to big for a comment, let’s blog it!” So here we are.

Off the top, I’d like to give a tip of the hat to Doug for stepping outside his day to day and taking a look at ASP.Net MVC. It’s very easy to hide behind FUD and just blow off something different. Additionally, his initial findings are pretty much on par with most other folks happy with WebForms who take their first look at MVC.

The MVC framework definitely provides simplicity and separation of concerns to web development. It allows you to only write the code you need to write to get the job done, and it allows you to work with the framework. Views become very small and very specialized, controller actions mature to be very thin, and it’s all easily testable.

This has made my work with the MVC framework extremely successful. Since everything is easily testable, as we refactor the code to clean it up or add new functionality, it all flows very easily.

Control reuse comes from veteran WebForms developers quite often. But if we again point at simplicity, how many of those drag and drop controls were written to cover more functionality than you need? You drag a grid control out and use 15% of it’s power because its made for everyone. Yes, you can write your own application controls to do exactly what you want, but you can do that in MVC, too.

Another point to control reuse is the leveraging of more javascript frameworks to do many of the things that the WebForm control suites do. In jQuery UI alone, you’ll get tabs, accordion panels, sliders and other UI elements, all with out that “server side” part that is so prevalent in WebForms. The win there is in more than just lighter weight controls, you gain a much better user experience. (And who doesn’t like happy users?)

The spaghetti code point Doug makes is quite valid, though I think that’s not a factor of one framework or the other as much as it is the person writing the code. The Glen Vanderburg quote, “A bad developer will move heaven and Earth to do the wrong thing,” applies to all languages and frameworks. The person with the keyboard under their fingers is responsible for keeping their code clean, not the framework developers, but I digress.

Spaghetti code in the views is a big sign that you’ve done something wrong. Even before moving to Spark, if you see lots of server instructions in your views, it’s time to stop and think, “What can I do differently here?” Same can be said of your controllers. If you’re used to writing a 50 line page load method in WebForms, turning similar code into 50 line controller actions is a step in the wrong direction. I guess the main point here is instead of relying/hoping for the framework to do the work for you, the onus is now squarely on the shoulders of the developer to keep his or her code concise.

Doug’s last point is very true, though: if you have a lot invested in WebForms in your current situation, there’s no real reason to switch away from it. Switching for the sake of switching to anything usually isn’t a good move.

That said, you can easily run WebForms and MVC in the same web application. If you have a little something to add to the project that can stand on its own, I’d say a look at MVC is in order.

This definitely would have been too long of a comment… :)

Labels: , ,

Wednesday, October 21, 2009

ASP.Net MVC v. WebForms

This question seems to come up a lot in discussions around these two ASP.Net frameworks. Just this past weekend in Cincy at the MVC Firestarter, it came up a number of times.

So, on the way to work this morning, I was listening to Hanselminutes 184, and the question was FINALLY given an answer by Scott Hunter.

If you care about separation of concerns, testability and tight control of your markup you should go with MVC. If you’re an enterprise developer and just want to get something out there quickly then use WebForms.

That’s paraphrased, I may have gotten the MVC reasons in a different order, but that was the point made.

Scary that “Just get it done,” is the main reason to use WebForms. I’ll stick with my “slow” TDD and long term maintainability in MVC and steer clear of WebForms where DDD apparently stands for Drag, Drop, Deploy.

Labels: , , ,

Monday, June 8, 2009

“But WebForms did that FOR me.”

While working with the model binder the other day, the statement in the title was made by one of the guys on my team. It’s not an unreasonable statement, but I think it spells out an important distinction between traditional ASP.Net WebForm development and using the new, shiny ASP.Net MVC framework.

The point in question was in posting an object after edit, the id didn’t automatically come through. The model binders do some magic under the hood, and it’s welcome magic in my opinion as I’ll gladly leave Request.Form back with Classic ASP. However, you still have to tell the model binder the whole story, it’s not done for you anymore. (Nor was it done for you before WebForms.)

Solution to our little problem: Stash the object id in a hidden form field. (Yes, I know, right click and view source and there’s my object id.) Once looked down upon in WebForms development…well, other than that one GIANT hidden form field called “ViewState”…the hidden field looks to be making a quiet comeback.

Basically, if you want the model binder to find all the bits to your object, you have to make it available when the page posts. So, it needs to be in the form somewhere.

Personally, I don’t see this as a step backwards, but I grew up in the salad days of request/response. Having to provide that info so you can get it back seems normal. The flip side is also true: if you don’t need it, you don’t have to add it.

The more I work with ASP.Net MVC, the more I fall in love with it.

Labels: ,

Tuesday, April 28, 2009

Code and Coffee

After a great day at Kalamazoo X, and a conversation with Mike Wood about his Bitslinger idea in Cincy. Jeff and I had a few hours in the truck headed south to work out something for Columbus, so Code and Coffee was born.

OK, we hatched the general idea…meet at a coffee shop on Thursday mornings, write code. I came up with the name and bought the domain. :)

The idea is straight forward: Show up at our coffee shop of choice, bring a laptop, pair up, and have fun writing some code.

Check out http://codeandcoffee.info/ and join us if you can.

Labels:

Thursday, April 9, 2009

What I'd Do Different

In my last post I mentioned a few things I'd like to do differently in my next new dev project where we utilize Kanban. I sat down with our PM, Elizabeth, and we did kind of a mini-project retrospective, and what we could do differently from the Kanban side of things to help things flow along better.

The first thing we thought would help would be to get better info on the cards, and to treat the cards as Minimal Marketable Features. Across the top of the card we'll put the feature number, name, and its time estimate. In the middle of the card, the description and any task breakout that's needed. Across the bottom we'll stick with the WIP start and end dates, and the cycle time will go between them once it's complete. The back of the card we'll put actual developer and tester times, and then once complete total that and put it on the front of the card under the estimated time.

This will accomplish a few things for us. First, on the dev side of things, it gets that task card breakout thing out of the way and allows us to track the features across the board as a single entity. Secondly, it gets more project management info clearly on the dev card, which makes it much easier for people not knee deep in the project daily to keep tabs on what's going on.

The second thing we thought should be implemented the next time around is an extension of the board, to the left. Our board for this one had a bullpen column where features were in holding waiting for the tasks to breakout. From there, they moved into the backlog, and into work in progress.

Our idea here is to break that bullpen column out into another Kanban section where discovery, design, and estimation takes place. Once that is complete the feature can wait in a "Ready for Dev" status and be pulled into the backlog column on the development Kanban board when the set trigger point is hit.

Elizabeth and I went back on forth a bit on where the bullpen board would reside. Initially I wanted to see it isolated from the dev team so they could concentrate solely on the dev tasks at hand. However, Elizabeth's persuasive abilities (strawberry cake with white icing may or may not have played a role here) led us to the conclusion that it should all be one board. This allows the developers to be aware of what's in the pipeline coming at them, lest they relax a bit too much at a critical point in the timeline. And, it allows the dev side of the board to pull from the bullpen as features are estimated and ready to go.

Finally one last thing we thought we'd employ would be different sized cards for different sized features. If we can't get all features to breakout into a similar estimate range, which is a very real possibility, then maybe get two or three ranges and denote them with different sized cards on the board. This would allow for different cycles to be tracked based on feature size, and a quick look at the board would tell you what type of features are moving through the system at any given time.

I think these changes to our approach will help the next new dev PIC-0300 project where we employ Kanban. We used it successfully before, but I think this will help get more features into done with less friction for the whole team. Which means cards will get put in the envelope above this lovely lady's picture in a shorter cycle. (Whiteboard drawing courtesy of Dan Shultz.)

Labels: , ,

Monday, April 6, 2009

Kanban Lessons Learned

After seeing success with Kanban in a production support environment (part 1, part 2), we decided to give it a try in a new development situation. This project was a mix of new development and working with an inherited code base to implement some existing features differently.

Because of this situation, we ended up with a mixed bag of features. PIC-0301At the onset, we decided to break these features out into tasks, and we would track both across our Kanban board, as shown here with a snapshot of our Work In Progress section.

Features were broken into tasks and grouped together in the backlog. Once a feature went into WIP, it's tasks moved below into the Task Breakout section and were worked there. Once all tasks were completed, they were once again compiled back into a feature and went into test as a whole.

What we tried to accomplish here was to keep the concept of a MMF while still breaking the work into smaller, more manageable units. What ended up happening was that features themselves became secondary to almost full task development, however we were tracking features through the system for our cycle time. Early, heavy task features that focused more on the business model skewed the cycle time higher, and later UI tweaking features sent it lower. As such, our cycle time diminished quickly as the deadline drew near...a good thing, but I don't think it was totally attributable to the team's momentum.

I think we failed here in poor estimation of what lie in front of us when we started. A good bit of this is the situation we were in at the onset where we were under pressure to start getting things moving right away, and we didn't give much credence to estimating later features very well. That wasn't really a Kanban issue, and we should have known better. The excuse is we had very little time to ramp up on the discovery side of things when we got the project, but it would just be an excuse...we should have known better.

One final area where we had some issues was in reporting where exactly we stood in features completed. We were fairly visible on this project, and had a lot of interest in our success by the due date. (OK, what project doesn't?) While you could look at the board and see what was being worked at any given point, due to the lack of good feature estimation up front, it was hard to see where we were in the big picture. In the latter half of the project we stole ourselves a project manager, and she did a bang up job of getting that information worked out, but she did struggle in figuring it out. Again, I think she had trouble due to the lack of good estimation up front.

It wasn't all pain and suffering as we moved our cards across the board.

One good thing we got out of the board was it was easily changed to fit our constantly changing team size and make up. We started out as three developers, and ended as four developers - two different than the original three, one PM, and one QA person. Being able to walk up to the board and change the queue limits on feature WIP, task development, and features in test made things flow quite smoothly as the project moved along. It did a good job of identifying a few roadblocks and getting them out of the way, as well.

As noted earlier, our cycle time did drop as we neared the due date. Part of that was due to the smaller features coming through later, but there was a good bit of momentum on the dev team, too. Morale stayed fairly good as we kept moving things into the done envelope at the right side of the board.

I still think we were successful with Kanban in this situation, but clearly I think we need some refinements around how we did it on this project. I'll save those ideas for my next post.

Labels: , ,

Tuesday, March 24, 2009

"Houston here. We're looking for somebody to blame for your problem, 13."

Fix the Problem, Not the Blame
It doesn't really matter whether the bug is your fault or someone else's—it is still your problem, and it still needs to be fixed.

--The Pragmatic Programmer

I highly doubt that was the response to Jim Lovell after the line, "Houston, we have a problem." However, in our world of software development it still seems to be the first reaction to any issue that comes up.

I know in projects past, I've been a huge offender of looking for, "It's not MY fault," rather than fixing blamethe problem at hand. Todd even nicknamed me Blameosaurus on one project because I got so good at looking for the blame. So, I'm not exempt from my own post here.

I've been a consultant for one company or another for over ten years now, and we're constantly thrown into burning buildings to get something working. There are a plethora of issues on day 1, and all too often those of us on the team spend too much time bitching about the issues and not enough time rolling up our sleeves to get things squared away. So, day 2 rolls around and we're in the same boat, and the same problem still exists.

That said, sometimes there is a right time to track somebody down that created a problem. Don't do it as a way to shame them, but rather for more clarification. Who knows what the situation as like at the time they made the error, and maybe it's a good time to help somebody learn something new.

I feel I'm still an offender of whipping out the blame thrower a bit too often, but I'm making a conscious effort to quit and move on with the solution.

Labels: , ,

Thursday, February 12, 2009

Goals for 2009

I got tagged by Jeffery back in January for this, and since there's nothing I should do today that I can't put off until tomorrow...

Professional Goals

1. Speak 12 to 15 times: I spoke 12 times last year, covered three different states, and had a heck of a time. Why no big increase here? Because realistically speaking (pardon the pun), that was plenty with everything else that goes on with job and family.

2. Present "Care About Your Craft" at least 5 times: I gave this one a couple times last year, and would like to give it more. It's a great talk that covers a lot of things developers can do outside of their syntax of choice to be better developers.
3. Upgrade the MVC talk and samples: When I wrote my goals out at the beginning of the year, I put this one on here because I'm a little behind on my MVC. But this week, I started in on a project that was going to leverage it, and found out just how far behind I am. So, I'm already underway on achieving this goal.

4. Create a new presentation: This one will be taken care of thanks to being invited to speak on Kanban at COALMG in March. (I've procrastinated this post long enough that one goal is reached! w00t!)

5. Write a sample app in Ruby: I need to work on my Ruby some more.

6. Contribute to an open source project: I need to do this, as well. Need to find the right one to contribute to, though. Maybe combine this with goal #5.
7. Get the blog better organized: Had this one on the list for a while, but I keep putting it off. Should I install Grafitti? Should I just run with Blogger? I need a new design no matter what engine I use. Thankfully, I've got a few friends who are willing to help out on all points, should be fun.
8. Write 35 blog posts: 3 posts a month should be doable. Though it's already February and I'm behind my pace.
9. Read 12 books: A book a month...like above, I'm aleady behind. On my list, though, are to re-read the Pragmatic Programmer, finish Implementing Lean Software, and to get through Uncle Bob Martin's Clean Code.

Personal Goals

1. Fix my office to be more usable: Wendy and I don't have the best layout to our home office, and we both need a little space of our own in there.
2. Get better lighting in our basement: We have two choices for lights during movie watching - harsh flourescent lighting, or none at all.

3. Budget our vacations better: We've got two trips planned already, and we tend to say, "Screw it! We're on vacation!" when we go to buy something while we're out seeing the world. (Usually Disney World.)
4. Clean up our finances: I'm waiting for a year when this ISN'T on my list of goals.
5. Lose weight: Like #4, I could use a year without this one on the list. Thankfully I'm starting '09 lighter than I was in '08, but could still drop a few more pounds.

Labels: ,

Wednesday, November 19, 2008

Kanban-o-rama - Part 2

In part one I laid out the why and the how of our Kanban set up. In this part, a nice cell phone picture and some what it's done for us.

The Board



Here's our "borrowed" whiteboard. In stroke of genius from Mark, we drew the dividing lines with a Sharpie which makes them semi-permanent. One post-it note equals one work item, so for every post-it on the board there's a corresponding entry in our SharePoint work item list. Yellow post-its are regular priority items, purple tickets are high priority. (The stray colors are just strays...green == yellow, and fucia == purple.)

To the right of the names is where we start working with the tickets in the backlog column. It's sized to fit three tickets to help enforce our max three rule for that slot. Below that is the Blocked area, which isn't sized to scale of their respective max allowable tickets.

Moving to the right across the board is each developer's Work in Progress slot. Again, sized to enforce the max allowable items. This is where carried over our dotting strategy from the previous set-up: Yellow is domain understood, green is design understood and in dev, red is dev complete, blue is in production. (Though following this photo we have decided that blue will mean passed testing in staging, ready for production.)

At the bottom of the Work in Progress column is our Emergency slot. This is where our "drop everything" items end up. To our surprise, it hasn't been utilized as much as we thought it would.

To the right of the Work in Progress slot are our Ready for Test and Tested slots. These are the first real community slots on the board, and the honor system is in place for getting things tested. So far, so good on that.

The far right of the board is open space for notes, tracking what's gone into production, and blimp drawings.

What its done for us

So far the big win for us has been gaining focus on one item at a time. We still have some growing to do in this area, as the inevitable "How long would it take to do X?" questions come up daily, and you find yourself looking at code you weren't aware existed when you started the day. So, we're trying to push harder to keep the distractions down, and keep the focus switching lessened.

Another thing that moving to this system has allowed is that it's much eaiser to report up the chain of command what each person is working on. It's much easier to manage expectations on when something will be finished and when another item will be started. Also, when the, "Item Q has to be done right away," request comes in I can say which items are being worked and ask which one should be stopped to pick up Item Q. Now that I can better articulate what each guy is doing, these requests are more often becoming, "Oh, this can wait until one of those is finished."

We've been using this for about four weeks now, and have had a few discussions around it. The early returns from the dev team is that they like it quite a bit. The numbers reflect that it's working, too, as we've closed more tickets over the last four weeks than we had in any four week period since mid-July.

Labels: ,

Sunday, November 16, 2008

Kanban-o-rama - Part 1

Our current project is much more of the maintenance variety than of the new development type. Originally we tried to apply our standard scrum-ish approach to it - feature cards, load sheets, 2 week iterations, etc. However, it became clear that working maintenance tickets wasn't going to fit that model. Our load sheets meant nothing after a while because they were just getting overloaded with work items that were un-estimated, but needed assigned to get worked. It also became increasingly difficult to track the status of an item. Due to the lack of information about some tickets, any developer would show multiple tickets being "worked" at any given time. Keeping track of that on prod push day wasn't very easy, either.

Enter the Kanban idea.

The idea was brought up after a Friday retrospective by fellow QSI guy, Alexei. Comrade, myself, and our PM had about an hour discussion around the idea, and the following Monday put it into action. I did some information gathering over the weekend, hit up a couple other Quick guys for some more information, "borrowed" a white board from an office in the building, and away we went.

Our setup

Our setup is pretty simple. You can have 1 item as "Work in Progress" at any one time. You can't work more than one item at a time. Focus on that item until complete, then pull an item from your backlog.

We set up the backlog not as a community backlog, but each developer has his own backlog. I know this isn't ideal, but it gives us one extra layer of control on the flow of which tickets go to which guy to fix them. (The system we're working on is pretty broad, and though I'd love to practice collective ownership of the whole thing across the whole team, that's just not practical.) The backlog can max out at 3 items, and the item you choose is your choice, unless there's a high priority item in your backlog. (Denoted by a purple ticket rather than the normal yellow.)

If your item becomes blocked, we have two blocked areas available to move the ticket into. The first is "Blocked, need more information." Tickets moved here are assigned back to the PM who will follow up with the user to get the information needed to complete the ticket.

The second blocked area is "Blocked, Internal" which is a horrible name...the creative juices just weren't flowing that day. Typically tickets get moved here when they're dependant on another work item to be completed prior to them being worked.

Our max tickets allowable in the Need More Info slot is 8, and the internal is 2. If we go over those counts, we stop and figure out what we need to do to move those tickets along.

Once a ticket is no longer blocked, it goes back into the developer's backlog that originally had it. If there's not room in the backlog when it comes unblocked, it will wait in the "Ready for Dev" queue that is maintained in SharePoint. All the tickets are tracked through SharePoint as well as on the board, but prior to hitting the board they're managed only in SharePoint.

Once a work item is completed, it moves to "Ready to Test." The rules of testing are you test a ticket you didn't complete, as we don't have dedicated QA resources available. When you complete an item and there's one available for test, take the time to test it before starting your next item. So far, using the honor system has worked well, though we do still have some testing to catch up on before we do our weekly prod push. (We've picked Tuesday, so there's some testing going on Monday afternoon.)

Following testing, the ticket moves to "Tested." There it sits until it's rolled out to production.

That's the standard flow we've been using, but we did open up an "Emergency" option. So far, we've only had three emergency items drop into that slot. When that happens, the developer chosen to work it stops the item he's currently working and switches gears to the emergency until it's complete.

I'll end part 1 here. Up next I'll show off some photos of our board and add some more details as to how its been working out for us.

Labels: ,

Wednesday, July 9, 2008

TDD Starting to Sink In

Back in late March, I blogged about my issues getting going with TDD. At the time I was nearing the end of a project where I had attempted some unit testing, but had not done it up front. I was looking forward to a clean slate to get some more work on TDDing up my code.

That opportunity somewhat presented itself, though I was moving on to an established team, which presents its own challenges. However, this team, or a good portion of it, was practicing TDD. So, plenty of example code out there. Not only that, I ended up sitting about 3 feet from world renowned TDD zealot, Steve Harman. Steve is a great teacher, and only yelled at me a few times. (And I only cried the one time...)

That helped on the professional side of things, but even in my own hobby coding I started writing more and more tests before the code. I've been presenting on ASP.Net MVC at a few places recently, and the sample code I use there was written all TDD style. (And is presented test first.) Well, almost all of it...somebody wrote his repository wrong, and the updates didn't work so well. I have some refactoring to do.

So, here I am 3 months later, where do I stand on the points I brought up back in March?

1. I tend to wrestle a lot with when to layout some of the framework and when to just breakdown and write the tests.

This one became pretty easy when Steve introduced some BDD (Behavior Driven Design/Development) style grammar to our testing. This one shift in thinking opened up my ability to get the requirements into unit tests, and get them green quicker. In a nutshell, thinking along the lines of, "When X condition is present, then Y should happen," and naming the classes and test methods with that type of grammar took me well beyond wondering when to write the tests.

2. A recent project found our team working with a pile of generated tests.

Generated tests are a thing of the past. This is a non-issue at this point.

3. When to mock?

Again, a healthy dose of Steve helped here a lot. Also, Rhino Mocks 3.5 was released with the Arrange, Act, Assert syntax, and that cleared up a lot in the mocking area. No more record and playback blocks, and lots of lambdas to stub out that which you want doing the dirty work.

The answer to the original question finally became clear: Get the hard stuff out of the way with mocks. Beyond that, get the stuff that you're not testing out of the way with mocks. The AAA syntax made that pretty easy.

4. Is this test trivial, or needed?

OK, I still have a bit of trouble here. Not as much as before, but occasionally I find myself writing a test, looking at it, and going, "Gee, I'm testing the setter of that property...that had BETTER work!"

5. I still have large holes in what I test.

Again, still having trouble here. Even with the good TDD practices in place at the most recent project, I found myself frustrated and writing the code and screen testing it rather than writing my unit tests up front. I did have a deadline that I was up against, but cutting the unit tests is never the right solution. I fell back to an old habit, one I've been working pretty diligently on breaking.

In the March blog entry, this referred to unit testing my javascript. Well, ending up on a Webforms project pretty much ended my worries about getting my javascript tested.

So, with those steps behind me, what do I want to focus on now? Well, I can still improve on numbers 4 and 5 above, but I think those two will be continuous improvements. I'm going to continue down the BDD-ish path. It's not pure BDD, but it got me over the hump, and I like the syntax. But overall, I'm just going to keep going at getting the tests written up front. Focus more on the red, green, refactor as much as I can. I'm seeing the benefits, just need to get those old habits kicked.

Labels: ,

Sunday, March 30, 2008

TDD growing pains

I've understood and attempted to follow TDD practices for a while. The initial understanding of it was pretty tough, and very, VERY sporadically put into practice. After all, it's a pretty big shift in thinking when you first encounter it. "Write tests? For code that's not there?? Wow, that's fantastic!!"

So, over time I've gotten much better at the whole TDD thing. Or so I had thought.

Wednesday, mid-presentation, my lack of patience with the system outed me. I had written my tests, passed my tests, changed my code, changed it a little more, and then went to present it. Wow did I get smacked in the head by not running the tests after each change. (Continuous integration for a small demo app didn't really enter my mind. I have a hard time firing up CI at home since there's not much to I, but maybe I should join Mr. Donaldson in doing so.) So, big time lesson learned there.

The flip side to that bit of a stumble was the amount of time TDD saved me on my current project at work. I had written a number of unit tests to cover some business logic, and a few integration tests. A couple of defects came in showing that I needed to change a number of my dates to nullable objects. Not a difficult change, but not totally trivial, either. Made the changes, ran the tests. Oops...more changes, ran the tests. The whole change over was done, tested, and passing within 15 minutes.

A few pitfalls I've fallen into while traveling down the path towards TDD enlightenment:

1. I tend to wrestle a lot with when to layout some of the framework and when to just breakdown and write the tests. The main reason I wrestle with this one is that the good ol' crutch of intellisense sure comes in handy for test writing if you've framed your code out some. (When writing Ruby code in e, this doesn't seem to be as much of an issue for me.)

2. A recent project found our team working with a pile of generated tests. With the ever present deadline looming larger and larger, we decided to go with the generated tests as they appeared to be "good enough." They were good at the start, but as the code base grew, and our tests with it, we started looking at our CI build taking up to an hour. There's a big red flag. Dug into the code, very few unit tests were generated, but a pile of integration tests were. Takes a while for nHibernate to do its thing 4,316 times. (We've since started cleaning that up, build is back to a more reasonable, but still outrageous half-an-hour now...)

3. When to mock? I'm hip to the whole mocking thing, but identifying the right time to do so is still giving me troubles. I'm sure I'll get there with practice, just need some more practice.

4. Is this test trivial, or needed? In a previous post I mentioned viewing code coverage the other way around, seeing what's uncovered rather than covered. I don't see 100% coverage, er I mean, 0% uncovered as attainable in the web projects I usually work on, but where do you draw the line? If you end up falling over on a piece of untested code, I guess it wasn't trivial.

5. I still have large holes in what I test. Just about all of my javascript code is completely untested. I know there are frameworks available to help me with that, but I haven't gotten down and dug into them.

So, short term I'm going to keep the ears pinned back and keep moving forward with the testing first. May as well get a home build server set up, and keep digging on mocking as much as I can. Gonna have to investigate Moq, as well. Also, time to get that javascript tested. With as much AJAX as we're cranking out, this is quickly becoming a priority.

Labels: , ,

Tech Night - Getting Started with MVC

First of all, thanks to all those who attended TechNight this past week at QSI HQ. That was by far the largest crowd I'd seen gather for TechNight, much bigger than the 10 people that came in September when I presented on ASP.Net AJAX. With Quick having the much larger training center now, I hope this trend continues.

The Snag

During post-presentation discussions, I finally arrived at why the test failed. Short version: I'm an idiot.

Long version: I went with the whole TDD approach to the presentation to show how MVC was more testable. It is a great way to show some of the advantages of MVC. It is if you continue to run those tests as you refactor your code.

What I did was stop at red, green, refactor. I didn't try for more green following an additional refactoring. I had written and passed my product controller tests, where the big test failure happened in the presentation, before I had added my model code to the product controller. That's a pretty big change, and clearly the tests caught that change...in front of an audience, rather than in the comfort of my own home.

So, my protests of, "These passed at home!" were correct, because I only ran them once. Like I said, idiocy.

In the end we got it working for purposes of the demo, and I owe Mel, Steve, Steve, Kris and many others who shouted advice a big thanks for helping me over the hurdle. However, the demo ended up testing what I didn't need or want to test: That LINQ was doing what it said. I had wanted to add one more test prior to the demo that hit an in memory collection of products, that would have solved my problem with the connection string and been a much better test of the controller code.

Here is a link to the code and slides: Getting Started With MVC

That resisdes in a SVN repository on Google Code (thanks Steve), and will get updated as I update the presentation. Clearly I have a couple of tests to add, some data issues to clear up, and will probalby change the slides some as it progresses. Keep an eye on it in the near future for updates, CODoDN will be here before I know it.

Labels: , , , , ,

Wednesday, March 12, 2008

Is code coverage worth bragging about?

I'm a hockey fan, have been for a while. In being a hockey fan, I've had a number of statistical discussions around the sport. Second only to baseball fans in statsville, hockey fans love their numbers. One major discussion took place around shots on goal. That semi-subjective stat that tells a team how many times the goalie got between them and a goal. I've seen teams put 40 shots on net and lose to a team that got 18 because 3 of the 18 went in and only 1 of the 40. After the game, you lost, but hey...you put 40 shots on that guy! You certainly didn't lose for a lack of trying.

So, over in the software world, I'm now wondering if Code Coverage is our shots on goal stat. You get over beers and start talking with peers and hear...

Bob: "I've got 40% code coverage!"

Terry: "Bah, that's nothing, we hit 55% this afternoon!"

James: "You both suck, we've got 70% coverage and are almost through UAT!"

Here's what's missing in that discussion...Bob is 60% uncovered, Terry is 45% uncovered, and James has 30% of his code waiting to spring something on him in the next few days of UAT. In essence, they've each got a number of shots on goal, but how many are in the net? Are we focused on the wrong side of the equation?

The goal of 100% code coverage is a tough one, unless you're Joe O'Brien. (See: Testing Mandatory, CodeMash 08) In my life in ASP.Net, getting 1% coverage on a code behind file would be worth a round of beers.

But, are we focused on the wrong goal? Clearly, increasing your code coverage is decreasing uncovered code. But, if your goal is 75% coverage and you reach that goal, do you stop? Maybe shifting our focus to code uncoverage will close that gap.

Don't be happy with those 40 shots on goal...

Labels: , ,

Tuesday, March 11, 2008

Mix08 Recap

My recap of Mix08 has to start with a big thank you to Jeff Blankenburg, and the small company he works for based in Redmond, WA. Jeff got me a ticket to Mix (QSI got me the plane ticket and hotel stay), then once I got there he got Colin Neller, who runs the Memphis user group, and myself tickets to the Blue Man Group. Then when the White Death hit Columbus and our flight home got cancelled, Jeff put us up in his room for the night because he was staying one more evening. (Oh, and he loaned me $40 at the craps table…but he told me the juice is running on that.) If your DE is to drive more interest, JB is doing a good job getting me around the Microsoft community.

Second big thank you is going to go to Steve Harman. Steve and I both work for Quick, and roomed together while at Mix. (That’s the rest of the “us” that Jeff put up courtesy of the Blizzard of ’08.) Steve has a number of contacts in the community, and he introduced me to everybody he knew, and some he didn’t know. (And after our interesting trip home, Steve and I didn't kill each other, and we're still speaking.)

So, with Jeff and Steve leading the way, easily the biggest part of Mix for me was the people I met. There were a number of sessions I didn’t go to as I stayed in the Open Spaces/Sandbox area to just talk with people. So, I may have missed a Silverlight session, but I got to spend about 35 minutes talking to Phil Haack about the ASP.Net MVC framework. The guy writing that framework has to be a pretty solid source of information. Later I watched the Steve Balmer keynote with Rob Conery. Rob shared a lot of what his general development practices are, and what tools he uses. (I didn’t luck out and have beers with ScottGu like Steve did, though.)

I did get to a few sessions, though. The highlight one for me was Scott Hanselman’s talk on the ASP.Net MVC framework. Since I’ll be doing one of those myself on March 26th, figured I better watch Scott to get some materials to borrow…er, I mean get ideas. I also got to see Nikhil Kothari talk about ASP.Net AJAX apps moving forward, which was pretty cool for me since I got a lot of information from Nikhil back when I was picking up on what was then ATLAS. One of the better sessions was a panel discussion on Open Source and where it’s headed. The panel consisted of Mike Schroepfer (Mozilla), Rob Conery (Microsoft), Andi Gutmans (Zend), Miguel de Icaza (Novell, Moonlight), Sam Ramji (Microsoft). They took questions which started the discussions, which got heated at times, but raised some great points. In hindsight, I wish I’d had found another panel discussion to go to.

All the sessions, including the keynotes (the Guy Kawasaki, Steve Ballmer keynote should not be missed) are available online now at http://sessions.visitmix.com in a number of formats. All that information is great, so in the end I really won’t miss any sessions I wanted to see, but the opportunities to meet the people I met aren’t available online. Here’s looking forward to Mix09 already.

Labels: , ,

Saturday, February 23, 2008

Don't hide behind a catch block

"Pragmatic Programmer tip #32: Crash Early."


I've been recently tasked with some refactoring items. Like any project that's longer than 8 weeks, you'll dig into some code and find yourself going, "What was I thinking with THIS?" Or, if the project's a bit longer, you wonder if you came up with this gem (and no, not a Ruby gem) or if somebody else on the team left this odor in the code.

The code smell of this particular blog post is the abuse of the try/catch block. I've stumbled across a few uses of the try/catch programatically, or worse, using an empty catch block to hide an issue you're not sure how to deal with.

Right off the top will go with the empty catch block. I encountered a few of these while refactoring, and had to wonder why we were hiding behind the empty catch block. Crash early, but when you crash sweep that under the rug and move on? That's not good. If you need a catch block, then isn't there something you should be catching? Take the following for an example:


That's a pretty simple little conversion function, with the dreaded empty catch block in there. It's there not because of the TryParse, which is going to give you a false if it fails its own try, but because applying ToString to a null object is going to throw an object error. Rather than the empty catch, why not a null check on o? Then you know what you're dealing with rather than not caring and returning 0 for anything you're not expecting. To me, this is a classic garbage in, garbage out scenario. You pass in a null or an object that can't be converted to a an int and you get a 0.

Next up was a bit of sheer genius, and throwing my hands up when dealing with nHibernate. Rather than find out what was going on, I resorted to using a try/catch procedurally to handle the issue. Here's a bit of code that shows my brilliant solution:


The issue there turned out to be that we were using the load method from nHibernate rather than the get, so I didn't have null object to check. I had an actual proxy object full of null properties. My solution, duck behind the catch block and make it bend to my will. If the load found something, the id check would pass and I'm doing an update. If the resulting object error from the property check threw, then I'm dealing with a new object, time for an insert.

In this case my ignorance of nHibernate's dealing with objects was the problem, but ignorance is no excuse. Using the try/catch in this manner was a hack with Paul Bunyan's ax. It got me moving foward, but was a bad solution.

The final empty catch falls in the same lines, where ignorance of what was available to us wasn't found until much later. This empty catch block example was saving us from a null reference error in a nullable data type in a data bind method.



Getting rid of this empty catch may have been the easiest of the three, because nullable data types carry a "HasValue" property that tells you, well, if they have a value. The refactored code looked like:


Using the HasValue property, we can refactor this one down to the always elegant ternary operator. We know what value we have or don't have and can cleanly bind our data to what's in this case a grid column.

If you're going to fail early, don't hide the failure. Figure out what it is and write the correct code for it. The try/catch is there to help you handle exceptions, not to hide them and move on.

Labels:

Thursday, February 21, 2008

Does Your Project Have a Junk Drawer?

Everybody's kitchen has a junk drawer. You know, the drawer where the tape, scissors, small jar of screws, various measuring items, and those clacker balls on a string that your mom is hiding from you. (Well, the ones my mom was hiding from me.) If you've got something in the house, and you're not sure where it goes, you fire it into the junk drawer. Oddly enough, you also find many useful items by looking in the junk drawer first when tackling something around the house.

However, I've found on a few recent projects that we're falling into the Junk Drawer model a bit. Look around your project, do you have file named "Utilities?" Maybe one called "GlobalMethods?" Or the very popular "ProjectHelper?" If so, there's a good chance you're throwing all kinds of things into the junk drawer. Could be a static class library, a little something in the App_Code directory in an ASP.Net project, or even a javascript file. Or, better yet, all three!

Now, don't misunderstand me, utility classes can be helpful. If you've got a series of string manipulations you need for a project, then a static stringUtils file makes perfect sense. Maybe a constants file for things that don't fit in an enum. As long as they are well defined and don't creep outside the scope of what you're trying to accomplish, I think they can be very helpful.

But, the junk drawer file that contains string manipulations, constants, get user name methods, some validation methods, a few odd conversion methods, a couple more string methods, and a few methods only called from your test project is not much of an asset to your project.

From a usage aspect, how do you tell other team members where your constants live? If they're scattered about your utility file, suddenly you're going to the same file for some string methods and your constants representing a product group. Or worse, your team gets so used to hitting your helper file that everything starts collecting there. Before you know it, you're looking at a maintenance nightmare with a couple thousand lines of code that should live in a number of more logical places.

Look around your projects, if you find a junk drawer take the time to refactor that thing out of there. Get all the files where they belong. You could end up with a utility file or two, but most likely you'll find you can move a number of methods right to the class that's using them because it's the only class that's using them. Turns out our friend YAGNI contributes many "global utility" functions to our projects.

Keep the junk drawer in your kitchen, though. Where else are you going to keep your SpongeBob commemorative Krusty Krab stamp?

Labels:

Tuesday, January 1, 2008

A little CodeMash love

Coming up in a few days will be CodeMash at the Kalahari Resort in Sandusky, OH. Having been to a few conferences, I consider this one a "don't miss." And here's why...

1. It's an indoor waterpark...nerds in speedos!

2. The collection of speakers and topics is second to none. This isn't your, "JAVA OR DIE!!!" meeting, just as its not, "Bill Gates cured my brother-in-law's limp," type show, either. It's a gathering of people passionate about their chosen field, wanting to share that passion, and get information on areas outside their comfort zone.

3. The Kalahari sells alcohol. Consider the alcohol induced war stories: "I had to deal with a five part composite primary key that allowed nulls!" It can only get better from there...

4. Keynoters that include Neal Ford (who also gave a keynote last year), Scott Hanselman, and Brian Goetz.

5. Breakout sessions with Neal Ford, Brian Goetz, Bruce Eckel, and Brian Prince! (Yes, I know, "one of these things is not like the others," but he has a direct impact on my paycheck.)

6. Conference food!!

If one or more of those six items hasn't piqued your interest then how about adding them all up: Brian Prince in a speedo delivering a presentation on Agile Development with a beer in one hand and a ham or turkey sandwich in the other.

Now that your interest has waned, fear not that won't happen. (And that direct impact on my paycheck is likely negative, now...)

Seriously, this is a good conference. If your looking for a "bang for your buck" type deal, then it's tough to beat CodeMash. I've been to pricier conferences and gotten much less out of them, mainly because much less was available. Last year's highlights for me were two breakout sessions with Scott Guthrie following his keynote and a session with Neal Ford on how to be a better overall developer. (Additionally, I had a strange urge to attend Burning Man...)

I came away last year being a little upset with myself for focusing too much in my .Net comfort zone, something I'm going to avoid this year. There are a couple of .Net sessions I want to see to learn some of the newer features, and one on Castle that I want to see. Beyond my comfort zone, there are a few Python sessions that I think I'll check-out. Oh, and I'll be in attendance at anything being presented by Neal Ford.

If you're planning on attending, look me up and say hi. I have a nullable composite key story to share with you. And, I don't own a speedo.

Yet.

Labels: , , , ,