Now here is a topic that has been beaten to death in other blog posts but it needs to be on this list.
If somehow you have missed the buzz around Test Driven Development (TDD) it is a great way to drive out the design of your software by writing a consumer of your code (the test) first. This way you design very intuitive and easy to read code. I must stress that TDD is primarily a design methodology NOT primarily a testing methodology. By using TDD you design good code and get unit tests as a side effect.
The key thing is to write a test before you write the implementation:
<Test()> _
Public Sub Save_Should_Assign_Customer_Id()
dim repository as ICustomerRepository = new CustomerRepository()
dim customer as new Customer
customer.FirstName="John"
cusotmer.LastName="Smith"
repository.Save(customer)
Assert.IsTrue(customer.ID <> 0)
End Sub
Now we have a test that does not even compile as the CustomerRepository does not even exist. So let us write a simple implementation:
Public Class CustomerRepository
Implements ICustomerRepository
Public Sub Save(customer as Customer) Implements ICustomerRepository.Save()
End Sub
End Class
Now we have code that compiles so we should run our test and ensure that the test fails. This is an important step as we want to ensure that the test will not pass if nothing happens in our code and also to ensure that our test is not improperly written.
Once the test fails we can go and add some code to make the test pass:
Public class CustomerRepository
implements ICustomerRepository
private customers as IList(of Customer) = new List(of Customer)
Public Sub Save(customer as Customer) Implements ICustomerRepository.Save()
dim maxId as integer
for each customer as customer in customers
if customer.customerId > maxId then maxId = customer.CustomerId
next
customer.CustomerId=maxId+1
customers.Add(Customer)
End Sub
End Class
When we re-run our test we should have a passing test. We can now go and refactor the code to be a bit more simplified. In this case I am going to take the maxId logic and extract it to its own method:
Public Class CustomerRepository
Implements ICustomerRepository
Private customers as IList(of Customer) = new List(of Customer)
Public Sub Save(customer as Customer) Implements ICustomerRepository.Save()
customer.CustomerId = GetMaxId() + 1
customers.Add(Customer)
End Sub
Private Function GetMaxId() as integer
dim maxId as integer
for each customer as customer in customers
if customer.customerId > maxId then maxId = customer.CustomerId
next
return maxId
End Function
End Class
Once this refactoring is done we run the tests again to ensure that our test still passes. This is TDD in its rawest form of Red->Green->Refactor.
Normally I would have written a test for GetMaxId() first to ensure that it behaves properly and then implemented that but I wanted to illustrate the red->green->refactor flow. We could add a test after to ensure GetMaxId() functions properly which is also fine.
There are so many sites, blogs, articles, and videos out there that I just wanted to give a quick overview of TDD. I did not believe people when they said that once you go down the TDD path that you never go back. Well they were right and it is now something I can not develop without.