Sunday, November 19, 2006

Tragic News

Tuesday morning I got some tragic news from my friends as Two Rivers Marketing. A plane that Two Rivers had chartered for a business trip crashed a few miles outside South Bend, Indiana. On the plane were five people, four of whom I had the privilege of working with during my six months at their company.

One of them was a very good friend of mine. Actually Eric Jacobs was much more than a friend. He was friend, a father, an advocate and a leader in our community.
When my wife and I moved back to Des Moines, Eric wanted me to come to Two Rivers. He was adamant about it. In a company that had been burnt by consultants in the past, he put his reputation on the line a recommended me to the senior partners. I was flattered and I tried like crazy to make sure that he didn't tarnish his reputation by recommending me. Eric was always there to encourage me to take on a new challenge. He believed in me and that helped me believe in myself.
As a leader in the community, Eric took the reigns of the Iowa .NET User Group and has been leading us since its inception. He always joked that since he couldn't code very well, he had to find another way to contribute. He came up with the idea of linking our members with leaders of other non-profit organizations and having us create websites for them. We would never be comfortable taking the credit himself, but he was the guy ordering the pizza every month. He was the guy sending the email reminding people about the meeting. He was the guy updating the website. He was the guy!
As a father and husband, Eric was my role model. I was always amazed at his ability to raise four boys with his wife, Heather. When my family and I went through a personal tragedy, Eric and his family had gone through something similar and he helped me through it. When my wife became pregnant with our first child, he let me know what to expect and made me less anxious about becoming a father.
I couple weeks ago, Eric called and wanted to get together for lunch. Unfortunately our schedules didn't mesh and we were never able to get together. I'm so sorry we couldn't see each other one last time. God bless you Eric, you touched the lives of many. You will be missed.

Saturday, October 28, 2006

Heartland Developers Conference 2006

I've been in Omaha for the last couple days at the Heartland Developers Conference. It was a great opportunity to catch up with a bunch of people.

It was nice to see Jeff Brand again. With his new responsibilites at Microsoft, Jeff doesn't make it down to Des Moines to hang out.

I also ran into Dru Sellers. I first met Dru a couple weeks earlier at Tulsa Tech Fest. Dru does PodcastStudio.net with Jeff Julian. Thursday afternoon after our presentation, Nick Parker and I sat down and did our first podcast with them. It will be released sometime over the next few months. It was a good interview and Dru and Jeff did a great job at keeping the conversation flowing.

We had a good time Thursday night after the first day of sessions. Nick Parker, Matt Ring, Mike Vesey, Ken Sherman, Dave Havenridge, Phil Stanislav, and Matt Milner had dinner at Omaha Prime in the Old Market. The steaks were great, but I'm still searching for a shrimp cocktail that compares to St. Elmo's in Indianapolis, IN.

It was fun and I can't wait to do it again next year!

Sunday, October 22, 2006

Agile Workspaces: Microsoft's Patterns & Practices Team

As most of you know, I'm very interested (read:fanatic) in agile development and have been disappointed with the lack of leadership from Microsoft in the agile space. However it appears that the Patterns & Practices team is starting to effect the development culture at Redmond.

In this video, Ed Jezierski and Peter Provost give a guided tour around their newly renovated agile development workspace.

Multiple sized reconfigurable team rooms - Lots of whiteboard space, each room has an overhead projector and multiple flat screen monitors at each workstation. Most of the team's daily work occurs in the team rooms, but every team member has an office space (shared or individual based on job function and preferences).

Escape Pods - Private small meeting rooms where developers can "escape" to make phone calls or hold small private meetings.

Modular interior office walls - The walls can be moved without a building permit.

Customer Room - Customers are top priority and have their own meeting room.

And the coolest....

Whiteboard Windows  - A white film sandwiched between two 8 ft. tall glass panels used to seperate rooms and can be used as whiteboards on both sides. Very cool and practical.

Has your team modified it's workspace to make the team more effective? Let me know, I love this stuff!

Sunday, September 3, 2006

Dear SourceSafe, I've found another

Dear SourceSafe,

We've been together so long and during that time we've been comfortable together, but not safe. During our time together, I've learned about your quirks. I admit then we first got together, I made some mistakes. I can't blame you for everything. But as we spent more time together, I discovered things about you that were harder to overlook. You don't have atomic check-in, you exclusively locked files, and it takes you forever to check-in, check-out, and create history reports. Through all this, I stuck with you.

