Wednesday, December 2, 2009

Wiring FxCop up to our build process

Earlier this week we decided to finally pull the trigger to have our automated build fail when the code violates the FxCop rules we use for code analysis. Previously we ran FxCop but rule violations didn't break the build. The code is a legacy application and so lots of rules were broken pretty much everywhere.

But yesterday I set all existing violations as exceptions so FxCop will basically ignore them. Today's effort was to figured out how to have the build break and still have the FxCop results appear in CruiseControl.NET (CC.NET). That second goal was a bit trickier than I thought it would be.

There were two changes that had to be made to enable this. First, was to have the NAnt script fail when FxCop finds a problem. This wasn't a big deal because FxCop only produces the XML output when there are violations. All I had to do was add a FAIL task that runs after the code analysis. If the output file exists we fail. This is what that task looks like:

<fail if="${file::exists(fxcop.output.path)}">FxCop rules violated, see FxCop Report for details.</fail>

Now the code analysis can build to break - awesome!

But doing this caused the FxCop Report in CC.NET to not display any results. This blog post by Leifw gave me the hint I needed to resolve the problem. Previously I had been doing my File Merge to get the FxCop results as part of the TASKS node of my CC.NET project configuration block. It turns out, though, File Merges done in the TASKS node won't occur if the build fails. I moved it to a PUBLISHERS node in the project and it all works ducky. That's because the PUBLISHERS node is processed even if the build fails. That looks like this:

<project name="MyWebGrocer.Gsa Trunk">
...
<publishers>
<merge>
<files>
<file>C:\BuildArtifacts\Project_Trunk\*.xml</file>
</files>
</merge>
<xmllogger />
</publishers>
</project>

Now if someone commits code that does something unforgivable - like neglecting to make a method static if it doesn't use any instance members - the build will break and they can check what the offense was via the CC.NET dashboard.

It's still a legacy application - but we won't be committing any more legacy code.

Wednesday, September 16, 2009

VT Code Camp 1: Summary

It's been nice to read some of the posts people have made about the VT code camp. The ones I've seen are by Bradley Holt, Chris Bowen, Dave Burke and Jim O'Neil. But I thought I would post my own summary of the first VT code camp.

First, I want to reiterate my appreciation to the many donors, speakers and volunteers who made the event the wild success that it was. You folks rock!

