Visit the Code Camp wiki to find out what Code Camps are happening near you – level 100
Visit the Code Camp wiki to find out what Code Camps are happening near you. There are several resources on this site:
Jeffrey Palermo, Microsoft MVP, Author, Speaker, Clear Measure Chief Architect, Azure DevOps Expert
Visit the Code Camp wiki to find out what Code Camps are happening near you. There are several resources on this site:
It’s an old interview, but timeless tips. Roy Osherove interviews Charlie Poole, who is the lead deverloper of the NUnit testing framework. This was a very interesting interview. Some points that stood out in my mind were:
I’d recommend a listen if you have time – I listen in the gym while working out.
Rob Caron has stated that the Guidelines for Test-Driven Development posts on MSDN is erroneous and will be corrected and that Microsoft has no intention of “redefining” TDD.
“We’re aware of the issue and are taking steps to rectify it. An error in a help topic is no different than a coding error – it’s a bug and we’re fixing it. Because of the process involved in publishing product documentation on MSDN, it takes a little bit of time to get updated files in place.“
So far the MSDN article has been rated by over 350 people and has an average rating of 1.13 on a scale from 1 to 9.
We’re having a vanpool from Austin to Houston on Nov 29th for the TDD workshop. We’ll meet at 4:30 and leaving promptly at 5AM for Houston. We’ll return around 9PM. Meet in the parking lot on the SW corner of 183 and Burnet. Here’s a satellite picture of the area.
http://maps.google.com/maps?ll=30.372135,-97.726994&spn=0.006446,0.009560&t=h&hl=en
Check out the AgileATX Yahoo group for more info.
Along with Resharper, the following class was created using a minimum number of keystrokes. Basically, I typed the names of the fields, and shortcut the rest. Consider the following class that I might want to have Xml documentation for:
public class Person
{
private string _firstName;
private string _lastName;
private string _phoneNumber;
private int _age;
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public string PhoneNumber
{
get { return _phoneNumber; }
set { _phoneNumber = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public Person(string firstName, string lastName, string phoneNumber, int age)
{
_firstName = firstName;
_lastName = lastName;
_phoneNumber = phoneNumber;
_age = age;
}
}
I could type all the Xml comments myself, but that would be considerable effort, and there isn’t anything special about this class. Most people could guess what this API does, so why not have a tool help with the Xml comments. I press CTRL + Q (my GhostDoc shortcut key) on each of my properties as well as the constructor, and I immediately have the following:
public class Person
{
private string _firstName;
private string _lastName;
private string _phoneNumber;
private int _age;
/// <summary>
/// Gets or sets the name of the last.
/// </summary>
/// <value>The name of the last.</value>
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
/// <summary>
/// Gets or sets the phone number.
/// </summary>
/// <value>The phone number.</value>
public string PhoneNumber
{
get { return _phoneNumber; }
set { _phoneNumber = value; }
}
/// <summary>
/// Gets or sets the age.
/// </summary>
/// <value>The age.</value>
public int Age
{
get { return _age; }
set { _age = value; }
}
/// <summary>
/// Gets or sets the name of the first.
/// </summary>
/// <value>The name of the first.</value>
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref=”Person”/> class.
/// </summary>
/// <param name=”firstName”>Name of the first.</param>
/// <param name=”lastName”>Name of the last.</param>
/// <param name=”phoneNumber”>The phone number.</param>
/// <param name=”age”>The age.</param>
public Person(string firstName, string lastName, string phoneNumber, int age)
{
_firstName = firstName;
_lastName = lastName;
_phoneNumber = phoneNumber;
_age = age;
}
}
Most of the work is done. There is no way GhostDoc can read my mind, so I might have to make a few adjustments to the comments, but they are minimal. Note that GhostDoc got confused on firstName and lastName, but that’s understandable. It hits the rest dead-on:
public class Person
{
private string _firstName;
private string _lastName;
private string _phoneNumber;
private int _age;
/// <summary>
/// Gets or sets the last name.
/// </summary>
/// <value>The last name.</value>
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
/// <summary>
/// Gets or sets the phone number.
/// </summary>
/// <value>The phone number.</value>
public string PhoneNumber
{
get { return _phoneNumber; }
set { _phoneNumber = value; }
}
/// <summary>
/// Gets or sets the age.
/// </summary>
/// <value>The age.</value>
public int Age
{
get { return _age; }
set { _age = value; }
}
/// <summary>
/// Gets or sets the first name.
/// </summary>
/// <value>The first name.</value>
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref=”Person”/> class.
/// </summary>
/// <param name=”firstName”>First name.</param>
/// <param name=”lastName”>Last name.</param>
/// <param name=”phoneNumber”>The phone number.</param>
/// <param name=”age”>The age.</param>
public Person(string firstName, string lastName, string phoneNumber, int age)
{
_firstName = firstName;
_lastName = lastName;
_phoneNumber = phoneNumber;
_age = age;
}
}
James Shore’s post about TDD is a must read.
I commend Microsoft for putting a big emphasis on automated testing. This is a big step for the software industry as a whole to embrace automated testing. The hardware industry has already discovered this and has a built-in self-test in almost every device. Likewise, software should have built-in self-tests to ensure that everything is working.
Microsoft has provided Unit Testing and Generating Source Code for Unit Test Frameworks Using Visual Studio 2005 Team System. In this article they describe how to unit test some code using Team System’s automated testing features. The problem is that what is actually described is integration testing. The tests call a BankAccount object and exercise some methods. There is no mocking(stubbing) of BankAccount’s dependencies, so this cannot be a unit test. If BankAccount actually works, it will have to communicate with some dependency unless this BankAccount keeps everything in memory.
Here are some recommended “unit tests” from the article:
Clearly, the assumption is made that a database is in the testing stack. This disqualifies the tests from being unit tests because they include a dependency and test more code than the “unit” – BankAccount component.
Automated testing is very important, but I must clarify some points in this article. The testing described here is “integration testing”. This kind of testing is important too, but it’s important to make the distinction. Unit tests test at the unit level and exclude a database. Unit tests are fast and can run on any workstation, not just a specially configured development environment.
Integration tests include multiple components of a system and make sure the pieces work together. In an integration test, it is appropriate to include multiple components including a database. For unit testing, including a database is not appropriate.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class WebForm1 : Page
{
protected DataGrid grid;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
grid.DataSource = this.GetSource();
this.BindGrid(0);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);
}
private string[] GetSource()
{
//just imagine how you would get/cache your data source.
string[] rows = new string[10000];
for (int i = 0; i < 10000; i++)
{
rows[i] = i.ToString();
}
return rows;
}
private void BindGrid(int currentPageIndex)
{
grid.DataSource = this.GetSource();
grid.CurrentPageIndex = currentPageIndex;
grid.DataBind();
}
private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)
{
this.BindGrid(e.NewPageIndex);
}
}
This works fine, but I have to click so many times to get to page
100 (10 clicks). I would like to be able to punch in a number and
jump to that page quickly. Let’s examine the following code and
how I created some controls to insert into the DataGrid paging
mechanism. The DataGrid doesn’t provide a PageTemplate, so we
have to do a bit of manual control arrangement. First, we’ll set
up how we would like it to work:
Let’s add our jump-to section:
<form id=”Form1″ method=”post” runat=”server”>
<asp:DataGrid AllowPaging=”True” PagerStyle-Mode=”NumericPages”
PagerStyle-PageButtonCount=”10″ ID=”grid” Runat=”server” />
<asp:Panel ID=”pagerEnhancement” Runat=”server”>
Jump to page:
<asp:TextBox id=jumpToText Runat=”server” Width=”25″></asp:TextBox>
<asp:Button id=jumpToButton Runat=”server” Text=”Go”></asp:Button>
</asp:Panel>
</form>
Notice that we just have a textbox and a button. We’ve added code to make this affect the DataGrid page:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class WebForm1 : Page
{
protected System.Web.UI.WebControls.TextBox jumpToText;
protected System.Web.UI.WebControls.Button jumpToButton;
protected System.Web.UI.WebControls.Panel pagerEnhancement;
protected DataGrid grid;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
grid.DataSource = this.GetSource();
this.BindGrid(0);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);
jumpToButton.Click +=new EventHandler(jumpToButton_Click);
}
private string[] GetSource()
{
//just imagine how you would get/cache your data source.
string[] rows = new string[10000];
for (int i = 0; i < 10000; i++)
{
rows[i] = i.ToString();
}
return rows;
}
private void BindGrid(int currentPageIndex)
{
grid.DataSource = this.GetSource();
grid.CurrentPageIndex = currentPageIndex;
grid.DataBind();
}
private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)
{
this.BindGrid(e.NewPageIndex);
}
private void jumpToButton_Click(object sender, System.EventArgs e)
{
int newPage = int.Parse(jumpToText.Text);
this.BindGrid(newPage – 1); //The DataGrid needs a page index, zero-based.
}
}
This works, but when I make my DataGrid pretty, I don’t want this
paging attachment left out. I need it to be inside the DataGrid,
so let’s write some code to move it from outside the DataGrid to right
next to the default pager:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
public class WebForm1 : Page
{
protected TextBox jumpToText;
protected Button jumpToButton;
protected Panel pagerEnhancement;
protected DataGrid grid;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
grid.DataSource = this.GetSource();
this.BindGrid(0);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
grid.PageIndexChanged += new DataGridPageChangedEventHandler(grid_PageIndexChanged);
jumpToButton.Click += new EventHandler(jumpToButton_Click);
grid.ItemCreated +=new DataGridItemEventHandler(grid_ItemCreated);
}
private string[] GetSource()
{
//just imagine how you would get/cache your data source.
string[] rows = new string[10000];
for (int i = 0; i < 10000; i++)
{
rows[i] = i.ToString();
}
return rows;
}
private void BindGrid(int currentPageIndex)
{
grid.DataSource = this.GetSource();
grid.CurrentPageIndex = currentPageIndex;
grid.DataBind();
}
private void grid_PageIndexChanged(object source, DataGridPageChangedEventArgs e)
{
this.BindGrid(e.NewPageIndex);
}
private void jumpToButton_Click(object sender, EventArgs e)
{
int newPage = int.Parse(jumpToText.Text);
this.BindGrid(newPage – 1); //The DataGrid needs a page index, zero-based.
}
private void grid_ItemCreated(object sender, DataGridItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Pager)
{
TableCell pagerCell = (TableCell) e.Item.Controls[0];// User Trace to view the
//control tree and found out how to grab the pager.;
pagerCell.Controls.Add(pagerEnhancement);
}
}
}
Notice how I am listening to the ItemCreated event of the DataGrid
and then moving the control when I’m on the Pager. I used the
Trace feature to observe the DataGrid control to see how the Pager was
laid out. The DataGrid is rendered as an Html table, so I just
needed to move my extra paging controls to the appropriate TableCell.
Obviously, I have simplified this example to demonstrate the basics
of adding to the default paging mechanism in the DataGrid. When I
use this technique, I make the appearance a lot more attractive, and I
also validate that an actual page number was entered into the
TextBox. After all, I have to gracefully handle whatever the user
types into that box.
At the Innotech conference, there was a TDD panel with Mary Poppendieck and 4 members of the local developer community (2 of them are my coworkers). Mary clarified that TDD is as old as software development itself. She relates that when she was coding assembly, she would create a testing framework to simulate the device she was writing for before she wrote any code. Then, every bit of code was written with automated tests. Here is a picture of the panel. From left to right there is Scott Bellware, Jeremy Miller, Jeff Smith, Bret Pettichord, and Mary Poppendieck.


This Wednesday, I attended the Innotech conference (no relation to Office Space), where I attended a session given by Mary Poppendieck, the author of Lean Software Development. She elaborated on some principal of making software development more lean. It starts with eliminating waste. At lunch, we convinced her to come out to a local burger place and had a great time discussing software and Agile over burgers. Coincidentally, every attendee is a member of the AgileATX practitioners group. Pictured, you’ll see Jeffrey Palermo (me), Blake Caraway, Steve Donie, Scott Bellware, Bret Pettichord, Phred Menyhert, Jeremy Miller, and Mary Poppendieck.