Our relationship has gotten so bad that when you're not around, my friends and I make jokes about you. We use hurtful names for you like "Source Unsafe" or "Sour Safe". This isn't fair to you and I feel awful about it, because I know how insecure you are.

I have to be honest with you, I've been thinking about someone else, Subversion (SVN). Subversion is different from you and that's a little scary, a little exciting, but from the little amount of time that we've spent together...it just feels right. You know what I mean? I'm sorry, but never got that feeling with you.

I know we'll continue to run into each other for years to come and I'd like to remain friends, but I think it's best if we spent some time apart for awhile.

Sincerely,
Tim

P.S. If your interested in learning more about Subversion and how to install it on a Windows system. Please refer to these links.

If you're planning on using Apache Web Server, the SVN module doesn't work with the latest version (2.2.x). Use version 2.0.54 (at the time of this writting).

http://geekswithblogs.net/emanish/archive/2006/06/14/81905.aspx
http://blog.briankohrs.com/2005/09/20/guide-to-installing-the-subverison-http-module-on-windows/
http://www.subversionary.org/howto/setting-up-a-server-on-windows

Sunday, August 27, 2006

Object-Oriented Overview and Shared vs Instance Methods

In order to be a quality software developer today, you need to have an understanding of object oriented programming. However, if you want to be an Agile or Test Driven developer, you need a much stronger understanding. Why? Because when you're agile, you must be able to make changes quickly without affecting the system. In order to do that, you need to reduce (or eliminate) duplicate code and minimize coupling. OOP provides ways to do these things better than (in my opinion) procedural programming.
 
The purpose of this post is to provide a quick start to OOP. I hope you find it helpful.
 
Object-Oriented Overview
I found a simple and short tutorial to OOP concepts. It's in Java, but the concepts work for any OO language and it's short and simple.
 
 
So do you know the difference between a class (or Type) and an object?
 
A Class is the code that defines an object. An object is an instance of that class. If you "new up" a class, you get an object. It's that simple!
 
Shared/static vs. Instance Methods
Now that you understand the differences between a class and an object we can discuss the difference between Shared and Instance methods. Shared methods are at the class level, instance methods are on the object..err...instance. This means that each object that is created has it's own copy of the instance methods, but the shared function is used by all code in the application. I guess that is why the VB.NET team named them "shared".  Since shared methods are global, they can be helpful in some situations, for example, factory methods or singletons, but in general I avoid them for a few reasons:
 
You can't put shared methods on interfaces
Shared methods can cause multi-threading problems
They encourage procedural coding
 
Example:
For this example we'll use the good ol' Person Class.
 
        Public Class Person
    'Constructor
    Public Sub New(ByVal firstName As String, ByVal lastName As String)
        Me.FirstName = firstName
        Me.LastName = lastName
    End Sub
 
    'Fields
    Public FirstName As String
    Public LastName As String
 
    'Instance Method
    Public Function DisplayName() As String
        Return String.Format("{0}, {1}", Me.LastName, Me.FirstName)
    End Function
 
    'Shared Functions
    Public Shared Function Steve() As Person
        Return New Person("Steve", "Person")
    End Function
 
    Public Shared Function Tim() As Person
        Return New Person("Tim", "Person")
    End Function
 
End Class
In the Person class, FirstName and LastName fields are data stored within an object, and the DisplayName function describes a behavior for the class.
 
An object is an instance of a class. When "new up" a class we create a new instance (object) of the class. In this example, myPerson is an object, Person is a Class.

    Private myPerson As Person = New Person
 
To access a shared method, you don't need to "new up" an object. You can call it directly on the class. For example, Person.Steve() or Person.Tim(), work without "newing up" an object.
 
However, we don't have access to instance (non-shared) methods. You can't call Person.DisplayName(), but you can "new up" a person object and call DisplayName(), New Person().DisplayName.
 
In order to add to the confusion, VB.NET shows Shared methods on object variables. Calling myPerson.Steve() on an object instance works fine in VB.NET, but causes confusion. Please don't do this. I was hoping the VB.NET team would remove this "feature" in 2005, but it would have broken alot of systems.
 
I hope this wasn't too confusing, but understanding the basic concepts will help you develop better quality systems.
 

 

Monday, June 19, 2006

IIS looses changes after restart

