Chris Fuller  

Source Control Best Practices (Part 2 of 2)

Posted by Chris Fuller
Wednesday, November 25, 2009

The primary purpose of source control is to share a common library of
source across developers and check files in and out of that common
library to enable collaboration.

Most application developers understand the importance of source
control. Unfortunately, I have had the unpleasant experience of having seen
first-hand the perils of not implementing source control correctly. I am sharing my story in the hope it may help you understand source control better and avoid the productivity drain that can occur when your team has to waste time fighting against source control rather than using source control as a valuable development tool.

On one project I was on, the team implemented improper source control.
I tried to help them understand that this was not the proper use of
source control software, but I was a late-comer to the project and
procedures were already established that the team was unwilling to change.

At any rate, I don't know where the team got this theory, but their concept
for source control was that every developer should have their own branch of
source code. The concept was that any one developer should be able to make
changes to any area of the system without holding up any of the other team
members. This was supposed to make our team more agile and efficient.

We ended up having the following results instead:

1. The primary purpose of source control was effectively negated.
Instead of checking in and out of a common library, we each checked
in and out of our own, isolated library.

2. Creating even an interim build was a monumental effort. Bringing our
code libraries together was a painstaking (and manual) task where we sifted
through which changes to apply from each developer. This process took
literally days to complete and often resulted in the introduction of bugs and
issues because it was so difficult to create a good version of the source.

3. Deja Vu all over again. After a common build was eventually completed,
each of us was required to create our own branch from the common source
and we would begin the exercise of being out of sync once again.

Let me give you a quick example:

I have taken a messy module with 800 lines of code
and paired it down to 200 lines of code, in doing so I eliminated 3 redundant
methods entirely. My colleague made a few small changes to his branch of the code,
and checked these changes into his branch. When we go to do the build, the
"build master," the poor developer stuck with bringing all of the various branches
together for our build, looks at both of our versions of source and sees that they
are different. How does this "build master" know which code is correct? She is under time pressure to get the build out, she sees that my version is missing 3 methods, so she decides that the source with the most code is the correct one, starts with that and picks and chooses the differences that appear to make sense to create the version used for the build. When the build is done, and I get the new "master" copy of the source, I look at this module and all of the clean-up work that I did was gone. I either have to blow it off, or do it again.

Each developer should be in control and have responsibility for making sure the
correct source is checked out and checked back in. This should not be left up to
a single developer at the end. No matter how good that developer is, it is
simply too daunting of a task, especially in crunch time, to have to go back
through and make judgment calls about other developer's code.

Needless to say, this process of creating a branch for each developer killed
our productivity, caused in-fighting amongst the project team, and absolutely
killed moral.

In the end, this project was delivered very late, with very few of the
promised features. I attribute most, (if not all), of this project's issues to improper source control procedures.

Please see my previous post for how to use source control and branching effectively.

Rick Sternquist  

Who are you following?

Posted by Rick Sternquist
Monday, November 23, 2009

I've found Twitter to be a great way to keep up with the latest and greatest information on Microsoft software development technologies. A lot of people at work ask me about Twitter and who I follow. Below is my list.

I'm grateful to all of them for the time and effort they put into Twitter and keeping us all informed as well as entertained.

Scott Guthrie @scottgu
Scott Hanselman @shanselman
Tim Heuer @timheuer
Brad Abrams @brada
Jeff Handley @jeffhandley
Nikhil Kothari @nikhilk
Phil Haack @haacked
Jesse Liberty @jesseliberty
Rocky Lhotka @rockylhotka
John Papa @john_papa
Jeff Atwood @codinghorror
Shawn Wildermuth @shawnwildermuth
Bill Reiss @billreiss
Silverlight News @silverlightnews


You can also follow Chicago Technologies at...

Rick Sternquist @rsternquist
Chris Fuller @cfullerchicago
Tom Cox @mrtomcox

Chris Fuller  

Top Lunch Places in the Loop

Posted by Chris Fuller
Saturday, November 21, 2009

I love working in Chicago, and especially in the Loop. My favorite activity is lunch. My friends and I work very hard to find the best lunch places.

Note: I am not including any place that is out of my daily lunch budget, so The Rivers and Lloyds, though excellent restaurants, get excluded because they are too pricey for me to go to without a special occasion. I also don't include any carry-out only places. We go to these sometimes too, but I prefer a sit down lunch, (SRO is my only exception to this rule).

My favorites list is made up of sit-down places I can go to with my friends, any day of the week. Here are my favorites:

1. Heaven on 7 (original)

Rating: ****

Cuisine: New Orleans

Location:
7th floor of the Garland Building -
111 N Wabash Ave (Wabash & Washington)

Specialty: Gumbo

Known for: New Orleans style atmosphere and food.





My Notes:
Heaven on 7 is located on the 7th floor of the office building near the corner of Wabash and Washington. Get there by 11:30 if you don't want to wait in line. The atmosphere is great, the service is good and the food is consistent and delicious.