Code camp setup began around 7:30AM. This was only my second time at Kalkin Hall and was just as impressed with this location as I was when I had seen it the day before. It is just a wonderful space that suited our event to a "T." Again, many thanks to the UVM School of Business Administration for opening their doors to us. The setup team included Margot Schips, Julie Lerman, Laura Blood, Carl Lorenston, Bradley Holt and Dan Russell. (If I'm forgetting someone I apologize. Things were moved so fast and furious during the day I neglected to stop and take notes to do this properly.)

We got our only crisis out of the way early on Saturday when at around 7:35AM when we found out one of the rooms we were told we would be using turned out to be hosting a different all day event. After some frantic calls made by Margot we got it straightened out and were able to use an alternate room which worked just as well.

After that it was smooth sailing. We had a marvelous breakfast spread provided by Green Mountain Coffee Roasters. Lots of coffee, lots of pastries, lots of bagels and even lots of fruit. It was all yummy (and I speak from experience... lots of experience).

In typical VT style we began the welcoming remarks a few minutes behind schedule (what? you got someplace to be?). After thanking the donors, orienting everyone to the space and reviewing the day's schedule we turned our attendees loose. Plenty of positive energy and familiar faces.

The first two time slots went off without any projectors exploding (although it took a little bit to figure one of them out). Laura Blood was super-generous with her time and watched the registration desk. After that we broke for a lunch provided by MyWebGrocer. Lots of pizza and soda. Filled me right up. By this point my schedule started to even out. We had the swag organized, the registrations had started to die down and Julie and I had done the pizza run (complete with expert parking job). So I made the most of it and enjoyed the lunch break. It was great to spend a few minutes chatting with folks I knew and meeting folks I hadn't - plus the surreal experience of meeting in person folks I only knew from online.

After lunch we dove back into session. We moved the registration desk downstairs where it was manned by Dave Burke. Dave's one of the first people I met when I started to attend the .NET user groups and I always enjoy talking with him. Plus, when he adjusted my name tag for me it was the most action I had had all day.

Soon it was time for another snack break - this time courtesy of Microsoft. Sodas, brownies, and other tasty treats. Noshing and networking... good times.

We held the raffle during the last break. We gathered in one of the session rooms and used a random number generator to identify the winners. Julie also took a moment to extend a special thank you to Steve Andrews and Alison Gianotto who were the two speakers who travelled the farthest. After all the support our donors provided we ended up with nearly 30 prizes to give away - so we ran a little longer than expected. The final sessions started a little late, but everyone was still going strong. We volunteers set about cleaning up during the last session so we could get an early exit to a social gathering at the Windjammer. Special thanks to Chris Bowen and Microsoft for treating the speakers and volunteers so kindly.

I could keep writing about all the people I met and reconnected with. I might even do a post about the lessons learned that I hope to apply to the next code camp (yes, we intend to do this again). The whole experience was exciting, maddening and gratifying. I'll keep searching for posts, tweets and pictures tagged with VTCODECAMP to see what people thought. I hope you do, too. And join us at the next VT Code Camp!

Friday, September 11, 2009

Twas the night before code camp...

No more messing around - tomorrow is the first VT code camp. We've got everything as done as we can at this point. Excellent speakers/sessions lined up, a kickin' venue, a good team of volunteers and lots-o-swag. We've got over 100 people who have registered to attend, which far exceeds my expectations. I think I'm probably on the record somewhere stating that for our first code camp 50-70 would be a great turn out but talk of 100 was fantasy.

Looks like I was wrong. Happily, happily wrong.

Seriously, for this event to have that many people register is a huge testament to the development community in VT and the northeast in general (we've got participation from as far away as PA and NYC).

I'm super pleased with the support we've received from our donors, too. The UVM School of Business Administration has opened their doors to us for the venue. Green Mountain Coffee Roasters is covering breakfast, MyWebGrocer (my employer) is buying pizza and soda for lunch and Microsoft is providing an afternoon snack.

Chris Pels and the http://www.thedevcommunity.org/ site helped us by managing our registration and speaker abstract submissions which was HUGE.

We've a pile of swag to raffle and give away, too. Donors are:
It takes a lot of people to get an event like this off the ground and we have a great team. Super big thanks go to Bradley Holt, Carl Lorentson, Julie Lerman, Laura Blood, Margot Schips, Martin Stevanof, Matthew Weier O’Phinney and Rob Rohr who did a lot of heavy lifting to get us poised for a successful event tomorrow.

I also got some wonderful advice about organizing a code camp from Chris Bowen and Jim O'Neil our regional Microsoft development evangelists and also from Dennis Perlot and Supriyo "SB" Chatterje from the CT code camp. These four guys provided some good input and are all class acts.

Finally, I wouldn't even be able to be involved in this kind of community development if it weren't for my wife, Sue, who will be taking care of the kids while I'm at the code camp. So she gets a thank you, too.

So that's it. Everything is printed, the alarm is set and I'm really very, very excited to see how we do.

Wednesday, August 12, 2009

WebKit border radius and cascading styles don't always mix

Since starting the new job in January I've had to learn more about developing for the web than I ever have. One of the fascinating (and frustrating) aspects has been the way different browsers render the same code. The only web content I've written prior to this job was a very basic set of static pages for the Burlington Irish Heritage Festival and for an intranet web application where the company dictated which browser was to be used. But with the new gig I'm in the real world. That means every change I make needs to test against 4 or 5 browsers. And that's just on my development box, once it goes into QA the application is tested against over 20 different browser and OS combinations.

So I've started to familiarize myself with the various rendering engines used by the major browsers. One of the big ones is the WebKit open source engine. It serves as the rendering engine for some of the browsers I need to support; Safari on Windows and Google's Chrome. Recently we encountered a little WebKit specific gotcha that I wouldn't have expected. It has to do with a WebKit specific CSS attribute, -webkit-border-radius. It's a wonderful attribute that when set instructs the WebKit browsers to round the corners of an element. This post has a very good summary of the -webkit-border-radius attribute (and it's Mozilla equivilent, -moz-border-radius). The important point for this discussion is -webkit-border-radius is a shortcut declaration.

The problem we encountered had to do with how the -webkit-border-radius attribute behaved when used in a cascading style. The application on which I work has one style sheet defined for application wide default styles and then uses additional files to adjust the styles as needed. So, for example, the application default stylesheet may define a class like this:

.someRoundedThing { -webkit-border-radius: 4px; }

which will will cause a WebKit browser to round the corners of an element decorated with that class. Another style sheet could then declares following:

.someRoundedThing { -webkit-border-radius: 8px; }

If a page pulls in the application style sheet and then the alternate style sheet what should happen is the elements on that page which are decorated with the "someRoundedThing" class should be twice as rounded (again, only in WebKit browsers) than on a page where only the application default styles are included. But this wasn't working as expected.

In order for the page defined style to work we had to declare the alternate -webkit-border-radius value using the more verbose, four value declaration. Like this:

.someRoundedThing { -webkit-border-radius: 8px 8px 8px 8px; }

Declaring each corner's radius individually also worked:
.someRoundedThing {
-webkit-border-top-left-radius: 8px;
-webkit-border-top-right-radius: 8px;
-webkit-border-top-bottom-radius: 8px;
-webkit-border-top-bottom-radius: 8px;
}

While I'm not certain why this is going on, I assume it is related to the differences in implementation outlined in this post.

So while I like using the shortcut declarations for their terseness it appears they can lead to problems if your not careful.

Wednesday, July 15, 2009

Browser differences and jQuery, (oh, yes... they exist)

I've been doing more with jQuery lately and I can't say how much I'm enjoying it. The other day I was able to take an old JavaScript function that was over 20 lines long and refactor it down to 4 lines... sweet! And one of the nice benefits of using jQuery has been not having to worry about coding to specific browser variations. I did come across something recently, though, that is inconsistent between the browsers which I thought I would share.

It has to do with the way CSS attributes are retrieved for an element. Sometimes the .css() method will return different values for the same style definition (or no value at all) depending on the browser. I'm probably expecting too much of jQuery in terms of it's browser agnostic implementation - but I was honestly surprised. Consider the following HTML page:

<html>
<head>
<style type="text/css">
.ugly
{
background-color: #3A9F0E;
border: solid 1px #FFD800;
color: #fff;
-moz-border-radius: 10px;
blur: 1;
}
</style>
</head>
<body>
<h1 class="ugly">test</h1>
<div id="dvDisplay" />
</body>
</html>

A very basic but easy to grasp example. Ugly, but easy to grasp. There is a H1 tag which has the "ugly" class applied. The ugly class has some style definitions (some valid/some not... more on that shortly). There's an empty DIV tag, too. We're going to use that - just watch.

Now let's add a little JavaScript to illustrate my jQuery concerns. It's going in the head section and looks like this:

<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var message = "";
var property = ["border-color",
"border-bottom-color",
"-moz-border-radius",
"-moz-border-radius-bottomleft",
"background-color",
"font-weight",
"blur"];
property.sort();

for (var i = 0; i < property.length; i++) {
message += property[i];
message += " = '";
message += $(".ugly").css(property[i]);
message += "' <br />";
}

$("#dvDisplay").html(message);
});
</script>

The script is going to run when document.ready event fires, build an array of some CSS properties, sort them (because I'm too lazy to put them in the right order) and then loop over those properties to see how the jQuery .css method returns them. Note that the first and second pair of properties (border-color | border-bottom-color and -moz-border-radius | -moz-border-radius-bottomleft) are going after similar values - it's just one is more specific. Note, also, how the style declarations for the ugly class define each of these. Anyway, each property is appended to the output message which is then displayed in that DIV we left open (see, I told you we would use it).

So what does the output look like? Well, despite the browser agnostic behavior of jQuery it depends which browser you're in. Here are the results I saw (all browsers running on XP professional):

Firefox (3.0.11)
-moz-border-radius = ''
-moz-border-radius-bottomleft = '10px'
background-color = 'rgb(58, 159, 14)'
blur = ''
border-bottom-color = 'rgb(255, 216, 0)'
border-color = ''
font-weight = 'bold'

Internet Explorer 8 (both browser modes and all document modes)
-moz-border-radius = '10px'
-moz-border-radius-bottomleft = 'undefined'
background-color = '#3a9f0e'
blur = '1'
border-bottom-color = '#ffd800'
border-color = '#ffd800'
font-weight = '700'

Google Chrome (2.0.172.33)
-moz-border-radius = 'null'
-moz-border-radius-bottomleft = 'null'
background-color = 'rgb(58, 159, 14)'
blur = 'null'
border-bottom-color = 'rgb(255, 216, 0)'
border-color = ''
font-weight = 'bold'

Safari (3.2.2)
-moz-border-radius = 'null'
-moz-border-radius-bottomleft = 'null'
background-color = 'rgb(58, 159, 14)'
blur = 'null'
border-bottom-color = 'rgb(255, 216, 0)'
border-color = ''
font-weight = 'bold'

So, where are the differences? What strikes me is that even though the -moz-border-radius property is a Mozilla specific style, the output in Firefox is an empty string. Only the specific corner (-moz-border-radius-bottomleft) has the value now. I can only assume the style definition I'm using is a shortcut like the border definition. That would explain why Firefox, Chrome and Safari all return an empty string when checking border-color but can return border-bottom-color. IE will give me either.

The other interesting thing is that while IE8 doesn't know squat about the -moz-border-radius property can tell me what I wanted the value to be (but unsurprisingly, can't provide the specific corner value). So IE8 seems to be able to access the style declarations even if it doesn't do anything with them. This brings me to the declaration of the blur property. I wanted to know if it was possible to use CSS styles to store values to be retrieved later by jQuery to be applied to a drop shadow effect (rather than hard coding in the script). And it appears that this approach would work with IE8 but not the others. Which is how I identified the different behaviors of the browsers in jQuery.

So time for one last assumption: I really believe jQuery is doing its best to get the style attributes but the browsers must be preventing it from doing that. This does not dimish my appreciation of jQuery, but makes me recognize different browsers continue to plague web development.