Mike Phelps sent this tip around to our team a couple weeks ago. I've experienced this problem and never put all the pieces before. Not it makes perfect sense. Now if I coule get him to start his own blog ;)

IIS runs strictly from memory (i.e, the IIS metabase is loaded to RAM). If you make changes to IIS, they are only made in memory. The changes don't actually stick until IIS writes to disk. This can occur with safely shutting down windows, or restarting IIS without a timeout/clicking End Now.

Want to see for yourself?

  • 1) Go to properties of the DataPortal web site, and change the anonymous credentials to be your user.
    2) Close the IIS control panel.
    3) Start/Run iisreset /timeout:0

    • A)This forces IIS to shut down, without saving to disk. The wait time is used to persist to disk.

    4) Check the user you changed in #1. It will be back to the original user.

The point: Be wary of using the timeout option when you've made metabase changes.

Saturday, May 20, 2006

Agile Pep Talk

I had the opportunity to spend lunch with Matt Ring last week. He contacted me via my blog (Someone reads it!). He needed an "agile pep talk". He's on the right track and hopefully I gave him a couple practical tips he could use as soon as he got back to the office.

If you need an "agile pep talk" or have some general questions on how to implement agile practices on your projects, feel free to contact me and we can grab some lunch and chat. Or for those of you don't eat, you can find me at every Agile Iowa and Iowa .NET User Group meeting.

Thursday, May 18, 2006

Tracking Manual Tests with FitNesse

Our team has been working with FitNesse for a couple months and I believe we are getting over the learning "hump". A question came up today and I think we came up with a good solution and I wanted to share it with others who may be in transition period with FitNesse.

We aren't able to create FitNesse tests for all the functionality within the system so we do have some manual tests we need to verify are working. We need to track the manual tests within FitNesse so naturally we created a fixture!

Our "manual test" fixture contains 2 columns: Description and Passed. Description contains the manual test case and Passed contains the DATE the test passed. Entering the date allows us to track the last time the test passed. The fixture also takes a parameter for the number of days between manual tests.

!|Run Manual Tests Every|90|Days|
|Description|Passed|
|Do some manual test|5/18/2006|

When the fixture runs, it checks if the manual tests have passed within the configured time period. If not it will throw an error and provide visibly to aging manual test results.

Manual tests are not the ideal solution, however, by tracking the manual tests and their age we can provide a stop gap solution while teams are working to automate their user acceptance tests. It also gets the non-technical team members familiar with FitNesse syntax and hopefully prepare them to speak in the language of "FitNesse".

Have you or your team created a custom fixture to solve a problem? Please leave a comment and let me know.

NOTE: My blog is junk! If the human interface proof image doesn't show up, remove "#feedback" from the URL.

 

Sunday, April 2, 2006

Rocky's comments on Test Driven Development

There is fued of sorts between the TDD crowd and Rocky Lhotka. I guess someone forgot to warn Rocky about the TDD crowd. This is the same community that got Microsoft to remove an article about TDD and VS 2005 that was on MDSN...briefly.

Rocky made some comments during a recent episode of DotNetRocks and Jeffery Palermo had some comments to which Rocky responded.

This is very interesting to me because we are using Rocky's .NET Business framework and trying to apply TDD practices with limited success. I would post about them, but I'm afraid I'll get flamed by the TDD crew (kidding, will kinda).

Saturday, March 25, 2006

Great .NET Rocks Episodes

I just spent most of today working on my Microsoft SBA Add-in and listening/watching the latest couple episodes of .NET Rocks TV.

In these episodes Jean-Paul Boodhoo explains the Model-view-presenter (MVP) patterns, demonstrates NMock v2 framework, and builds a simple application using Test Driven Development/Design process. He does a great job explaining these concepts while developing a simple web form application. This is well worth your time if you have a couple hours to spare.

Thursday, February 23, 2006

COM+/Enterprise Services Configuration

COM+ application components can be configured two ways. They can be configured to run as library applications (in-process) or as a Server application (out of process). Having a library component isn’t a problem since it is running with the application domain as the calling application. However, getting configuration settings into a Server application can be a challenge. So much so, that I typically recommend running a COM+ applications as a library application.