Downside:
I've been told that if I ever go to New Orleans, I won't like this restaurant anymore. The facts are that I've never been to New Orleans, and I love the food and atmosphere at this favorite.


2. Poag Mahones

Rating: ***

Cuisine: Bar food

Location: 333 S Wells

Specialty: Hamburgers

Known for: Good food and great service






My notes: Great atmosphere, friendly wait staff and really good food. The Garbage Salad and Cheeseburger are my favorites. The Catfish Po' Boy is good too.

Downside: This place fills up fast. Get there by 11:30, or you might have to wait for a table.


3. Franklin Tap

Rating: ***

Cuisine: Bar food

Location: 325 S Franklin (just South of the Sears Tower)

Specialty: Iced Tea, Sweet Potato Fries

Known for: Good food, best Iced Tea in the loop and attractive waitresses






My Notes: This place has the best Iced Tea in the loop. They have very good service. This is a great place to meet friends and hang out.

Downside: A little pricey for what it is.


4. Amarit
Rating: ****

Location: 600 South Dearborn

Cuisine: Thai

Specialty: Thai Cuisine

Known for: Quiet, relaxed atmosphere, best Thai food in the loop and good service.



My Notes:
This is a great place to bring friends if you want to relax and talk. It's relatively quiet and is relaxing and comfortable. My favorites are Tom Yum Soup and Yum Tah Lai (Seafood Salad)

Downside:
This place is a bit of a hike - it's South of Congress on Dearborn, so you might even say it's not even in the loop, but it's close enough and the food is worth the walk if you like Thai and catch a nice day.


5. SRO (Standing Room Only)

Rating: ***

Cuisine: Sandwiches

Location: 610 S Dearborn St

Specialty: Chicken Sandwich

Known for: Chicken Sandwich





My Notes: The owners of this place are great guys - they've been at this location for over 10 years now. They do a great job.

Downside: Unless it's a nice day, the seating is extremely limited. It's a great carry out place, or if it's a nice day, you can sit near the sidewalk. Otherwise, forget it - too crowded to eat in there comfortably.


6. Boni Vino
Rating: ***
Cuisine: Italian

Specialty: Meatball Sandwich

Known for: Friendly wait staff and location





My Notes: The owners of this place is friendly and greets us at the door on the way in and thanks us on the way out. For some reason, we always get the same waitress. We either tip her too much or she likes us.

Downside: Boni Vino is great for lunch, but the atmosphere is nothing fancy.. It's a greasy spoon, family run Italian place.



7. Monk's Pub

Rating: ***

Location: 205 W Lake St

Cuisine: Bar food

Specialty: Hamburgers

Known for: Atmosphere and hamburgers





My Notes: This place is great, but it gets crowded, so get there early.

Downside: If you're not there by 11:30, be prepared to wait - this place fills up fast.


8. Venice Cafe

Rating: **

Cuisine: Italian

Location: 233 South Wacker

Specialty: Calzone


Known for: Red sauce - as good as you will find anywhere.




My Notes: The calzones are fantastic - that is the only thing I've ever had there. The way they do the soda there is really annoying. It's serve-yourself fountain and they charge way too much for it, making what was a good deal an average deal at best.

Downside: This place used to be located across the street from the Sears (Willis) Tower, which was a great location. It's now located in the basement of the Sears (Willis) Tower and the atmosphere is average at best.


9. Boston Blackies

Rating: ***

Cuisine: Bar food

Location: 120 S Riverside Plz

Specialty: Hamburgers, home-made chips

Known for: Nice, friendly atmosphere, large proportions.



My Notes:
Very large portions. If you're hungry, this is the place to go. Every time I go there, I leave feeling like I need a nap.

Downside:
This place is very popular, so get there by 11:30 or you will have to wait.


10. Marquette Inn
Rating: **

Cuisine: Comfort food

Location: 135 West Madison

Specialty: Gyros



Known for: 1970s decor, friendly wait staff



My Notes: This place is a classic. There used to be locations all over the loop. Several have closed, but there are still a few around.

Downside: There is nothing fancy about this place. It is what it is - a greasy spoon diner. If you want a classic, dependable place with good comofort food, Marquette Inn is for you.

Tom Cox  

Rain Delay in Ireland

Posted by Tom Cox
Friday, November 20, 2009

England and Ireland have been really socked with rain recently. Here is the view out my sister-in-law's back window. That lake used to be the backyard and adjacent fields. I guess they can turn it into a trout farm or something now. Let's hope the waters subside soon.


Tom Cox  

Goldmine API Access - Gm7s32.dll

Posted by Tom Cox
Tuesday, November 17, 2009

I was recently writing an interface between an order management system and Goldmine. I needed to access the Goldmine API to write new contact records to Goldmine whenever there was contact info in the order management system that did not exist in Goldmine. Despite my best efforts, it took me a while to find out how to access the Goldmine API from my C#.Net code. So here's what I learned...