So why is configuration so difficult for server application? Well I’m glad you asked. It’s because the server application is running in a process called dllhost.exe. This process lives in the {Windows}\System32\ directory. The .NET framework “automagically” loads the configuration file named dllhost.exe.config to get the configuration settings as long as it is in the System32 directory. This works great until you have 2 Server components that need different configuration settings. Do you see the problem? 2 Processes – 1 Configuration file. Plus most IT departments freak out (with good reason) when you need to deploy a file to the System32 directory.

If you’ve read this far you’ll find the purpose for this post. I had a colleague send me a link that documents how to use the new options in COM+ 1.5 to use the application directory. This is the only time I’ve heard about using the application.manifest and the application.config files.

http://staff.newtelligence.net/clemensv/PermaLink.aspx?guid=0615b3cc-0fbf-4cf5-9d49-ae95b50f7e8d

 

Tuesday, February 7, 2006

Database Triggers Rant

The reasons I don't like database triggers:

1.) They are very difficult to debug
2.) They are a type of "magic" within a system. "Magic" is when something happens when I run code that I don't see in the code.
3.) They are not intuitive.

I find that database triggers get used in an organization when one or more of these things happen:
1.) A DBA has been tasked with writing application code
2.) The code is more difficult to change than it is to debug a database trigger
3.) The deployment process for code is significantly longer than the deployment process for SQL changes

Wednesday, January 25, 2006

FitNesse: Using COM+ Enterprise Services to Manage Transactions

I’ve been working on integrating FitNesse and FIT into my current project. As with all automated testing, managing test data is a challenge.

To manage the data we have 3 options:

  1. Abstract the data from the system
  2. Restore the data to a known state before the tests run
  3. Create a reciprocating transaction. i.e. Each insert has a corresponding delete
  4. Rollback the test when it’s completed.

Option 1 is great, but it is difficult to abstract a system from the database especially if you are working with a pre-existing (legacy) system.

Option 2 is viable, but I hate having to do a database restore before I run a test suite.

I’m too lazy for option 3 and wouldn’t pick this option if there are a slew of user acceptance tests(UAT).

So I want to use option 4. Roy Osherove wrote a great article describing how to manage your unit tests using COM+ enterprise services and I have been using this method ever since, however, my tests use “Services Without Components” (SWC) included in COM+ 1.5.

I figured I could you the same concept with FitNesse! My solution is very simple. I created a ColumnFixture that can begin a transaction, commit a transaction, but most importantly rollback a transaction. The Fixture has 2 columns, Action and Result?. The Action column take one of three values: “begin”, “rollback”, and “commit”. The Result? column can be left blank. It will get populated with the System.EnterpriseServices.TransactionStatus after the Result() method is executed.

Now that I have this ColumnFixture, I created two pages: BeginTransaction and RollbackTransaction. These pages will be included before and after, any test fixtures that I want to run within a transaction. I prefer to use FitNesse’s !include widget, but you could also use the SetUp and TearDown pages.

Here's the code.

/// <summary>
    /// This class provides a simple interface to support COM+ transactions.
    /// </summary>
    public class TransactionFixture : ColumnFixture
    {
        public string Action = "begin";
        public string Result()
        {
            TransactionStatus retVal = TransactionStatus.NoTransaction;
            switch(Action.ToLower())
            {
                case "begin":
                    ServiceConfig config = new ServiceConfig();
                    config.Transaction = TransactionOption.RequiresNew;
                    ServiceDomain.Enter( config );
                    break;
                case "rollback":
                    
                    if( ContextUtil.IsInTransaction )
                    {
                        ContextUtil.SetAbort();
                    }
                    retVal = ServiceDomain.Leave();
                    break;
                case "commit":
                    
                    if( ContextUtil.IsInTransaction )
                    {
                        ContextUtil.SetComplete();
                    }
                    retVal = ServiceDomain.Leave();
                    break;
                default:
                    throw new ArgumentException("Invalid value", "Action");
            }

            return retVal.ToString();
        }
    }

Screenshot - Before


Screenshot - After


 

BeginTransaction Page

|!-GiffordConsulting.FitNesseAid.TransactionFixture-!|
|Action|Result?|
|begin||

RollbackTransaction Page

|!-GiffordConsulting.FitNesseAid.TransactionFixture-!|
|Action|Result?|
|rollback||

Putting it all together using import widget

!include BeginTransaction

|!-GiffordConsulting.FitNesseAid.SignonFixture-!|
|Username|Password|Save?|
|Tim|apassword|true|

!include RollbackTransaction