You need to supply the method prototype to C#, this part was pretty straightforward and could be found in the (400+ page) API Guide:

[DllImport("Gm7s32.dll")]
public static extern int GMW_LoadAPI(string szSysDir, string szGoldDir, string szCommonDir, string szUser, string szPassword);

Notice the first 3 parameters are SysDir, GoldDir, and CommonDir. I had no idea what to use for these values. (The final 2 parameters: User and Password seemed easy enough!) After some painful searching and guesswork, I was able to log into the API and insert records. HOWEVER, I later found this quick bit of info that would have saved me hours...

Step 1: Log into Goldmine and select Help --> About


Step 2: Click the System button.


Step 3: Use the values in System Files, Goldmine Files, and Contact Files for your first 3 parameters.


Simple, eh?

Chris Fuller  

Source Control Best Practices (Part 1 of 2)

Posted by Chris Fuller

Source control is source control. Whether you use PVCS, StarTeam, SVN, ClearCase, SourceSafe, or Team Foundation, the fundamentals of checking in/checking out and
branching are the same. Most Source Control tools support branching in one way or another, and if they don't, you can do branching manually if you have to.

The first rule of branching is that you shouldn't branch if you don't need to.
Branching introduces complexity and overhead into your development environment, which is something to be avoided whenever possible. A rule of thumb for this would be: if you don't have a version of your software in production, you don't need to branch, (yet).

The purpose of branching is to allow you to fix production problems in the final released source while allowing new development to continue unimpeded.

For example....
I am on a team that is building a new CRM system. We put version 1.0 into production over the weekend, and, on Monday, we make some major overhauls to the security module. Several changes are checked into the main branch, but are not fully tested. On Wednesday, we find a security hole in the production version of the security module. Rather than fixing this on the main branch which has several
untested changes already checked in, we would get the code from the
production branch that we created over the weekend, patch, re-test,
deploy, and check these changes back into the branch.

After checking back in, we look at the differences between the production branch and
the main, development branch we are using and apply the same change we
just made in production to the development version.

Because you only need to patch and re-test a specific production
issue, you are able to isolate the change and thoroughly test and
release a specific change into production with confidence. This technique also allows you to move forward on new development initiatives with
confidence without worrying about how difficult it may be to roll-back
a change if you need to get back to the production version.

These concepts are not overly difficult or complex, but it is important to understand the correct way to branch, using the process and intent that source control allows.

If you do it correctly, it's easy and you will run a clean, efficient shop.
If you do it incorrectly, you will waste valuable time, effort and lose the good will and morale of your development team. Nothing is more
frustrating than working on a project where source control procedures
are erroneously applied. (I will write more on this subject in my next post).

Chris Fuller  

Landing the Big One

Posted by Chris Fuller
Sunday, November 15, 2009

During my recent family vacation to Puerto Vallarta, Mexico, I didn't catch H1N1, but I did land my first-ever fish. It was a Dorado, ("El Dorado"), or Mahi Mahi.

We caught it in the bay after launching near Mismaloya, just a few minutes South of downtown Puerto Vallarta.



It was an amazing experience - thanks to my brother-in-law, Jack McCabe, who is pictured here next to me with his catch. We had a great time and ate especially well that day!

Chris Fuller  

(503) Server Unavailable Error

Posted by Chris Fuller
Friday, November 6, 2009

We have an application that loads XHTML documents that are authored by
end-users into a database. This database is used by my client's
Intranet to deliver a combination of static and dynamic content to
employees through my client's Intranet.

I did not write the original application that loads this content in,
but I have been tasked with making modifications to it and supporting
it. This application ran fine for several months, but one day we
started getting, "The remote server returned an error: (503) Server
Unavailable", every time we loaded a document.

The code that was blowing up was pretty simple:

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(filePath);

filePath was the full path of the XHTML file, and we were blowing up
on the Load() method.

After some investigation, I determined that the DocType line in the
XHTML we were loading was causing the issue:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

I found that if I put the w3.org address into Internet Explorer, I got
the same (503) Server Unavailable error as our application was
getting. Strangely enough, I did not get this error from FireFox.
To resolve the error, I used FireFox to pull the
xhtml1-transitional.dtd file down locally from w3.org, and the 3
associated files:
xhtml-special.ent
xhtml-symbol.ent
xhtml-lat1.ent

I put these files onto our web server, (www.myclient.com/Intranet/XML)
and changed the DOCTYPE line in the XHTML content to this:

"http://www.myclient.com/Intranet/XML/xhtml1-transitional.dtd">

This resolved the issue.

So why were we getting this "The remote server returned an error:
(503) Server Unavailable" error?

It turns out that w3.org was blocking requests from my client's external web server. Here is
an explanation:

http://www.w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic